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"
32 #include <security_utilities/simulatecrash_assert.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 CF_RETURNS_RETAINED
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 CF_RETURNS_RETAINED
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 */
375 P12CrlBag::P12CrlBag(
376 NSS_P12_CrlBagType crlType
, // CRT_X509, only for now
378 NSS_Attribute
**attrs
, // optional
380 : P12SafeBag(attrs
, coder
),
383 coder
.allocCopyItem(crlData
, mCrlData
);
386 P12CrlBag::P12CrlBag(
387 NSS_P12_CrlBagType crlType
, // CRT_X509, only for now
391 P12BagAttrs
*otherAttrs
,
393 : P12SafeBag(fname
, keyId
, otherAttrs
, coder
),
396 coder
.allocCopyItem(CFDataGetBytePtr(crlData
),
397 CFDataGetLength(crlData
), mCrlData
);
400 P12CrlBag::~P12CrlBag()
402 /* nothing if everything we allocd is via mCoder */
406 * For decode - both shrouded and plain.
407 * On decode, we own the key and will do the CSSM_FreeKey in
408 * our destructor. Caller owns the actual CSSM_KEY memory.
410 P12KeyBag::P12KeyBag(
412 CSSM_CSP_HANDLE cspHand
,
413 NSS_Attribute
**attrs
, // optional
414 CSSM_DATA
&labelData
,
416 : P12SafeBag(attrs
, coder
),
427 /* for encode - app owns CSSM_KEY */
428 P12KeyBag::P12KeyBag(
430 CSSM_CSP_HANDLE cspHand
,
433 P12BagAttrs
*otherAttrs
,
435 SecKeyRef keyRef
/* = NULL */)
437 : P12SafeBag(fname
, keyId
, otherAttrs
, coder
),
438 mKey((CSSM_KEY_PTR
)key
),
441 mWeOwnKey(false), // app giveth, app taketh away
448 * Get creds associated with this key
450 OSStatus ortn
= SecKeyGetCredentials(mKeyRef
,
451 CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
,
452 kSecCredentialTypeDefault
,
455 p12LogCssmError("SecKeyGetCredentials", ortn
);
456 MacOSError::throwMe(ortn
);
464 P12KeyBag::~P12KeyBag()
469 void P12KeyBag::setLabel(
470 const CSSM_DATA
&newLabel
)
472 mCoder
.allocCopyItem(newLabel
, mLabel
);
475 /* reusable key setter */
476 void P12KeyBag::setKey(
477 CSSM_KEY_PTR cssmKey
)
483 void P12KeyBag::freeKey()
486 assert(mKey
!= NULL
);
487 assert(mCspHand
!= 0);
488 CSSM_FreeKey(mCspHand
, NULL
, mKey
, CSSM_FALSE
);
498 * Others we don't implement
500 P12OpaqueBag::P12OpaqueBag(
502 const CSSM_DATA
&blob
,
503 NSS_Attribute
**attrs
, // optional
505 : P12SafeBag(attrs
, coder
)
507 coder
.allocCopyItem(oid
, mOid
);
508 coder
.allocCopyItem(blob
, mBlob
);
511 P12OpaqueBag::P12OpaqueBag(
516 P12BagAttrs
*otherAttrs
,
518 : P12SafeBag(fname
, keyId
, otherAttrs
, coder
)
520 coder
.allocCopyItem(CFDataGetBytePtr(oid
),
521 CFDataGetLength(oid
), mOid
);
522 coder
.allocCopyItem(CFDataGetBytePtr(blob
),
523 CFDataGetLength(blob
), mBlob
);
526 P12OpaqueBag::~P12OpaqueBag()
528 /* nothing if everything we allocd is via mCoder */