]> git.saurik.com Git - apple/security.git/blob - AppleCSP/AppleCSP/wrapKey.cpp
be08e27a535398744dc35226d1d2b8c1ac3c349a
[apple/security.git] / AppleCSP / AppleCSP / wrapKey.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // wrapKey.cpp - wrap/unwrap key functions for AppleCSPSession
21 //
22
23 /*
24 * Currently the Security Server wraps public keys when they're stored, so we have
25 * to allow this. We might not want to do this in the real world.
26 */
27 #define ALLOW_PUB_KEY_WRAP 1
28
29 #include "AppleCSPSession.h"
30 #include "AppleCSPUtils.h"
31 #ifdef USE_SNACC
32 #include "pkcs_7_8.h"
33 #endif
34 #include "cspdebugging.h"
35
36 /*
37 * Wrap key function. Used for two things:
38 *
39 * -- Encrypt and encode a private or session key for export to
40 * a foreign system or program. Any type of keys may be used
41 * for the unwrapped key and the wrapping (encrypting) key,
42 * as long as this CSP understands those keys. The context
43 * must be of class ALGCLASS_SYMMETRIC or ALGCLASS_ASYMMETRIC,
44 * matching the wrapping key.
45 *
46 * Private keys will be PKCS8 encoded; session keys will be
47 * PKCS7 encoded. Both input keys may be in raw or reference
48 * format. Wrapped key will have BlobType CSSM_KEYBLOB_WRAPPED.
49 *
50 * -- Convert a reference key to a RAW key (with no encrypting).
51 * This is called a NULL wrap; no wrapping key need be present in
52 * the context, but the context must be of class
53 * ALGCLASS_SYMMETRIC and algorithm ALGID_NONE.
54 *
55 * There are serious inconsistencies in the specification of wrap
56 * algorithms to be used in the various CDSA specs (c914.pdf,
57 * CSP Behavior spec) and between those specs and the PKCS standards
58 * PKCS7, PKCS8, RFC2630). Here is what this module implements:
59 *
60 * On a wrap key op, the caller can add a CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT
61 * attribute to the context to specify the wrapping algorithm to be used.
62 * If it's there, that's what we use if appropriate for the incoming key
63 * types. Otherwise we figure out a reasonable default from the incoming
64 * key types. The wrapped key always has the appropriate KeyHeader.Format
65 * field set indicating how it was wrapped. Defaults are shows below.
66 *
67 * The format CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM is used to indicate
68 * a modified CMS-style wrapping which is similar to that specified in
69 * RFC2630, with some modification.
70 *
71 * Default wrapping if none specified:
72 *
73 * UnwrappedKey type WrappingKey type Format
74 * ----------------- ---------------- -------------------------
75 * 3DES 3DES CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM
76 * any Other symmetric CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7
77 * any Other asymmetric CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8
78 */
79
80 void AppleCSPSession::WrapKey(
81 CSSM_CC_HANDLE CCHandle,
82 const Context &Context,
83 const AccessCredentials &AccessCred,
84 const CssmKey &UnwrappedKey,
85 const CssmData *DescriptiveData,
86 CssmKey &WrappedKey,
87 CSSM_PRIVILEGE Privilege)
88 {
89 CssmKey::Header &wrappedHdr = WrappedKey.header();
90 bool isNullWrap = false;
91 CssmKey *wrappingKey = NULL;
92 CSSM_KEYBLOB_FORMAT wrapFormat;
93
94 switch(UnwrappedKey.keyClass()) {
95 case CSSM_KEYCLASS_PUBLIC_KEY:
96 case CSSM_KEYCLASS_PRIVATE_KEY:
97 case CSSM_KEYCLASS_SESSION_KEY:
98 break;
99 default:
100 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
101 }
102
103 /* wrapping key only required for non-NULL wrap */
104 wrappingKey = Context.get<CssmKey>(CSSM_ATTRIBUTE_KEY);
105 if(wrappingKey == NULL) {
106 if((Context.algorithm() == CSSM_ALGID_NONE) &&
107 (Context.type() == CSSM_ALGCLASS_SYMMETRIC)) {
108 // NULL wrap, OK
109 isNullWrap = true;
110 }
111 else {
112 errorLog0("WrapKey: missing wrapping key\n");
113 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY);
114 }
115 }
116
117 /*
118 * Validate misc. params as best we can
119 */
120 if(isNullWrap) {
121 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE;
122 }
123 else {
124 /*
125 * Can only wrap session and private keys.
126 */
127 #if !ALLOW_PUB_KEY_WRAP
128 if(UnwrappedKey.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY) {
129 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
130 }
131 #endif /* ALLOW_PUB_KEY_WRAP */
132 cspValidateIntendedKeyUsage(&wrappingKey->KeyHeader, CSSM_KEYUSE_WRAP);
133
134 /*
135 * make sure wrapping key type matches context
136 */
137 CSSM_CONTEXT_TYPE wrapType;
138 switch(wrappingKey->KeyHeader.KeyClass) {
139 case CSSM_KEYCLASS_PUBLIC_KEY:
140 case CSSM_KEYCLASS_PRIVATE_KEY:
141 wrapType = CSSM_ALGCLASS_ASYMMETRIC;
142 break;
143 case CSSM_KEYCLASS_SESSION_KEY:
144 wrapType = CSSM_ALGCLASS_SYMMETRIC;
145 break;
146 default:
147 errorLog0("WrapKey: bad class of wrappingKey\n");
148 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
149 }
150 if(wrapType != Context.type()) {
151 errorLog0("WrapKey: mismatch wrappingKey/contextType\n");
152 CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT);
153 }
154 if(Context.algorithm() == CSSM_ALGID_NONE) {
155 errorLog0("WrapKey: null wrap alg, non-null key\n");
156 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
157 }
158
159 /*
160 * Get optional wrap format, set default per incoming keys
161 * Note: no such atrribute ==> 0 ==> FORMAT_NONE, which we
162 * take to mean "use the default".
163 */
164 wrapFormat = Context.getInt(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT);
165 if(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) {
166 /* figure out a default */
167 if(wrapType == CSSM_ALGCLASS_ASYMMETRIC) {
168 /* easy */
169 #ifdef USE_SNACC
170 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
171 #else
172 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
173 #endif
174 }
175 else {
176 CASSERT(wrapType == CSSM_ALGCLASS_SYMMETRIC);
177 if((wrappingKey->algorithm() == CSSM_ALGID_3DES_3KEY) &&
178 (UnwrappedKey.algorithm() == CSSM_ALGID_3DES_3KEY)) {
179 /* apple custom CMS */
180 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
181 }
182 else {
183 /* normal case for symmetric wrapping keys */
184 #ifdef USE_SNACC
185 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7;
186 #else
187 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
188 #endif
189 }
190 } /* default for symmetric wrapping key */
191 } /* no format present or FORMAT_NONE */
192 }
193
194 /* make sure we have a valid format here */
195 switch(wrapFormat) {
196 #if 0
197 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7:
198 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8:
199 #endif
200 case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM:
201 break;
202 case CSSM_KEYBLOB_WRAPPED_FORMAT_NONE:
203 if(isNullWrap) {
204 /* only time this is OK */
205 break;
206 }
207 /* else fall thru */
208 default:
209 dprintf1("KeyWrap: invalid wrapFormat (%d)\n", (int)wrapFormat);
210 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT);
211 }
212 /* get the blob to be wrappped */
213 CssmData rawBlob;
214 bool allocdRawBlob = false;
215 CSSM_KEYBLOB_FORMAT rawFormat;
216
217 switch(UnwrappedKey.blobType()) {
218 case CSSM_KEYBLOB_RAW:
219 /* trivial case */
220 rawBlob = CssmData::overlay(UnwrappedKey.KeyData);
221 rawFormat = UnwrappedKey.blobFormat();
222 break;
223 case CSSM_KEYBLOB_REFERENCE:
224 /* get binary key, then get blob from it */
225 {
226 BinaryKey &binKey = lookupRefKey(UnwrappedKey);
227 /*
228 * Special case for null wrap - prevent caller from obtaining
229 * clear bits if CSSM_KEYATTR_SENSITIVE or !CSSM_KEYATTR_EXTRACTABLE.
230 * Don't trust the caller's header; use the one in the BinaryKey.
231 */
232 if(isNullWrap) {
233 CSSM_KEYATTR_FLAGS keyAttr = binKey.mKeyHeader.KeyAttr;
234 if((keyAttr & CSSM_KEYATTR_SENSITIVE) ||
235 !(keyAttr & CSSM_KEYATTR_EXTRACTABLE)) {
236 CssmError::throwMe(
237 CSSMERR_CSP_INVALID_KEYATTR_MASK);
238 }
239 }
240 rawFormat = requestedKeyFormat(Context, UnwrappedKey);
241 binKey.generateKeyBlob(privAllocator,
242 rawBlob,
243 rawFormat);
244 }
245 allocdRawBlob = true; // remember - we need to free
246 break;
247
248 default:
249 errorLog0("WrapKey: bad unwrappedKey BlobType\n");
250 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
251 }
252
253 /*
254 * Prepare outgoing header.
255 */
256 const CssmKey::Header &unwrappedHdr = UnwrappedKey.header();
257 setKeyHeader(wrappedHdr,
258 plugin.myGuid(),
259 unwrappedHdr.algorithm(), // same as incoming
260 unwrappedHdr.keyClass(), // same as incoming
261 unwrappedHdr.KeyAttr,
262 unwrappedHdr.KeyUsage);
263 wrappedHdr.LogicalKeySizeInBits = unwrappedHdr.LogicalKeySizeInBits;
264 wrappedHdr.WrapAlgorithmId = Context.algorithm(); // true for null
265 // and non-Null
266 wrappedHdr.Format = wrapFormat;
267 if(isNullWrap) {
268 wrappedHdr.BlobType = CSSM_KEYBLOB_RAW;
269 }
270 else {
271 wrappedHdr.BlobType = CSSM_KEYBLOB_WRAPPED;
272 }
273
274 /*
275 * special case - break out here for custom Apple CMS
276 */
277 if(!isNullWrap && (wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM)) {
278 try {
279 WrapKeyCms(CCHandle,
280 Context,
281 AccessCred,
282 UnwrappedKey,
283 rawBlob,
284 allocdRawBlob,
285 DescriptiveData,
286 WrappedKey,
287 Privilege);
288 }
289 catch(...) {
290 if(allocdRawBlob) {
291 freeCssmData(rawBlob, privAllocator);
292 }
293 throw;
294 }
295 if(allocdRawBlob) {
296 freeCssmData(rawBlob, privAllocator);
297 }
298 return;
299 }
300
301
302 /*
303 * Generate wrapped blob. Careful, we need to conditionally free
304 * rawBlob on error.
305 */
306 CssmData encryptedBlob;
307 CssmData remData;
308 WrappedKey.KeyData.Data = NULL; // ignore possible incoming KeyData
309 WrappedKey.KeyData.Length = 0;
310
311 try {
312 if(isNullWrap) {
313 /* copy raw blob to caller's wrappedKey */
314 copyCssmData(rawBlob,
315 CssmData::overlay(WrappedKey.KeyData),
316 normAllocator);
317 wrappedHdr.Format = rawFormat;
318 }
319 #ifdef USE_SNACC
320 else {
321 /* encrypt rawBlob using caller's context, then encode to
322 * WrappedKey.KeyData */
323 uint32 bytesEncrypted;
324 EncryptData(CCHandle,
325 Context,
326 &rawBlob, // ClearBufs[]
327 1, // ClearBufCount
328 &encryptedBlob, // CipherBufs[],
329 1, // CipherBufCount,
330 bytesEncrypted,
331 remData,
332 Privilege);
333
334 // I'm not 100% sure about this....
335 assert(remData.Length == 0);
336 encryptedBlob.Length = bytesEncrypted;
337 if(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7) {
338 cspEncodePkcs7(Context.algorithm(),
339 Context.getInt(CSSM_ATTRIBUTE_MODE),
340 encryptedBlob,
341 CssmData::overlay(WrappedKey.KeyData),
342 normAllocator);
343 }
344 else {
345 CASSERT(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8);
346 cspEncodePkcs8(Context.algorithm(),
347 Context.getInt(CSSM_ATTRIBUTE_MODE),
348 encryptedBlob,
349 CssmData::overlay(WrappedKey.KeyData),
350 normAllocator);
351 }
352 wrappedHdr.BlobType = CSSM_KEYBLOB_WRAPPED;
353 // OK to be zero or not present
354 wrappedHdr.WrapMode = Context.getInt(
355 CSSM_ATTRIBUTE_MODE);
356 }
357 #endif
358 }
359 catch (...) {
360 errorLog0("WrapKey: EncryptData() threw exception\n");
361 if(allocdRawBlob) {
362 freeCssmData(rawBlob, privAllocator);
363 }
364 /* mallocd in EncryptData, thus normAllocator */
365 freeCssmData(encryptedBlob, normAllocator);
366 freeCssmData(remData,normAllocator);
367 throw;
368 }
369 if(allocdRawBlob) {
370 freeCssmData(rawBlob, privAllocator);
371 }
372 freeCssmData(encryptedBlob, normAllocator);
373 freeCssmData(remData, normAllocator);
374 }
375
376 /*
377 * Unwrap key function. Used for:
378 *
379 * -- Given key of BlobType CSSM_KEYBLOB_WRAPPED, decode and decrypt
380 * it, yielding a key in either raw or reference format. Unwrapping
381 * key may be either raw or reference. The context must match
382 * the unwrapping key (ALGCLASS_SYMMETRIC or ALGCLASS_ASYMMETRIC).
383 *
384 * Private keys are assumed to be PKCS8 encoded; session keys
385 * are assumed to be PKCS7 encoded.
386 *
387 * -- Convert a Raw key to a reference key (with no decrypting).
388 * This is called a NULL unwrap; no unwrapping key need be present in
389 * the context, but the context must be of class
390 * ALGCLASS_SYMMETRIC and algorithm ALGID_NONE.
391 */
392 void AppleCSPSession::UnwrapKey(
393 CSSM_CC_HANDLE CCHandle,
394 const Context &Context,
395 const CssmKey *PublicKey,
396 const CssmKey &WrappedKey,
397 uint32 KeyUsage,
398 uint32 KeyAttr,
399 const CssmData *KeyLabel,
400 const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry,
401 CssmKey &UnwrappedKey,
402 CssmData &DescriptiveData,
403 CSSM_PRIVILEGE Privilege)
404 {
405 bool isNullUnwrap = false;
406 CssmKey *unwrappingKey = NULL;
407 cspKeyType keyType; // CKT_Public, etc.
408 CSSM_KEYBLOB_FORMAT wrapFormat = WrappedKey.blobFormat();
409
410 /* obtain unwrapping key if present */
411 unwrappingKey = Context.get<CssmKey>(CSSM_ATTRIBUTE_KEY);
412 if(unwrappingKey == NULL) {
413 if((Context.algorithm() == CSSM_ALGID_NONE) &&
414 (Context.type() == CSSM_ALGCLASS_SYMMETRIC)) {
415 // NULL unwrap, OK
416 isNullUnwrap = true;
417 }
418 else {
419 errorLog0("UnwrapKey: missing wrapping key\n");
420 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY);
421 }
422 }
423
424 /*
425 * validate unwrappingKey
426 */
427 if(!isNullUnwrap) {
428 /* make sure unwrapping key type matches context */
429 CSSM_CONTEXT_TYPE unwrapType;
430 switch(unwrappingKey->KeyHeader.KeyClass) {
431 case CSSM_KEYCLASS_PUBLIC_KEY:
432 case CSSM_KEYCLASS_PRIVATE_KEY:
433 unwrapType = CSSM_ALGCLASS_ASYMMETRIC;
434 break;
435 case CSSM_KEYCLASS_SESSION_KEY:
436 unwrapType = CSSM_ALGCLASS_SYMMETRIC;
437 break;
438 default:
439 errorLog0("UnwrapKey: bad class of wrappingKey\n");
440 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
441 }
442 if(unwrapType != Context.type()) {
443 errorLog0("UnwrapKey: mismatch unwrappingKey/contextType\n");
444 CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT);
445 }
446 if(Context.algorithm() == CSSM_ALGID_NONE) {
447 errorLog0("UnwrapKey: null wrap alg, non-null key\n");
448 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
449 }
450 cspValidateIntendedKeyUsage(&unwrappingKey->KeyHeader, CSSM_KEYUSE_UNWRAP);
451 }
452
453 /* validate WrappedKey */
454 switch(WrappedKey.keyClass()) {
455 case CSSM_KEYCLASS_PUBLIC_KEY:
456 #if !ALLOW_PUB_KEY_WRAP
457 if(!isNullUnwrap) {
458 errorLog0("UnwrapKey: unwrap of public key illegal\n");
459 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
460 }
461 #endif /* ALLOW_PUB_KEY_WRAP */
462 keyType = CKT_Public;
463 break;
464 case CSSM_KEYCLASS_PRIVATE_KEY:
465 keyType = CKT_Private;
466 break;
467 case CSSM_KEYCLASS_SESSION_KEY:
468 keyType = CKT_Session;
469 break;
470 default:
471 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
472 }
473 if(isNullUnwrap) {
474 if(WrappedKey.blobType() != CSSM_KEYBLOB_RAW) {
475 errorLog0("UnwrapKey: expected raw blobType\n");
476 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
477 }
478 }
479 else {
480 if(WrappedKey.blobType() != CSSM_KEYBLOB_WRAPPED) {
481 errorLog0("UnwrapKey: expected wrapped blobType\n");
482 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
483 }
484 }
485
486 /* validate requested storage and usage */
487 cspKeyStorage keyStorage = cspParseKeyAttr(keyType, KeyAttr);
488 switch(keyStorage) {
489 case CKS_Ref:
490 case CKS_Data:
491 break; // OK
492 default:
493 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
494 }
495 cspValidateKeyUsageBits(keyType, KeyUsage);
496
497 /* prepare outgoing header */
498 CssmKey::Header &unwrappedHdr = UnwrappedKey.header();
499 const CssmKey::Header &wrappedHdr = WrappedKey.header();
500 setKeyHeader(unwrappedHdr,
501 plugin.myGuid(),
502 wrappedHdr.algorithm(), // same as incoming
503 wrappedHdr.keyClass(), // same as incoming
504 KeyAttr & ~KEY_ATTR_RETURN_MASK,
505 KeyUsage);
506 unwrappedHdr.LogicalKeySizeInBits = wrappedHdr.LogicalKeySizeInBits;
507 unwrappedHdr.KeyUsage = wrappedHdr.KeyUsage;
508 UnwrappedKey.KeyData.Data = NULL; // ignore possible incoming KeyData
509 UnwrappedKey.KeyData.Length = 0;
510
511 /* validate wrappedKey format */
512 if(!isNullUnwrap) {
513 switch(wrapFormat) {
514 #ifdef USE_SNACC
515 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7:
516 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8:
517 break;
518 #endif
519 case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM:
520 UnwrapKeyCms(CCHandle,
521 Context,
522 WrappedKey,
523 CredAndAclEntry,
524 UnwrappedKey,
525 DescriptiveData,
526 Privilege,
527 keyStorage);
528 return;
529 default:
530 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT);
531 }
532 }
533
534 /* Get key blob, decoding and decrypting if necessary */
535 CssmData decodedBlob;
536 CssmData remData;
537 try {
538 if(isNullUnwrap) {
539 /* simple copy of raw blob */
540 copyData(WrappedKey.KeyData,
541 UnwrappedKey.KeyData,
542 normAllocator);
543 unwrappedHdr.BlobType = CSSM_KEYBLOB_RAW;
544 unwrappedHdr.Format = wrapFormat;
545 }
546 #ifdef USE_SNACC
547 else {
548 /* decode wrapped blob, then decrypt to UnwrappedKey.KeyData
549 * using caller's context */
550 CSSM_KEYBLOB_FORMAT rawFormat;
551 if(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7) {
552 cspDecodePkcs7(WrappedKey,
553 decodedBlob,
554 rawFormat,
555 normAllocator);
556 }
557 else {
558 cspDecodePkcs8(WrappedKey,
559 decodedBlob,
560 rawFormat,
561 normAllocator);
562 }
563 uint32 bytesDecrypted;
564 CssmData *unwrapData =
565 CssmData::overlay(&UnwrappedKey.KeyData);
566
567 DecryptData(CCHandle,
568 Context,
569 &decodedBlob, // CipherBufs[],
570 1, // CipherBufCount,
571 unwrapData, // ClearBufs[]
572 1, // ClearBufCount
573 bytesDecrypted,
574 remData,
575 Privilege);
576
577 // I'm not 100% sure about this....
578 assert(remData.Length == 0);
579 UnwrappedKey.KeyData.Length = bytesDecrypted;
580 unwrappedHdr.BlobType = CSSM_KEYBLOB_RAW;
581 unwrappedHdr.Format = rawFormat;
582 }
583 #endif
584 }
585 catch (...) {
586 errorLog0("UnwrapKey: DecryptData() threw exception\n");
587 freeCssmData(decodedBlob, normAllocator);
588 freeCssmData(remData, normAllocator);
589 throw;
590 }
591 freeCssmData(decodedBlob, normAllocator);
592 freeCssmData(remData, normAllocator);
593
594 /*
595 * One more thing: cook up a BinaryKey if caller wants a
596 * reference key.
597 */
598 if(keyStorage == CKS_Ref) {
599 /*
600 * We have a key in raw format; convert to BinaryKey.
601 */
602 BinaryKey *binKey = NULL;
603 CSPKeyInfoProvider *provider = infoProvider(UnwrappedKey);
604 provider->CssmKeyToBinary(&binKey);
605 addRefKey(*binKey, UnwrappedKey);
606 delete provider;
607 }
608 }
609