]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / libsecurity_pkcs12 / lib / pkcs12SafeBag.cpp
1 /*
2 * Copyright (c) 2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * pkcs12SafeBag.cpp : internal representation of various kinds
25 * of P12 SafeBags
26 */
27
28 #include "pkcs12SafeBag.h"
29 #include "pkcs12Debug.h"
30 #include "pkcs12Utils.h"
31 #include <string.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>
37
38 /*
39 * P12SafeBag, abstract superclass of all safe bags.
40 *
41 * Constructor for decoding. Attr may include friendlyName and localKeyId;
42 * It may also be empty or NULL.
43 */
44 P12SafeBag::P12SafeBag(
45 NSS_Attribute **attrs, // including friendlyName, etc.
46 SecNssCoder &coder)
47 : mBagAttrs(coder),
48 mCoder(coder)
49 {
50 mFriendlyName.Data = mLocalKeyId.Data = NULL;
51 mFriendlyName.Length = mLocalKeyId.Length = 0;
52
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);
58
59 if(nssCompareCssmData(&attr->attrType,
60 &CSSMOID_PKCS9_FriendlyName)) {
61 /*
62 * BMP string (UniCode). Spec says only one legal value.
63 */
64 if(numValues != 1) {
65 p12ErrorLog("FriendlyName with %u values\n", numValues);
66 /* but let's keep going if we can */
67 if(numValues == 0) {
68 P12_THROW_DECODE;
69 }
70 }
71 if(mCoder.decodeItem(*attr->attrValue[0],
72 kSecAsn1BMPStringTemplate, &mFriendlyName)) {
73 p12ErrorLog("***Error decoding FriendlyName string\n");
74 P12_THROW_DECODE;
75 }
76 }
77 else if(nssCompareCssmData(&attr->attrType,
78 &CSSMOID_PKCS9_LocalKeyId)) {
79 /*
80 * Octet string. Spec says only one legal value.
81 */
82 if(numValues != 1) {
83 p12ErrorLog("LocalKeyId with %u values\n", numValues);
84 /* but let's keep going if we can */
85 if(numValues == 0) {
86 P12_THROW_DECODE;
87 }
88 }
89 if(mCoder.decodeItem(*attr->attrValue[0],
90 kSecAsn1OctetStringTemplate, &mLocalKeyId)) {
91 p12ErrorLog("***Error decoding LocalKeyId\n");
92 P12_THROW_DECODE;
93 }
94 }
95 else {
96 /* others */
97 mBagAttrs.addAttr(*attr);
98 }
99 }
100 }
101
102 /*
103 * Constructor for encoding. All arguments except for the coder
104 * are optional.
105 */
106 P12SafeBag::P12SafeBag(
107 CFStringRef fname,
108 CFDataRef keyId,
109 P12BagAttrs *otherAttrs, // optional
110 SecNssCoder &coder)
111 : mBagAttrs(otherAttrs, coder),
112 mCoder(coder)
113 {
114 friendlyName(fname);
115 localKeyId(keyId);
116 }
117
118 P12SafeBag::~P12SafeBag()
119 {
120 /* nothing if everything we allocd is via mCoder */
121 }
122
123 /*
124 * Setters in CF terms, used when constructing prior
125 * to encoding.
126 */
127 void P12SafeBag::friendlyName(
128 CFStringRef fname)
129 {
130 CFIndex len = 0;
131
132 if(fname != NULL) {
133 len = CFStringGetLength(fname);
134 }
135 if(len == 0) {
136 mFriendlyName.Data = NULL;
137 mFriendlyName.Length = 0;
138 return;
139 }
140
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);
147 *cp++ = uc >> 8;
148 *cp++ = uc & 0xff;
149 }
150 }
151
152 void P12SafeBag::localKeyId(
153 CFDataRef keyId)
154 {
155 CFIndex len = 0;
156
157 if(keyId != NULL) {
158 len = CFDataGetLength(keyId);
159 }
160 if(len == 0) {
161 mLocalKeyId.Data = NULL;
162 mLocalKeyId.Length = 0;
163 return;
164 }
165 mCoder.allocItem(mLocalKeyId, len);
166 const UInt8 *cp = CFDataGetBytePtr(keyId);
167 memmove(mLocalKeyId.Data, cp, len);
168 }
169
170 /*
171 * Copy out all attrs in API form. All incoming ptrs
172 * are optional.
173 */
174 void P12SafeBag::copyAllAttrs(
175 CFStringRef *fName,
176 CFDataRef *keyId,
177 P12BagAttrs **bagAttrs)
178 {
179 if(fName) {
180 *fName = friendlyName();
181 }
182 if(keyId) {
183 *keyId = localKeyId();
184 }
185 if(bagAttrs) {
186 if(mBagAttrs.numAttrs()) {
187 /* make a copy of our bag attrs */
188 P12BagAttrs *attrs = new P12BagAttrs(&mBagAttrs, mCoder);
189 *bagAttrs = attrs;
190 }
191 else {
192 *bagAttrs = NULL;
193 }
194 }
195 }
196
197
198 /* getters in CF terms - result is created and returned */
199 CFStringRef CF_RETURNS_RETAINED P12SafeBag::friendlyName()
200 {
201 if(mFriendlyName.Data == NULL) {
202 /* not present, no error */
203 return NULL;
204 }
205 /* shouldn't have stored this if it's an odd number of bytes */
206 assert((mFriendlyName.Length & 1) == 0);
207
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;
212 UniChar *outp = uc;
213 while(inp < (mFriendlyName.Data + mFriendlyName.Length)) {
214 *outp = (((unsigned)inp[0]) << 8) | inp[1];
215 outp++;
216 inp += 2;
217 }
218 CFStringRef cstr = CFStringCreateWithCharacters(NULL, uc, strLen);
219 free(uc);
220 return cstr;
221 }
222
223 CFDataRef CF_RETURNS_RETAINED P12SafeBag::localKeyId()
224 {
225 if(mLocalKeyId.Data == NULL) {
226 /* not present, no error */
227 return NULL;
228 }
229 return CFDataCreate(NULL, (const UInt8 *)mLocalKeyId.Data,
230 mLocalKeyId.Length);
231 }
232
233 /*
234 * Get all attrs, including friendlyName and localKeyId,
235 * in preparation for encoding.
236 */
237 NSS_Attribute **P12SafeBag::getAllAttrs()
238 {
239 unsigned numAttrs = mBagAttrs.numAttrs();
240 if(mFriendlyName.Data) {
241 numAttrs++;
242 }
243 if(mLocalKeyId.Data) {
244 numAttrs++;
245 }
246 NSS_Attribute **attrs =
247 (NSS_Attribute **)p12NssNullArray(numAttrs, mCoder);
248 unsigned outDex=0;
249 for(unsigned i=0; i<mBagAttrs.numAttrs(); i++) {
250 attrs[outDex++] = mBagAttrs.getAttr(i);
251 }
252 if(mFriendlyName.Data) {
253 CSSM_DATA berName = {0, NULL};
254 if(mCoder.encodeItem(&mFriendlyName, kSecAsn1BMPStringTemplate,
255 berName)) {
256 p12ErrorLog("***Error encoding FriendlyName string\n");
257 P12_THROW_ENCODE;
258 }
259 attrs[outDex++] = makeAttr(CSSMOID_PKCS9_FriendlyName,
260 berName);
261 }
262 if(mLocalKeyId.Data) {
263 CSSM_DATA berName = {0, NULL};
264 if(mCoder.encodeItem(&mLocalKeyId, kSecAsn1OctetStringTemplate,
265 berName)) {
266 p12ErrorLog("***Error encoding LocalKeyId string\n");
267 P12_THROW_ENCODE;
268 }
269 attrs[outDex++] = makeAttr(CSSMOID_PKCS9_LocalKeyId,
270 berName);
271 }
272 assert(outDex == numAttrs);
273 return attrs;
274 }
275
276 /*
277 * Create an NSS_Attribute * for friendlyName or keyId
278 */
279 NSS_Attribute *P12SafeBag::makeAttr(
280 const CSSM_OID &attrId,
281 const CSSM_DATA &attrValue)
282 {
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]);
289 return attr;
290 }
291
292 /*
293 * Individual bag types
294 */
295
296 /* decode */
297 P12CertBag::P12CertBag(
298 NSS_P12_CertBagType certType, // CT_X509, CT_SDSI
299 CSSM_DATA &certData,
300 NSS_Attribute **attrs, // optional
301 SecNssCoder &coder)
302 : P12SafeBag(attrs, coder),
303 mCertType(certType),
304 mCertRef(NULL)
305 {
306 coder.allocCopyItem(certData, mCertData);
307 }
308
309 /* encode */
310 P12CertBag::P12CertBag(
311 NSS_P12_CertBagType certType, // CT_X509, CT_SDSI
312 CSSM_DATA &certData,
313 CFStringRef fname,
314 CFDataRef keyId,
315 P12BagAttrs *otherAttrs,
316 SecNssCoder &coder)
317 : P12SafeBag(fname, keyId, otherAttrs, coder),
318 mCertType(certType),
319 mCertRef(NULL)
320 {
321 coder.allocCopyItem(certData, mCertData);
322 }
323
324 P12CertBag::~P12CertBag()
325 {
326 if(mCertRef) {
327 CFRelease(mCertRef);
328 }
329 /* everything else we allocd is via mCoder */
330 }
331
332 /* convert to P12CertBag to SecCertificateRef */
333 SecCertificateRef P12CertBag::getSecCert()
334 {
335 if(mCertRef) {
336 CFRetain(mCertRef); /* a ref count for the caller */
337 return mCertRef;
338 }
339
340 /* lazy creation... */
341 CSSM_CERT_TYPE certType;
342 CSSM_CERT_ENCODING certEncoding;
343 switch(mCertType) {
344 case CT_X509:
345 certType = CSSM_CERT_X_509v3;
346 certEncoding = CSSM_CERT_ENCODING_DER;
347 break;
348 case CT_SDSI:
349 certType = CSSM_CERT_SDSIv1;
350 /* it's base64 encoded - no value for that in this enum */
351 certEncoding = CSSM_CERT_ENCODING_UNKNOWN;
352 break;
353 default:
354 /* shouldn't currently happen, but... */
355 certType = CSSM_CERT_UNKNOWN;
356 certEncoding = CSSM_CERT_ENCODING_UNKNOWN;
357 break;
358 }
359 OSStatus ortn = SecCertificateCreateFromData(
360 &mCertData,
361 certType,
362 certEncoding,
363 &mCertRef);
364 if(ortn) {
365 MacOSError::throwMe(ortn);
366 }
367
368 /* One ref count for us, one for the caller */
369 if (mCertRef) {
370 CFRetain(mCertRef);
371 }
372 return mCertRef;
373 }
374
375 P12CrlBag::P12CrlBag(
376 NSS_P12_CrlBagType crlType, // CRT_X509, only for now
377 CSSM_DATA &crlData,
378 NSS_Attribute **attrs, // optional
379 SecNssCoder &coder)
380 : P12SafeBag(attrs, coder),
381 mCrlType(crlType)
382 {
383 coder.allocCopyItem(crlData, mCrlData);
384 }
385
386 P12CrlBag::P12CrlBag(
387 NSS_P12_CrlBagType crlType, // CRT_X509, only for now
388 CFDataRef crlData,
389 CFStringRef fname,
390 CFDataRef keyId,
391 P12BagAttrs *otherAttrs,
392 SecNssCoder &coder)
393 : P12SafeBag(fname, keyId, otherAttrs, coder),
394 mCrlType(crlType)
395 {
396 coder.allocCopyItem(CFDataGetBytePtr(crlData),
397 CFDataGetLength(crlData), mCrlData);
398 }
399
400 P12CrlBag::~P12CrlBag()
401 {
402 /* nothing if everything we allocd is via mCoder */
403 }
404
405 /*
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.
409 */
410 P12KeyBag::P12KeyBag(
411 CSSM_KEY_PTR key,
412 CSSM_CSP_HANDLE cspHand,
413 NSS_Attribute **attrs, // optional
414 CSSM_DATA &labelData,
415 SecNssCoder &coder)
416 : P12SafeBag(attrs, coder),
417 mKey(key),
418 mCspHand(cspHand),
419 mKeyRef(NULL),
420 mWeOwnKey(true),
421 mPrivKeyCreds(NULL),
422 mDupKey(false)
423 {
424 setLabel(labelData);
425 }
426
427 /* for encode - app owns CSSM_KEY */
428 P12KeyBag::P12KeyBag(
429 const CSSM_KEY *key,
430 CSSM_CSP_HANDLE cspHand,
431 CFStringRef fname,
432 CFDataRef keyId,
433 P12BagAttrs *otherAttrs,
434 SecNssCoder &coder,
435 SecKeyRef keyRef /* = NULL */)
436
437 : P12SafeBag(fname, keyId, otherAttrs, coder),
438 mKey((CSSM_KEY_PTR)key),
439 mCspHand(cspHand),
440 mKeyRef(keyRef),
441 mWeOwnKey(false), // app giveth, app taketh away
442 mPrivKeyCreds(NULL),
443 mDupKey(false)
444 {
445 if(mKeyRef) {
446 CFRetain(mKeyRef);
447 /*
448 * Get creds associated with this key
449 */
450 OSStatus ortn = SecKeyGetCredentials(mKeyRef,
451 CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
452 kSecCredentialTypeDefault,
453 &mPrivKeyCreds);
454 if(ortn) {
455 p12LogCssmError("SecKeyGetCredentials", ortn);
456 MacOSError::throwMe(ortn);
457 }
458 }
459 mLabel.Data = NULL;
460 mLabel.Length = 0;
461 }
462
463
464 P12KeyBag::~P12KeyBag()
465 {
466 freeKey();
467 }
468
469 void P12KeyBag::setLabel(
470 const CSSM_DATA &newLabel)
471 {
472 mCoder.allocCopyItem(newLabel, mLabel);
473 }
474
475 /* reusable key setter */
476 void P12KeyBag::setKey(
477 CSSM_KEY_PTR cssmKey)
478 {
479 freeKey();
480 mKey = cssmKey;
481 }
482
483 void P12KeyBag::freeKey()
484 {
485 if(mWeOwnKey) {
486 assert(mKey != NULL);
487 assert(mCspHand != 0);
488 CSSM_FreeKey(mCspHand, NULL, mKey, CSSM_FALSE);
489 }
490 mKey = NULL;
491 if(mKeyRef) {
492 CFRelease(mKeyRef);
493 mKeyRef = NULL;
494 }
495 }
496
497 /*
498 * Others we don't implement
499 */
500 P12OpaqueBag::P12OpaqueBag(
501 const CSSM_OID &oid,
502 const CSSM_DATA &blob,
503 NSS_Attribute **attrs, // optional
504 SecNssCoder &coder)
505 : P12SafeBag(attrs, coder)
506 {
507 coder.allocCopyItem(oid, mOid);
508 coder.allocCopyItem(blob, mBlob);
509 }
510
511 P12OpaqueBag::P12OpaqueBag(
512 CFDataRef oid,
513 CFDataRef blob,
514 CFStringRef fname,
515 CFDataRef keyId,
516 P12BagAttrs *otherAttrs,
517 SecNssCoder &coder)
518 : P12SafeBag(fname, keyId, otherAttrs, coder)
519 {
520 coder.allocCopyItem(CFDataGetBytePtr(oid),
521 CFDataGetLength(oid), mOid);
522 coder.allocCopyItem(CFDataGetBytePtr(blob),
523 CFDataGetLength(blob), mBlob);
524 }
525
526 P12OpaqueBag::~P12OpaqueBag()
527 {
528 /* nothing if everything we allocd is via mCoder */
529 }
530