]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_pkcs12/lib/pkcs12Crypto.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_pkcs12 / lib / pkcs12Crypto.cpp
1 /*
2 * Copyright (c) 2003-2004,2011,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 /*
25 * pkc12Crypto.cpp - PKCS12-specific cyptrographic routines
26 */
27
28 #include "pkcs12Crypto.h"
29 #include "pkcs12Utils.h"
30 #include "pkcs12Debug.h"
31 #include <security_cdsa_utils/cuCdsaUtils.h>
32 #include <security_cdsa_utilities/cssmacl.h>
33 #include <security_keychain/Access.h>
34
35 /*
36 * Given appropriate P12-style parameters, cook up a CSSM_KEY.
37 * Caller MUST CSSM_FreeKey() when it's done with the key.
38 */
39 #define KEY_LABEL "p12 key"
40
41 CSSM_RETURN p12KeyGen(
42 CSSM_CSP_HANDLE cspHand,
43 CSSM_KEY &key,
44 bool isForEncr, // true: en/decrypt false: MAC
45 CSSM_ALGORITHMS keyAlg,
46 CSSM_ALGORITHMS pbeHashAlg, // actually must be SHA1 for now
47 uint32 keySizeInBits,
48 uint32 iterCount,
49 const CSSM_DATA &salt,
50 /* exactly one of the following two must be valid */
51 const CSSM_DATA *pwd, // unicode external representation
52 const CSSM_KEY *passKey,
53 CSSM_DATA &iv) // referent is optional
54 {
55 CSSM_RETURN crtn;
56 CSSM_CC_HANDLE ccHand;
57 CSSM_DATA dummyLabel;
58 CSSM_ACCESS_CREDENTIALS creds;
59
60 memset(&key, 0, sizeof(CSSM_KEY));
61 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
62
63 /* infer key derivation algorithm */
64 CSSM_ALGORITHMS deriveAlg = CSSM_ALGID_NONE;
65 if(pbeHashAlg != CSSM_ALGID_SHA1) {
66 return CSSMERR_CSP_INVALID_ALGORITHM;
67 }
68 if(isForEncr) {
69 /*
70 * FIXME - if this key is going to be used to wrap/unwrap a
71 * shrouded key bag, its usage will change accordingly...
72 */
73 deriveAlg = CSSM_ALGID_PKCS12_PBE_ENCR;
74 }
75 else {
76 deriveAlg = CSSM_ALGID_PKCS12_PBE_MAC;
77 }
78 CSSM_CRYPTO_DATA seed;
79 if(pwd) {
80 seed.Param = *pwd;
81 }
82 else {
83 seed.Param.Data = NULL;
84 seed.Param.Length = 0;
85 }
86 seed.Callback = NULL;
87 seed.CallerCtx = NULL;
88
89 crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
90 deriveAlg,
91 keyAlg,
92 keySizeInBits,
93 &creds,
94 passKey, // BaseKey
95 iterCount,
96 &salt,
97 &seed, // seed
98 &ccHand);
99 if(crtn) {
100 p12LogCssmError("CSSM_CSP_CreateDeriveKeyContext", crtn);
101 return crtn;
102 }
103
104 dummyLabel.Length = strlen(KEY_LABEL);
105 dummyLabel.Data = (uint8 *)KEY_LABEL;
106
107 /* KEYUSE_ANY - this is just an ephemeral session key */
108 crtn = CSSM_DeriveKey(ccHand,
109 &iv,
110 CSSM_KEYUSE_ANY,
111 CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE,
112 &dummyLabel,
113 NULL, // cred and acl
114 &key);
115 CSSM_DeleteContext(ccHand);
116 if(crtn) {
117 p12LogCssmError("CSSM_DeriveKey", crtn);
118 }
119 return crtn;
120 }
121
122 /*
123 * Decrypt (typically, an encrypted P7 ContentInfo contents)
124 */
125 CSSM_RETURN p12Decrypt(
126 CSSM_CSP_HANDLE cspHand,
127 const CSSM_DATA &cipherText,
128 CSSM_ALGORITHMS keyAlg,
129 CSSM_ALGORITHMS encrAlg,
130 CSSM_ALGORITHMS pbeHashAlg, // SHA1, MD5 only
131 uint32 keySizeInBits,
132 uint32 blockSizeInBytes, // for IV
133 CSSM_PADDING padding, // CSSM_PADDING_PKCS7, etc.
134 CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBCPadIV8, etc.
135 uint32 iterCount,
136 const CSSM_DATA &salt,
137 /* exactly one of the following two must be valid */
138 const CSSM_DATA *pwd, // unicode external representation
139 const CSSM_KEY *passKey,
140 SecNssCoder &coder, // for mallocing plainText
141 CSSM_DATA &plainText)
142 {
143 CSSM_RETURN crtn;
144 CSSM_KEY ckey;
145 CSSM_CC_HANDLE ccHand = 0;
146 CSSM_DATA ourPtext = {0, NULL};
147 CSSM_DATA remData = {0, NULL};
148
149 /* P12 style IV derivation, optional */
150 CSSM_DATA iv = {0, NULL};
151 CSSM_DATA_PTR ivPtr = NULL;
152 if(blockSizeInBytes) {
153 coder.allocItem(iv, blockSizeInBytes);
154 ivPtr = &iv;
155 }
156
157 /* P12 style key derivation */
158 crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
159 keySizeInBits, iterCount, salt, pwd, passKey, iv);
160 if(crtn) {
161 return crtn;
162 }
163 /* subsequent errors to errOut: */
164
165 /* CSSM context */
166 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
167 encrAlg,
168 mode,
169 NULL, // access cred
170 &ckey,
171 ivPtr, // InitVector, optional
172 padding,
173 NULL, // Params
174 &ccHand);
175 if(crtn) {
176 cuPrintError("CSSM_CSP_CreateSymmetricContext", crtn);
177 goto errOut;
178 }
179
180 /* go - CSP mallocs ptext and rem data */
181 CSSM_SIZE bytesDecrypted;
182 crtn = CSSM_DecryptData(ccHand,
183 &cipherText,
184 1,
185 &ourPtext,
186 1,
187 &bytesDecrypted,
188 &remData);
189 if(crtn) {
190 cuPrintError("CSSM_DecryptData", crtn);
191 }
192 else {
193 coder.allocCopyItem(ourPtext, plainText);
194 plainText.Length = bytesDecrypted;
195
196 /* plaintext copied into coder space; free the memory allocated
197 * by the CSP */
198 freeCssmMemory(cspHand, ourPtext.Data);
199 }
200 /* an artifact of CSPFullPLuginSession - this never contains
201 * valid data but sometimes gets mallocds */
202 if(remData.Data) {
203 freeCssmMemory(cspHand, remData.Data);
204 }
205 errOut:
206 if(ccHand) {
207 CSSM_DeleteContext(ccHand);
208 }
209 CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
210 return crtn;
211 }
212
213 /*
214 * Decrypt (typically, an encrypted P7 ContentInfo contents)
215 */
216 CSSM_RETURN p12Encrypt(
217 CSSM_CSP_HANDLE cspHand,
218 const CSSM_DATA &plainText,
219 CSSM_ALGORITHMS keyAlg,
220 CSSM_ALGORITHMS encrAlg,
221 CSSM_ALGORITHMS pbeHashAlg, // SHA1, MD5 only
222 uint32 keySizeInBits,
223 uint32 blockSizeInBytes, // for IV
224 CSSM_PADDING padding, // CSSM_PADDING_PKCS7, etc.
225 CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBCPadIV8, etc.
226 uint32 iterCount,
227 const CSSM_DATA &salt,
228 /* exactly one of the following two must be valid */
229 const CSSM_DATA *pwd, // unicode external representation
230 const CSSM_KEY *passKey,
231 SecNssCoder &coder, // for mallocing cipherText
232 CSSM_DATA &cipherText)
233 {
234 CSSM_RETURN crtn;
235 CSSM_KEY ckey;
236 CSSM_CC_HANDLE ccHand = 0;
237 CSSM_DATA ourCtext = {0, NULL};
238 CSSM_DATA remData = {0, NULL};
239
240 /* P12 style IV derivation, optional */
241 CSSM_DATA iv = {0, NULL};
242 CSSM_DATA_PTR ivPtr = NULL;
243 if(blockSizeInBytes) {
244 coder.allocItem(iv, blockSizeInBytes);
245 ivPtr = &iv;
246 }
247
248 /* P12 style key derivation */
249 crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
250 keySizeInBits, iterCount, salt, pwd, passKey, iv);
251 if(crtn) {
252 return crtn;
253 }
254 /* subsequent errors to errOut: */
255
256 /* CSSM context */
257 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
258 encrAlg,
259 mode,
260 NULL, // access cred
261 &ckey,
262 ivPtr, // InitVector, optional
263 padding,
264 NULL, // Params
265 &ccHand);
266 if(crtn) {
267 cuPrintError("CSSM_CSP_CreateSymmetricContext", crtn);
268 goto errOut;
269 }
270
271 /* go - CSP mallocs ctext and rem data */
272 CSSM_SIZE bytesEncrypted;
273 crtn = CSSM_EncryptData(ccHand,
274 &plainText,
275 1,
276 &ourCtext,
277 1,
278 &bytesEncrypted,
279 &remData);
280 if(crtn) {
281 cuPrintError("CSSM_DecryptData", crtn);
282 }
283 else {
284 coder.allocCopyItem(ourCtext, cipherText);
285 cipherText.Length = bytesEncrypted;
286
287 /* plaintext copied into coder space; free the memory allocated
288 * by the CSP */
289 freeCssmMemory(cspHand, ourCtext.Data);
290 }
291 /* an artifact of CSPFUllPLuginSession - this never contains
292 * valid data but sometimes gets mallocds */
293 if(remData.Data) {
294 freeCssmMemory(cspHand, remData.Data);
295 }
296 errOut:
297 if(ccHand) {
298 CSSM_DeleteContext(ccHand);
299 }
300 CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
301 return crtn;
302 }
303
304 /*
305 * Calculate the MAC for a PFX. Caller is either going compare
306 * the result against an existing PFX's MAC or drop the result into
307 * a newly created PFX.
308 */
309 CSSM_RETURN p12GenMac(
310 CSSM_CSP_HANDLE cspHand,
311 const CSSM_DATA &ptext, // e.g., NSS_P12_DecodedPFX.derAuthSaafe
312 CSSM_ALGORITHMS alg, // better be SHA1!
313 unsigned iterCount,
314 const CSSM_DATA &salt,
315 /* exactly one of the following two must be valid */
316 const CSSM_DATA *pwd, // unicode external representation
317 const CSSM_KEY *passKey,
318 SecNssCoder &coder, // for mallocing macData
319 CSSM_DATA &macData) // RETURNED
320 {
321 CSSM_RETURN crtn;
322 CSSM_CC_HANDLE ccHand = 0;
323
324 /* P12 style key derivation */
325 unsigned keySizeInBits;
326 CSSM_ALGORITHMS hmacAlg;
327 switch(alg) {
328 case CSSM_ALGID_SHA1:
329 keySizeInBits = 160;
330 hmacAlg = CSSM_ALGID_SHA1HMAC;
331 break;
332 case CSSM_ALGID_MD5:
333 /* not even sure if this is legal in p12 world... */
334 keySizeInBits = 128;
335 hmacAlg = CSSM_ALGID_MD5HMAC;
336 break;
337 default:
338 return CSSMERR_CSP_INVALID_ALGORITHM;
339 }
340 CSSM_KEY macKey;
341 CSSM_DATA iv = {0, NULL};
342 crtn = p12KeyGen(cspHand, macKey, false, hmacAlg, alg,
343 keySizeInBits, iterCount, salt, pwd, passKey, iv);
344 if(crtn) {
345 return crtn;
346 }
347 /* subsequent errors to errOut: */
348
349 /* prealloc the mac data */
350 coder.allocItem(macData, keySizeInBits / 8);
351 crtn = CSSM_CSP_CreateMacContext(cspHand, hmacAlg, &macKey, &ccHand);
352 if(crtn) {
353 cuPrintError("CSSM_CSP_CreateMacContext", crtn);
354 goto errOut;
355 }
356
357 crtn = CSSM_GenerateMac (ccHand, &ptext, 1, &macData);
358 if(crtn) {
359 cuPrintError("CSSM_GenerateMac", crtn);
360 }
361 errOut:
362 if(ccHand) {
363 CSSM_DeleteContext(ccHand);
364 }
365 CSSM_FreeKey(cspHand, NULL, &macKey, CSSM_FALSE);
366 return crtn;
367 }
368
369 /*
370 * Unwrap a shrouded key.
371 */
372 CSSM_RETURN p12UnwrapKey(
373 CSSM_CSP_HANDLE cspHand,
374 CSSM_DL_DB_HANDLE_PTR dlDbHand, // optional
375 int keyIsPermanent, // nonzero - store in DB
376 const CSSM_DATA &shroudedKeyBits,
377 CSSM_ALGORITHMS keyAlg, // of the unwrapping key
378 CSSM_ALGORITHMS encrAlg,
379 CSSM_ALGORITHMS pbeHashAlg, // SHA1, MD5 only
380 uint32 keySizeInBits,
381 uint32 blockSizeInBytes, // for IV
382 CSSM_PADDING padding, // CSSM_PADDING_PKCS7, etc.
383 CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBCPadIV8, etc.
384 uint32 iterCount,
385 const CSSM_DATA &salt,
386 const CSSM_DATA *pwd, // unicode external representation
387 const CSSM_KEY *passKey,
388 SecNssCoder &coder, // for mallocing privKey
389 const CSSM_DATA &labelData,
390 SecAccessRef access, // optional
391 bool noAcl,
392 CSSM_KEYUSE keyUsage,
393 CSSM_KEYATTR_FLAGS keyAttrs,
394
395 /*
396 * Result: a private key, reference format, optionaly stored
397 * in dlDbHand
398 */
399 CSSM_KEY_PTR &privKey)
400 {
401 CSSM_RETURN crtn;
402 CSSM_KEY ckey;
403 CSSM_CC_HANDLE ccHand = 0;
404 CSSM_KEY wrappedKey;
405 CSSM_KEY unwrappedKey;
406 CSSM_KEYHEADER &hdr = wrappedKey.KeyHeader;
407 CSSM_DATA descrData = {0, NULL}; // not used for PKCS8 wrap
408 CSSM_KEYATTR_FLAGS reqAttr = keyAttrs;
409
410 ResourceControlContext rcc;
411 ResourceControlContext *rccPtr = NULL;
412 Security::KeychainCore::Access::Maker maker;
413
414 /* P12 style IV derivation, optional */
415 CSSM_DATA iv = {0, NULL};
416 CSSM_DATA_PTR ivPtr = NULL;
417 if(blockSizeInBytes) {
418 coder.allocItem(iv, blockSizeInBytes);
419 ivPtr = &iv;
420 }
421
422 /* P12 style key derivation */
423 crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
424 keySizeInBits, iterCount, salt, pwd, passKey, iv);
425 if(crtn) {
426 return crtn;
427 }
428 /* subsequent errors to errOut: */
429
430 /* CSSM context */
431 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
432 encrAlg,
433 mode,
434 NULL, // access cred
435 &ckey,
436 ivPtr, // InitVector, optional
437 padding,
438 NULL, // Params
439 &ccHand);
440 if(crtn) {
441 p12LogCssmError("CSSM_CSP_CreateSymmetricContext", crtn);
442 goto errOut;
443 }
444 if(dlDbHand) {
445 crtn = p12AddContextAttribute(ccHand,
446 CSSM_ATTRIBUTE_DL_DB_HANDLE,
447 sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE),
448 dlDbHand);
449 if(crtn) {
450 p12LogCssmError("AddContextAttribute", crtn);
451 goto errOut;
452 }
453 }
454
455 /*
456 * Cook up minimal WrappedKey header fields
457 */
458 memset(&wrappedKey, 0, sizeof(CSSM_KEY));
459 memset(&unwrappedKey, 0, sizeof(CSSM_KEY));
460
461 hdr.HeaderVersion = CSSM_KEYHEADER_VERSION;
462 hdr.BlobType = CSSM_KEYBLOB_WRAPPED;
463 hdr.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
464
465 /*
466 * This one we do not know. The CSP will figure out the format
467 * of the unwrapped key after it decrypts the raw key material.
468 */
469 hdr.AlgorithmId = CSSM_ALGID_NONE;
470 hdr.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
471
472 /* also inferred by CSP */
473 hdr.LogicalKeySizeInBits = 0;
474 hdr.KeyAttr = CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_EXTRACTABLE;
475 hdr.KeyUsage = CSSM_KEYUSE_ANY;
476 hdr.WrapAlgorithmId = encrAlg;
477 hdr.WrapMode = mode;
478
479 if(dlDbHand && keyIsPermanent) {
480 reqAttr |= CSSM_KEYATTR_PERMANENT;
481 }
482
483 wrappedKey.KeyData = shroudedKeyBits;
484
485 if(!noAcl) {
486 // Create a Access::Maker for the initial owner of the private key.
487 memset(&rcc, 0, sizeof(rcc));
488 maker.initialOwner(rcc);
489 rccPtr = &rcc;
490 }
491
492 crtn = CSSM_UnwrapKey(ccHand,
493 NULL, // PublicKey
494 &wrappedKey,
495 keyUsage,
496 reqAttr,
497 &labelData,
498 rccPtr, // CredAndAclEntry
499 privKey,
500 &descrData); // required
501 if(crtn) {
502 p12LogCssmError("CSSM_UnwrapKey", crtn);
503 if(crtn == CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA) {
504 /* report in a keychain-friendly way */
505 crtn = errSecDuplicateItem;
506 }
507 }
508
509 // Finally fix the acl and owner of the private key to the
510 // specified access control settings.
511 if((crtn == CSSM_OK) && !noAcl) {
512 try {
513 CssmClient::KeyAclBearer bearer(
514 cspHand, *privKey, Allocator::standard());
515 SecPointer<KeychainCore::Access> initialAccess(access ?
516 KeychainCore::Access::required(access) : /* caller-supplied */
517 new KeychainCore::Access("privateKey")); /* default */
518 initialAccess->setAccess(bearer, maker);
519 }
520 catch (const CssmError &e) {
521 /* not implemented means we're talking to the CSP which does
522 * not implement ACLs */
523 if(e.error != CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED) {
524 crtn = e.error;
525 }
526 }
527 catch(...) {
528 p12ErrorLog("p12 exception on setAccess\n");
529 crtn = errSecAuthFailed; /* ??? */
530 }
531 }
532
533 errOut:
534 if(ccHand) {
535 CSSM_DeleteContext(ccHand);
536 }
537 CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
538 return crtn;
539 }
540
541 /*
542 * Wrap a private key, yielding shrouded key bits.
543 */
544 CSSM_RETURN p12WrapKey(
545 CSSM_CSP_HANDLE cspHand,
546 CSSM_KEY_PTR privKey,
547 const CSSM_ACCESS_CREDENTIALS *privKeyCreds,
548 CSSM_ALGORITHMS keyAlg, // of the unwrapping key
549 CSSM_ALGORITHMS encrAlg,
550 CSSM_ALGORITHMS pbeHashAlg, // SHA1, MD5 only
551 uint32 keySizeInBits,
552 uint32 blockSizeInBytes, // for IV
553 CSSM_PADDING padding, // CSSM_PADDING_PKCS7, etc.
554 CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBCPadIV8, etc.
555 uint32 iterCount,
556 const CSSM_DATA &salt,
557 const CSSM_DATA *pwd, // unicode external representation
558 const CSSM_KEY *passKey,
559 SecNssCoder &coder, // for mallocing keyBits
560 CSSM_DATA &shroudedKeyBits) // RETURNED
561 {
562 CSSM_RETURN crtn;
563 CSSM_KEY ckey;
564 CSSM_CC_HANDLE ccHand = 0;
565 CSSM_KEY wrappedKey;
566 CSSM_CONTEXT_ATTRIBUTE attr;
567 CSSM_DATA descrData = {0, NULL};
568 CSSM_ACCESS_CREDENTIALS creds;
569
570 /* key must be extractable */
571 if (!(privKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE)) {
572 return errSecDataNotAvailable;
573 }
574
575 if(privKeyCreds == NULL) {
576 /* i.e., key is from the bare CSP with no ACL support */
577 memset(&creds, 0, sizeof(creds));
578 privKeyCreds = &creds;
579 }
580
581 /* P12 style IV derivation, optional */
582 CSSM_DATA iv = {0, NULL};
583 CSSM_DATA_PTR ivPtr = NULL;
584 if(blockSizeInBytes) {
585 coder.allocItem(iv, blockSizeInBytes);
586 ivPtr = &iv;
587 }
588
589 /* P12 style key derivation */
590 crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
591 keySizeInBits, iterCount, salt, pwd, passKey, iv);
592 if(crtn) {
593 return crtn;
594 }
595 /* subsequent errors to errOut: */
596
597 /* CSSM context */
598 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
599 encrAlg,
600 mode,
601 NULL, // access cred
602 &ckey,
603 ivPtr, // InitVector, optional
604 padding,
605 NULL, // Params
606 &ccHand);
607 if(crtn) {
608 p12LogCssmError("CSSM_CSP_CreateSymmetricContext", crtn);
609 goto errOut;
610 }
611
612 memset(&wrappedKey, 0, sizeof(CSSM_KEY));
613
614 /* specify PKCS8 wrap format */
615 attr.AttributeType = CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT;
616 attr.AttributeLength = sizeof(uint32);
617 attr.Attribute.Uint32 = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
618 crtn = CSSM_UpdateContextAttributes(
619 ccHand,
620 1,
621 &attr);
622 if(crtn) {
623 p12LogCssmError("CSSM_UpdateContextAttributes", crtn);
624 goto errOut;
625 }
626
627 crtn = CSSM_WrapKey(ccHand,
628 privKeyCreds,
629 privKey,
630 &descrData, // DescriptiveData
631 &wrappedKey);
632 if(crtn) {
633 p12LogCssmError("CSSM_WrapKey", crtn);
634 }
635 else {
636 coder.allocCopyItem(wrappedKey.KeyData, shroudedKeyBits);
637
638 /* this was mallocd by CSP */
639 freeCssmMemory(cspHand, wrappedKey.KeyData.Data);
640 }
641 errOut:
642 if(ccHand) {
643 CSSM_DeleteContext(ccHand);
644 }
645 CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
646 return crtn;
647 }