2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // wrapKey.cpp - wrap/unwrap key functions for AppleCSPSession
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.
27 #define ALLOW_PUB_KEY_WRAP 1
29 #include "AppleCSPSession.h"
30 #include "AppleCSPUtils.h"
31 #include "AppleCSPKeys.h"
33 #include "cspdebugging.h"
36 * Wrap key function. Used for two things:
38 * -- Encrypt and encode a private or session key for export to
39 * a foreign system or program. Any type of keys may be used
40 * for the unwrapped key and the wrapping (encrypting) key,
41 * as long as this CSP understands those keys. The context
42 * must be of class ALGCLASS_SYMMETRIC or ALGCLASS_ASYMMETRIC,
43 * matching the wrapping key.
45 * In the absence of an explicit CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT
46 * attribute, private keys will be PKCS8 wrapped; session keys will be
47 * PKCS7 wrapped. Both input keys may be in raw or reference
48 * format. Wrapped key will have BlobType CSSM_KEYBLOB_WRAPPED.
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.
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:
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.
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.
71 * Default wrapping if none specified based on ther unwrapped key as
74 * UnwrappedKey Wrap format
75 * ------------ -----------
78 * FEE private APPLE_CUSTOM
82 void AppleCSPSession::WrapKey(
83 CSSM_CC_HANDLE CCHandle
,
84 const Context
&Context
,
85 const AccessCredentials
&AccessCred
,
86 const CssmKey
&UnwrappedKey
,
87 const CssmData
*DescriptiveData
,
89 CSSM_PRIVILEGE Privilege
)
91 CssmKey::Header
&wrappedHdr
= WrappedKey
.header();
92 bool isNullWrap
= false;
93 CssmKey
*wrappingKey
= NULL
;
94 CSSM_KEYBLOB_FORMAT wrapFormat
;
96 switch(UnwrappedKey
.keyClass()) {
97 case CSSM_KEYCLASS_PUBLIC_KEY
:
98 case CSSM_KEYCLASS_PRIVATE_KEY
:
99 case CSSM_KEYCLASS_SESSION_KEY
:
102 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
105 /* wrapping key only required for non-NULL wrap */
106 wrappingKey
= Context
.get
<CssmKey
>(CSSM_ATTRIBUTE_KEY
);
107 if(wrappingKey
== NULL
) {
108 if((Context
.algorithm() == CSSM_ALGID_NONE
) &&
109 (Context
.type() == CSSM_ALGCLASS_SYMMETRIC
)) {
114 errorLog0("WrapKey: missing wrapping key\n");
115 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY
);
120 * Validate misc. params as best we can
123 wrapFormat
= CSSM_KEYBLOB_WRAPPED_FORMAT_NONE
;
127 * Can only wrap session and private keys.
129 #if !ALLOW_PUB_KEY_WRAP
130 if(UnwrappedKey
.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY
) {
131 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
133 #endif /* ALLOW_PUB_KEY_WRAP */
134 cspValidateIntendedKeyUsage(&wrappingKey
->KeyHeader
, CSSM_KEYUSE_WRAP
);
135 cspVerifyKeyTimes(wrappingKey
->KeyHeader
);
138 * make sure wrapping key type matches context
140 CSSM_CONTEXT_TYPE wrapType
;
141 switch(wrappingKey
->KeyHeader
.KeyClass
) {
142 case CSSM_KEYCLASS_PUBLIC_KEY
:
143 case CSSM_KEYCLASS_PRIVATE_KEY
:
144 wrapType
= CSSM_ALGCLASS_ASYMMETRIC
;
146 case CSSM_KEYCLASS_SESSION_KEY
:
147 wrapType
= CSSM_ALGCLASS_SYMMETRIC
;
150 errorLog0("WrapKey: bad class of wrappingKey\n");
151 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY
);
153 if(wrapType
!= Context
.type()) {
154 errorLog0("WrapKey: mismatch wrappingKey/contextType\n");
155 CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT
);
157 if(Context
.algorithm() == CSSM_ALGID_NONE
) {
158 errorLog0("WrapKey: null wrap alg, non-null key\n");
159 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
163 * Get optional wrap format, set default per incoming keys
164 * Note: no such atrribute ==> 0 ==> FORMAT_NONE, which we
165 * take to mean "use the default".
167 wrapFormat
= Context
.getInt(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT
);
168 if(wrapFormat
== CSSM_KEYBLOB_WRAPPED_FORMAT_NONE
) {
169 /* figure out a default based on unwrapped key */
170 switch(UnwrappedKey
.keyClass()) {
171 case CSSM_KEYCLASS_SESSION_KEY
:
172 wrapFormat
= CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7
;
174 case CSSM_KEYCLASS_PUBLIC_KEY
:
175 wrapFormat
= CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM
;
177 case CSSM_KEYCLASS_PRIVATE_KEY
:
178 switch(UnwrappedKey
.algorithm()) {
180 wrapFormat
= CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM
;
183 wrapFormat
= CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8
;
188 /* NOT REACHED - checked above */
191 } /* no format present or FORMAT_NONE */
194 /* make sure we have a valid format here */
196 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7
:
197 if(UnwrappedKey
.keyClass() != CSSM_KEYCLASS_SESSION_KEY
) {
198 /* this wrapping style only for symmetric keys */
199 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
202 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8
:
203 case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL
:
204 if(UnwrappedKey
.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY
) {
205 /* these wrapping styles only for private keys */
206 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
209 case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM
:
210 /* no restrictions (well AES can't be the wrap alg but that will
213 case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1
:
214 /* RSA private key, reference format, only */
215 if(UnwrappedKey
.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY
) {
216 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
218 if(UnwrappedKey
.algorithm() != CSSM_ALGID_RSA
) {
219 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
221 if(UnwrappedKey
.blobType() != CSSM_KEYBLOB_REFERENCE
) {
222 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT
);
225 case CSSM_KEYBLOB_WRAPPED_FORMAT_NONE
:
227 /* only time this is OK */
232 dprintf1("KeyWrap: invalid wrapFormat (%d)\n", (int)wrapFormat
);
233 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT
);
235 /* get the blob to be wrappped */
237 bool allocdRawBlob
= false;
238 CSSM_KEYBLOB_FORMAT rawFormat
;
241 * Outgoing same as incoming unless a partial key is completed during
244 const CssmKey::Header
&unwrappedHdr
= UnwrappedKey
.header();
245 CSSM_KEYATTR_FLAGS unwrappedKeyAttrFlags
= unwrappedHdr
.KeyAttr
;
247 switch(UnwrappedKey
.blobType()) {
248 case CSSM_KEYBLOB_RAW
:
250 * Trivial case - we already have the blob.
251 * This op - wrapping a raw key - is not supported for the
252 * CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1 format since that doesn't
253 * operate on a key blob.
255 rawBlob
= CssmData::overlay(UnwrappedKey
.KeyData
);
256 rawFormat
= UnwrappedKey
.blobFormat();
258 case CSSM_KEYBLOB_REFERENCE
:
259 /* get binary key, then get blob from it */
261 BinaryKey
&binKey
= lookupRefKey(UnwrappedKey
);
264 * Subsequent tests for extractability: don't trust the
265 * caller's header; use the one in the BinaryKey.
267 CSSM_KEYATTR_FLAGS keyAttr
= binKey
.mKeyHeader
.KeyAttr
;
268 if(!(keyAttr
& CSSM_KEYATTR_EXTRACTABLE
)) {
269 /* this key not extractable in any form */
270 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
274 * CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: we're ready to roll;
275 * all we need is the reference key.
277 if(wrapFormat
== CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1
) {
282 * Null wrap - prevent caller from obtaining
283 * clear bits if CSSM_KEYATTR_SENSITIVE
285 if(isNullWrap
&& (keyAttr
& CSSM_KEYATTR_SENSITIVE
)) {
286 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
290 * Special case for PKCS8 and openssl: need to get blob of a specific
291 * algorithm-dependent format. Caller can override our
293 * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT
296 rawFormat
= requestedKeyFormat(Context
, UnwrappedKey
);
297 if(rawFormat
== CSSM_KEYBLOB_RAW_FORMAT_NONE
) {
298 CSSM_ALGORITHMS keyAlg
= binKey
.mKeyHeader
.AlgorithmId
;
300 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8
:
301 rawFormat
= pkcs8RawKeyFormat(keyAlg
);
303 case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL
:
304 rawFormat
= opensslRawKeyFormat(keyAlg
);
307 /* punt and take default for key type */
313 * DescriptiveData for encoding, currently only used for
316 if((DescriptiveData
!= NULL
) && (DescriptiveData
->Length
!= 0)) {
317 binKey
.descData(*DescriptiveData
);
320 /* optional parameter-bearing key */
321 CssmKey
*paramKey
= Context
.get
<CssmKey
>(CSSM_ATTRIBUTE_PARAM_KEY
);
322 binKey
.generateKeyBlob(privAllocator
,
327 unwrappedKeyAttrFlags
);
329 allocdRawBlob
= true; // remember - we need to free
333 errorLog0("WrapKey: bad unwrappedKey BlobType\n");
334 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
338 * Prepare outgoing header.
340 setKeyHeader(wrappedHdr
,
342 unwrappedHdr
.algorithm(), // same as incoming
343 unwrappedHdr
.keyClass(), // same as incoming
344 unwrappedKeyAttrFlags
,
345 unwrappedHdr
.KeyUsage
);
346 wrappedHdr
.LogicalKeySizeInBits
= unwrappedHdr
.LogicalKeySizeInBits
;
347 wrappedHdr
.WrapAlgorithmId
= Context
.algorithm(); // true for null
349 wrappedHdr
.StartDate
= unwrappedHdr
.StartDate
;
350 wrappedHdr
.EndDate
= unwrappedHdr
.EndDate
;
351 wrappedHdr
.Format
= wrapFormat
;
353 wrappedHdr
.BlobType
= CSSM_KEYBLOB_RAW
;
356 wrappedHdr
.BlobType
= CSSM_KEYBLOB_WRAPPED
;
360 * special cases - break out here for Apple Custom and OpenSSHv1
364 case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM
:
378 freeCssmData(rawBlob
, privAllocator
);
383 freeCssmData(rawBlob
, privAllocator
);
386 case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1
:
389 * 1. We don't have to worry about allocdRawBlob since this
390 * operation only works on reference keys and we did not
391 * obtain the raw blob from the BinaryKey.
392 * 2. This is a redundant lookupRefKey, I know, but since
393 * that returns a reference, it would just be too messy to have
394 * the previous call be in the same scope as this.
396 BinaryKey
&binKey
= lookupRefKey(UnwrappedKey
);
397 WrapKeyOpenSSH1(CCHandle
,
409 /* proceed to encrypt blob */
416 * Generate wrapped blob. Careful, we need to conditionally free
419 CssmData encryptedBlob
;
421 WrappedKey
.KeyData
.Data
= NULL
; // ignore possible incoming KeyData
422 WrappedKey
.KeyData
.Length
= 0;
426 /* copy raw blob to caller's wrappedKey */
427 copyCssmData(rawBlob
,
428 CssmData::overlay(WrappedKey
.KeyData
),
430 wrappedHdr
.Format
= rawFormat
;
433 /* encrypt rawBlob using caller's context, then encode to
434 * WrappedKey.KeyData */
435 CSSM_SIZE bytesEncrypted
;
436 EncryptData(CCHandle
,
438 &rawBlob
, // ClearBufs[]
440 &encryptedBlob
, // CipherBufs[],
441 1, // CipherBufCount,
446 // I'm not 100% sure about this....
447 assert(remData
.Length
== 0);
448 encryptedBlob
.Length
= bytesEncrypted
;
449 WrappedKey
.KeyData
= encryptedBlob
;
450 wrappedHdr
.BlobType
= CSSM_KEYBLOB_WRAPPED
;
451 // OK to be zero or not present
452 wrappedHdr
.WrapMode
= Context
.getInt(
453 CSSM_ATTRIBUTE_MODE
);
457 errorLog0("WrapKey: EncryptData() threw exception\n");
459 freeCssmData(rawBlob
, privAllocator
);
461 freeCssmData(remData
,normAllocator
);
465 freeCssmData(rawBlob
, privAllocator
);
467 freeCssmData(remData
, normAllocator
);
471 * Unwrap key function. Used for:
473 * -- Given key of BlobType CSSM_KEYBLOB_WRAPPED, decode and decrypt
474 * it, yielding a key in either raw or reference format. Unwrapping
475 * key may be either raw or reference. The context must match
476 * the unwrapping key (ALGCLASS_SYMMETRIC or ALGCLASS_ASYMMETRIC).
478 * Private keys are assumed to be PKCS8 encoded; session keys
479 * are assumed to be PKCS7 encoded.
481 * -- Convert a Raw key to a reference key (with no decrypting).
482 * This is called a NULL unwrap; no unwrapping key need be present in
483 * the context, but the context must be of class
484 * ALGCLASS_SYMMETRIC and algorithm ALGID_NONE.
486 void AppleCSPSession::UnwrapKey(
487 CSSM_CC_HANDLE CCHandle
,
488 const Context
&Context
,
489 const CssmKey
*PublicKey
,
490 const CssmKey
&WrappedKey
,
493 const CssmData
*KeyLabel
,
494 const CSSM_RESOURCE_CONTROL_CONTEXT
*CredAndAclEntry
,
495 CssmKey
&UnwrappedKey
,
496 CssmData
&DescriptiveData
,
497 CSSM_PRIVILEGE Privilege
)
499 bool isNullUnwrap
= false;
500 CssmKey
*unwrappingKey
= NULL
;
501 cspKeyType keyType
; // CKT_Public, etc.
502 CSSM_KEYBLOB_FORMAT wrapFormat
= WrappedKey
.blobFormat();
504 /* obtain unwrapping key if present */
505 unwrappingKey
= Context
.get
<CssmKey
>(CSSM_ATTRIBUTE_KEY
);
506 if(unwrappingKey
== NULL
) {
507 if((Context
.algorithm() == CSSM_ALGID_NONE
) &&
508 (Context
.type() == CSSM_ALGCLASS_SYMMETRIC
)) {
513 errorLog0("UnwrapKey: missing wrapping key\n");
514 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY
);
519 * validate unwrappingKey
522 /* make sure unwrapping key type matches context */
523 CSSM_CONTEXT_TYPE unwrapType
;
524 switch(unwrappingKey
->KeyHeader
.KeyClass
) {
525 case CSSM_KEYCLASS_PUBLIC_KEY
:
526 case CSSM_KEYCLASS_PRIVATE_KEY
:
527 unwrapType
= CSSM_ALGCLASS_ASYMMETRIC
;
529 case CSSM_KEYCLASS_SESSION_KEY
:
530 unwrapType
= CSSM_ALGCLASS_SYMMETRIC
;
533 errorLog0("UnwrapKey: bad class of wrappingKey\n");
534 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY
);
536 if(unwrapType
!= Context
.type()) {
537 errorLog0("UnwrapKey: mismatch unwrappingKey/contextType\n");
538 CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT
);
540 if(Context
.algorithm() == CSSM_ALGID_NONE
) {
541 errorLog0("UnwrapKey: null wrap alg, non-null key\n");
542 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
544 cspValidateIntendedKeyUsage(&unwrappingKey
->KeyHeader
, CSSM_KEYUSE_UNWRAP
);
545 cspVerifyKeyTimes(unwrappingKey
->KeyHeader
);
548 /* validate WrappedKey */
549 switch(WrappedKey
.keyClass()) {
550 case CSSM_KEYCLASS_PUBLIC_KEY
:
551 #if !ALLOW_PUB_KEY_WRAP
553 errorLog0("UnwrapKey: unwrap of public key illegal\n");
554 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
556 #endif /* ALLOW_PUB_KEY_WRAP */
557 keyType
= CKT_Public
;
559 case CSSM_KEYCLASS_PRIVATE_KEY
:
560 keyType
= CKT_Private
;
562 case CSSM_KEYCLASS_SESSION_KEY
:
563 keyType
= CKT_Session
;
566 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
569 if(WrappedKey
.blobType() != CSSM_KEYBLOB_RAW
) {
570 errorLog0("UnwrapKey: expected raw blobType\n");
571 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT
);
575 if(WrappedKey
.blobType() != CSSM_KEYBLOB_WRAPPED
) {
576 errorLog0("UnwrapKey: expected wrapped blobType\n");
577 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT
);
581 /* validate requested storage and usage */
582 cspKeyStorage keyStorage
= cspParseKeyAttr(keyType
, KeyAttr
);
588 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
590 cspValidateKeyUsageBits(keyType
, KeyUsage
);
592 /* prepare outgoing header */
593 CssmKey::Header
&unwrappedHdr
= UnwrappedKey
.header();
594 const CssmKey::Header
&wrappedHdr
= WrappedKey
.header();
595 setKeyHeader(unwrappedHdr
,
597 wrappedHdr
.algorithm(), // same as incoming
598 wrappedHdr
.keyClass(), // same as incoming
599 KeyAttr
& ~KEY_ATTR_RETURN_MASK
,
601 unwrappedHdr
.LogicalKeySizeInBits
= wrappedHdr
.LogicalKeySizeInBits
;
602 unwrappedHdr
.StartDate
= wrappedHdr
.StartDate
;
603 unwrappedHdr
.EndDate
= wrappedHdr
.EndDate
;
604 UnwrappedKey
.KeyData
.Data
= NULL
; // ignore possible incoming KeyData
605 UnwrappedKey
.KeyData
.Length
= 0;
607 /* validate wrappedKey format */
610 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7
:
611 if(WrappedKey
.keyClass() != CSSM_KEYCLASS_SESSION_KEY
) {
612 /* this unwrapping style only for symmetric keys */
613 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
616 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8
:
617 case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL
:
618 if(WrappedKey
.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY
) {
619 /* these unwrapping styles only for private keys */
620 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
623 case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM
:
624 UnwrapKeyCms(CCHandle
,
633 case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1
:
634 /* RSA private key, unwrap to ref key only */
635 if(WrappedKey
.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY
) {
636 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
638 if(WrappedKey
.algorithm() != CSSM_ALGID_RSA
) {
639 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
641 if(keyStorage
!= CKS_Ref
) {
642 errorLog0("UNwrapKey: OPENSSH1 only wraps to reference key\n");
643 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT
);
645 UnwrapKeyOpenSSH1(CCHandle
,
655 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT
);
659 /* Get key blob, decoding and decrypting if necessary */
660 CssmData decodedBlob
;
664 /* simple copy of raw blob */
665 copyData(WrappedKey
.KeyData
,
666 UnwrappedKey
.KeyData
,
668 unwrappedHdr
.BlobType
= CSSM_KEYBLOB_RAW
;
669 unwrappedHdr
.Format
= wrapFormat
;
672 decodedBlob
= CssmData::overlay(WrappedKey
.KeyData
);
673 CSSM_SIZE bytesDecrypted
;
674 CssmData
*unwrapData
=
675 CssmData::overlay(&UnwrappedKey
.KeyData
);
677 DecryptData(CCHandle
,
679 &decodedBlob
, // CipherBufs[],
680 1, // CipherBufCount,
681 unwrapData
, // ClearBufs[]
687 // I'm not 100% sure about this....
688 assert(remData
.Length
== 0);
689 UnwrappedKey
.KeyData
.Length
= bytesDecrypted
;
690 unwrappedHdr
.BlobType
= CSSM_KEYBLOB_RAW
;
693 * Figure out various header fields from resulting blob
696 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7
:
697 unwrappedHdr
.Format
=
698 CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
699 if(unwrappedHdr
.LogicalKeySizeInBits
== 0) {
700 unwrappedHdr
.LogicalKeySizeInBits
=
701 (unsigned)(bytesDecrypted
* 8);
703 /* app has to infer/know algorithm */
705 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8
:
706 pkcs8InferKeyHeader(UnwrappedKey
);
708 case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL
:
710 * App told us key algorithm (in WrappedKey).
711 * Infer format and key size.
713 opensslInferKeyHeader(UnwrappedKey
);
719 errorLog0("UnwrapKey: DecryptData() threw exception\n");
720 freeCssmData(remData
, normAllocator
);
723 freeCssmData(remData
, normAllocator
);
726 * One more thing: cook up a BinaryKey if caller wants a
729 if(keyStorage
== CKS_Ref
) {
731 * We have a key in raw format; convert to BinaryKey.
733 BinaryKey
*binKey
= NULL
;
734 CSPKeyInfoProvider
*provider
= infoProvider(UnwrappedKey
);
735 /* optional parameter-bearing key */
736 CssmKey
*paramKey
= Context
.get
<CssmKey
>(CSSM_ATTRIBUTE_PARAM_KEY
);
737 provider
->CssmKeyToBinary(paramKey
, UnwrappedKey
.KeyHeader
.KeyAttr
, &binKey
);
738 addRefKey(*binKey
, UnwrappedKey
);