2 * Copyright (c) 2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * pkcs12SafeBag.cpp : internal representation of various kinds
28 #include "pkcs12SafeBag.h"
29 #include "pkcs12Debug.h"
30 #include "pkcs12Utils.h"
33 #include <Security/Security.h>
34 #include <Security/SecKeyPriv.h>
35 #include <Security/SecAsn1Templates.h>
36 #include <security_asn1/nssUtils.h>
39 * P12SafeBag, abstract superclass of all safe bags.
41 * Constructor for decoding. Attr may include friendlyName and localKeyId;
42 * It may also be empty or NULL.
44 P12SafeBag::P12SafeBag(
45 NSS_Attribute
**attrs
, // including friendlyName, etc.
50 mFriendlyName
.Data
= mLocalKeyId
.Data
= NULL
;
51 mFriendlyName
.Length
= mLocalKeyId
.Length
= 0;
53 /* parse attrs into friendlyName, localKeyId, and generic attrs */
54 unsigned numAttrs
= nssArraySize((const void **)attrs
);
55 for(unsigned dex
=0; dex
<numAttrs
; dex
++) {
56 NSS_Attribute
*attr
= attrs
[dex
];
57 unsigned numValues
= nssArraySize((const void**)attr
->attrValue
);
59 if(nssCompareCssmData(&attr
->attrType
,
60 &CSSMOID_PKCS9_FriendlyName
)) {
62 * BMP string (UniCode). Spec says only one legal value.
65 p12ErrorLog("FriendlyName with %u values\n", numValues
);
66 /* but let's keep going if we can */
71 if(mCoder
.decodeItem(*attr
->attrValue
[0],
72 kSecAsn1BMPStringTemplate
, &mFriendlyName
)) {
73 p12ErrorLog("***Error decoding FriendlyName string\n");
77 else if(nssCompareCssmData(&attr
->attrType
,
78 &CSSMOID_PKCS9_LocalKeyId
)) {
80 * Octet string. Spec says only one legal value.
83 p12ErrorLog("LocalKeyId with %u values\n", numValues
);
84 /* but let's keep going if we can */
89 if(mCoder
.decodeItem(*attr
->attrValue
[0],
90 kSecAsn1OctetStringTemplate
, &mLocalKeyId
)) {
91 p12ErrorLog("***Error decoding LocalKeyId\n");
97 mBagAttrs
.addAttr(*attr
);
103 * Constructor for encoding. All arguments except for the coder
106 P12SafeBag::P12SafeBag(
109 P12BagAttrs
*otherAttrs
, // optional
111 : mBagAttrs(otherAttrs
, coder
),
118 P12SafeBag::~P12SafeBag()
120 /* nothing if everything we allocd is via mCoder */
124 * Setters in CF terms, used when constructing prior
127 void P12SafeBag::friendlyName(
133 len
= CFStringGetLength(fname
);
136 mFriendlyName
.Data
= NULL
;
137 mFriendlyName
.Length
= 0;
141 /* convert unicode to byte array */
142 unsigned flen
= (unsigned)(len
* sizeof(UniChar
));
143 mCoder
.allocItem(mFriendlyName
, flen
);
144 unsigned char *cp
= mFriendlyName
.Data
;
145 for(CFIndex dex
=0; dex
<len
; dex
++) {
146 UniChar uc
= CFStringGetCharacterAtIndex(fname
, dex
);
152 void P12SafeBag::localKeyId(
158 len
= CFDataGetLength(keyId
);
161 mLocalKeyId
.Data
= NULL
;
162 mLocalKeyId
.Length
= 0;
165 mCoder
.allocItem(mLocalKeyId
, len
);
166 const UInt8
*cp
= CFDataGetBytePtr(keyId
);
167 memmove(mLocalKeyId
.Data
, cp
, len
);
171 * Copy out all attrs in API form. All incoming ptrs
174 void P12SafeBag::copyAllAttrs(
177 P12BagAttrs
**bagAttrs
)
180 *fName
= friendlyName();
183 *keyId
= localKeyId();
186 if(mBagAttrs
.numAttrs()) {
187 /* make a copy of our bag attrs */
188 P12BagAttrs
*attrs
= new P12BagAttrs(&mBagAttrs
, mCoder
);
198 /* getters in CF terms - result is created and returned */
199 CFStringRef
P12SafeBag::friendlyName()
201 if(mFriendlyName
.Data
== NULL
) {
202 /* not present, no error */
205 /* shouldn't have stored this if it's an odd number of bytes */
206 assert((mFriendlyName
.Length
& 1) == 0);
208 /* convert byte array to unicode */
209 unsigned long strLen
= mFriendlyName
.Length
/ 2;
210 UniChar
*uc
= (UniChar
*)malloc(strLen
* sizeof(UniChar
));
211 const uint8
*inp
= mFriendlyName
.Data
;
213 while(inp
< (mFriendlyName
.Data
+ mFriendlyName
.Length
)) {
214 *outp
= (((unsigned)inp
[0]) << 8) | inp
[1];
218 CFStringRef cstr
= CFStringCreateWithCharacters(NULL
, uc
, strLen
);
223 CFDataRef
P12SafeBag::localKeyId()
225 if(mLocalKeyId
.Data
== NULL
) {
226 /* not present, no error */
229 return CFDataCreate(NULL
, (const UInt8
*)mLocalKeyId
.Data
,
234 * Get all attrs, including friendlyName and localKeyId,
235 * in preparation for encoding.
237 NSS_Attribute
**P12SafeBag::getAllAttrs()
239 unsigned numAttrs
= mBagAttrs
.numAttrs();
240 if(mFriendlyName
.Data
) {
243 if(mLocalKeyId
.Data
) {
246 NSS_Attribute
**attrs
=
247 (NSS_Attribute
**)p12NssNullArray(numAttrs
, mCoder
);
249 for(unsigned i
=0; i
<mBagAttrs
.numAttrs(); i
++) {
250 attrs
[outDex
++] = mBagAttrs
.getAttr(i
);
252 if(mFriendlyName
.Data
) {
253 CSSM_DATA berName
= {0, NULL
};
254 if(mCoder
.encodeItem(&mFriendlyName
, kSecAsn1BMPStringTemplate
,
256 p12ErrorLog("***Error encoding FriendlyName string\n");
259 attrs
[outDex
++] = makeAttr(CSSMOID_PKCS9_FriendlyName
,
262 if(mLocalKeyId
.Data
) {
263 CSSM_DATA berName
= {0, NULL
};
264 if(mCoder
.encodeItem(&mLocalKeyId
, kSecAsn1OctetStringTemplate
,
266 p12ErrorLog("***Error encoding LocalKeyId string\n");
269 attrs
[outDex
++] = makeAttr(CSSMOID_PKCS9_LocalKeyId
,
272 assert(outDex
== numAttrs
);
277 * Create an NSS_Attribute * for friendlyName or keyId
279 NSS_Attribute
*P12SafeBag::makeAttr(
280 const CSSM_OID
&attrId
,
281 const CSSM_DATA
&attrValue
)
283 NSS_Attribute
*attr
= mCoder
.mallocn
<NSS_Attribute
>();
284 mCoder
.allocCopyItem(attrId
, attr
->attrType
);
285 attr
->attrValue
= mCoder
.mallocn
<CSSM_DATA
*>(2);
286 attr
->attrValue
[0] = mCoder
.mallocn
<CSSM_DATA
>();
287 attr
->attrValue
[1] = NULL
;
288 mCoder
.allocCopyItem(attrValue
, *attr
->attrValue
[0]);
293 * Individual bag types
297 P12CertBag::P12CertBag(
298 NSS_P12_CertBagType certType
, // CT_X509, CT_SDSI
300 NSS_Attribute
**attrs
, // optional
302 : P12SafeBag(attrs
, coder
),
306 coder
.allocCopyItem(certData
, mCertData
);
310 P12CertBag::P12CertBag(
311 NSS_P12_CertBagType certType
, // CT_X509, CT_SDSI
315 P12BagAttrs
*otherAttrs
,
317 : P12SafeBag(fname
, keyId
, otherAttrs
, coder
),
321 coder
.allocCopyItem(certData
, mCertData
);
324 P12CertBag::~P12CertBag()
329 /* everything else we allocd is via mCoder */
332 /* convert to P12CertBag to SecCertificateRef */
333 SecCertificateRef
P12CertBag::getSecCert()
336 CFRetain(mCertRef
); /* a ref count for the caller */
340 /* lazy creation... */
341 CSSM_CERT_TYPE certType
;
342 CSSM_CERT_ENCODING certEncoding
;
345 certType
= CSSM_CERT_X_509v3
;
346 certEncoding
= CSSM_CERT_ENCODING_DER
;
349 certType
= CSSM_CERT_SDSIv1
;
350 /* it's base64 encoded - no value for that in this enum */
351 certEncoding
= CSSM_CERT_ENCODING_UNKNOWN
;
354 /* shouldn't currently happen, but... */
355 certType
= CSSM_CERT_UNKNOWN
;
356 certEncoding
= CSSM_CERT_ENCODING_UNKNOWN
;
359 OSStatus ortn
= SecCertificateCreateFromData(
365 MacOSError::throwMe(ortn
);
368 /* One ref count for us, one for the caller */
373 P12CrlBag::P12CrlBag(
374 NSS_P12_CrlBagType crlType
, // CRT_X509, only for now
376 NSS_Attribute
**attrs
, // optional
378 : P12SafeBag(attrs
, coder
),
381 coder
.allocCopyItem(crlData
, mCrlData
);
384 P12CrlBag::P12CrlBag(
385 NSS_P12_CrlBagType crlType
, // CRT_X509, only for now
389 P12BagAttrs
*otherAttrs
,
391 : P12SafeBag(fname
, keyId
, otherAttrs
, coder
),
394 coder
.allocCopyItem(CFDataGetBytePtr(crlData
),
395 CFDataGetLength(crlData
), mCrlData
);
398 P12CrlBag::~P12CrlBag()
400 /* nothing if everything we allocd is via mCoder */
404 * For decode - both shrouded and plain.
405 * On decode, we own the key and will do the CSSM_FreeKey in
406 * our destructor. Caller owns the actual CSSM_KEY memory.
408 P12KeyBag::P12KeyBag(
410 CSSM_CSP_HANDLE cspHand
,
411 NSS_Attribute
**attrs
, // optional
412 CSSM_DATA
&labelData
,
414 : P12SafeBag(attrs
, coder
),
425 /* for encode - app owns CSSM_KEY */
426 P12KeyBag::P12KeyBag(
428 CSSM_CSP_HANDLE cspHand
,
431 P12BagAttrs
*otherAttrs
,
433 SecKeyRef keyRef
/* = NULL */)
435 : P12SafeBag(fname
, keyId
, otherAttrs
, coder
),
436 mKey((CSSM_KEY_PTR
)key
),
439 mWeOwnKey(false), // app giveth, app taketh away
446 * Get creds associated with this key
448 OSStatus ortn
= SecKeyGetCredentials(mKeyRef
,
449 CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
,
450 kSecCredentialTypeDefault
,
453 p12LogCssmError("SecKeyGetCredentials", ortn
);
454 MacOSError::throwMe(ortn
);
462 P12KeyBag::~P12KeyBag()
467 void P12KeyBag::setLabel(
468 const CSSM_DATA
&newLabel
)
470 mCoder
.allocCopyItem(newLabel
, mLabel
);
473 /* reusable key setter */
474 void P12KeyBag::setKey(
475 CSSM_KEY_PTR cssmKey
)
481 void P12KeyBag::freeKey()
484 assert(mKey
!= NULL
);
485 assert(mCspHand
!= 0);
486 CSSM_FreeKey(mCspHand
, NULL
, mKey
, CSSM_FALSE
);
496 * Others we don't implement
498 P12OpaqueBag::P12OpaqueBag(
500 const CSSM_DATA
&blob
,
501 NSS_Attribute
**attrs
, // optional
503 : P12SafeBag(attrs
, coder
)
505 coder
.allocCopyItem(oid
, mOid
);
506 coder
.allocCopyItem(blob
, mBlob
);
509 P12OpaqueBag::P12OpaqueBag(
514 P12BagAttrs
*otherAttrs
,
516 : P12SafeBag(fname
, keyId
, otherAttrs
, coder
)
518 coder
.allocCopyItem(CFDataGetBytePtr(oid
),
519 CFDataGetLength(oid
), mOid
);
520 coder
.allocCopyItem(CFDataGetBytePtr(blob
),
521 CFDataGetLength(blob
), mBlob
);
524 P12OpaqueBag::~P12OpaqueBag()
526 /* nothing if everything we allocd is via mCoder */