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 // AppleCSPContext.cpp - CSP-wide contexts
23 #include "AppleCSPContext.h"
24 #include "AppleCSPSession.h"
25 #include "AppleCSPUtils.h"
28 * Empty destructor (just to avoid out-of-line copies)
30 AppleCSPContext::~AppleCSPContext()
34 * get symmetric key bits - context.key can be either ref or raw.
35 * A convenience routine typically used by subclass's init().
37 void AppleCSPContext::symmetricKeyBits(
38 const Context
&context
,
39 CSSM_ALGORITHMS requiredAlg
, // throws if this doesn't match key alg
40 CSSM_KEYUSE intendedUse
, // throws if key usage doesn't match this
41 UInt8
*&keyBits
, // RETURNED (not mallocd or copied)
42 UInt32
&keyLen
) // RETURNED
44 /* key must be present and it must be a session key matching caller's spec */
46 context
.get
<CssmKey
>(CSSM_ATTRIBUTE_KEY
, CSSMERR_CSP_MISSING_ATTR_KEY
);
47 if(key
.keyClass() != CSSM_KEYCLASS_SESSION_KEY
) {
48 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
50 if(key
.algorithm() != requiredAlg
) {
51 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH
);
53 cspValidateIntendedKeyUsage(&key
.KeyHeader
, intendedUse
);
55 /* extract raw bits one way or the other */
56 switch(key
.blobType()) {
57 case CSSM_KEYBLOB_RAW
:
58 /* easy case, the bits are right there in the CssmKey */
59 if(key
.blobFormat() != CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
) {
60 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
62 keyLen
= key
.length();
63 keyBits
= key
.KeyData
.Data
;
66 case CSSM_KEYBLOB_REFERENCE
:
68 /* do a lookup to get a binary key */
69 BinaryKey
&binKey
= mSession
.lookupRefKey(key
);
70 /* fails if this is not a SymmetricBinaryKey */
71 SymmetricBinaryKey
*symBinKey
=
72 dynamic_cast<SymmetricBinaryKey
*>(&binKey
);
73 if(symBinKey
== NULL
) {
74 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
76 keyLen
= symBinKey
->mKeyData
.Length
;
77 keyBits
= symBinKey
->mKeyData
.Data
;
81 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
86 // Called from subclass after it allocates its BinaryKeys.
87 // Caller frees BinaryKeys if we throw any exception.
88 void AppleKeyPairGenContext::generate(
89 const Context
&context
,
90 AppleCSPSession
&session
,
94 BinaryKey
*privBinKey
)
97 cspKeyStorage privStorage
;
98 cspKeyStorage pubStorage
;
99 CssmKey::Header
&pubHdr
= pubKey
.header();
100 CssmKey::Header
&privHdr
= privKey
.header();
102 // validate context and key header args
103 pubStorage
= cspParseKeyAttr(CKT_Public
, pubHdr
.KeyAttr
);
104 privStorage
= cspParseKeyAttr(CKT_Private
, privHdr
.KeyAttr
);
105 cspValidateKeyUsageBits(CKT_Public
, pubHdr
.KeyUsage
);
106 cspValidateKeyUsageBits(CKT_Private
, privHdr
.KeyUsage
);
108 // have subclass generate the key pairs in the form of
109 // its native BinaryKeys
110 generate(context
, *pubBinKey
, *privBinKey
, keySize
);
112 // FIXME - Any other header setup?
113 pubHdr
.LogicalKeySizeInBits
=
114 privHdr
.LogicalKeySizeInBits
= keySize
;
115 pubHdr
.KeyAttr
&= ~KEY_ATTR_RETURN_MASK
;
116 privHdr
.KeyAttr
&= ~KEY_ATTR_RETURN_MASK
;
118 // Handle key formatting. Delete the BinaryKeys if
119 // we're not creating ref keys.
122 session
.addRefKey(*pubBinKey
, pubKey
);
125 pubHdr
.Format
= requestedKeyFormat(context
, pubKey
);
126 pubBinKey
->mKeyHeader
= pubHdr
;
127 pubBinKey
->generateKeyBlob(
128 session
.normAlloc(), // alloc in user space
129 CssmData::overlay(pubKey
.KeyData
),
137 switch(privStorage
) {
139 session
.addRefKey(*privBinKey
, privKey
);
142 privHdr
.Format
= requestedKeyFormat(context
, privKey
);
143 privBinKey
->mKeyHeader
= privHdr
;
144 privBinKey
->generateKeyBlob(
145 session
.normAlloc(), // alloc in user space
146 CssmData::overlay(privKey
.KeyData
),
157 * Called from subclass's generate method. Subclass is also a
160 void AppleSymmKeyGenContext::generateSymKey(
161 const Context
&context
,
162 AppleCSPSession
&session
, // for ref keys
163 CssmKey
&cssmKey
) // RETURNED
165 /* there really is no legal way this should throw... */
166 uint32 reqKeySize
= context
.getInt(
167 CSSM_ATTRIBUTE_KEY_LENGTH
,
168 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH
);
169 if((reqKeySize
< minSizeInBits
) ||
170 (reqKeySize
> maxSizeInBits
)) {
171 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE
);
173 if(mustBeByteSized
) {
174 if((reqKeySize
& 0x7) != 0) {
175 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE
);
179 // validate KeyAtrr and KeyUsage already present in header
180 cspKeyStorage keyStorage
;
181 CssmKey::Header
&hdr
= cssmKey
.header();
183 keyStorage
= cspParseKeyAttr(CKT_Session
, hdr
.KeyAttr
);
184 cspValidateKeyUsageBits(CKT_Session
, hdr
.KeyUsage
);
185 hdr
.KeyAttr
&= ~KEY_ATTR_RETURN_MASK
;
187 hdr
.LogicalKeySizeInBits
= reqKeySize
;
188 uint32 keySizeInBytes
= (reqKeySize
+ 7) / 8;
189 SymmetricBinaryKey
*binKey
= NULL
;
190 CssmData
*keyData
= NULL
;
195 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
197 /* cook up a symmetric binary key */
198 binKey
= new SymmetricBinaryKey(reqKeySize
);
199 keyData
= &binKey
->mKeyData
;
202 /* key bytes --> caller's cssmKey */
203 keyData
= &(CssmData::overlay(cssmKey
.KeyData
));
204 setUpCssmData(*keyData
, keySizeInBytes
,
205 session
.normAlloc());
209 // in any case, fill key bytes with random data
210 session
.getRandomBytes(keySizeInBytes
, keyData
->Data
);
212 if(keyStorage
== CKS_Ref
) {
213 session
.addRefKey(*binKey
, cssmKey
);
217 hdr
.BlobType
= CSSM_KEYBLOB_RAW
;
218 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
221 // FIXME - any other header fields?
225 // Symmetric Binary Key support
227 SymmetricBinaryKey::SymmetricBinaryKey(
228 unsigned keySizeInBits
) :
229 mAllocator(CssmAllocator::standard(CssmAllocator::sensitive
))
231 setUpCssmData(mKeyData
, (keySizeInBits
+ 7) / 8, mAllocator
);
234 SymmetricBinaryKey::~SymmetricBinaryKey()
236 freeCssmData(mKeyData
, mAllocator
);
239 void SymmetricBinaryKey::generateKeyBlob(
240 CssmAllocator
&allocator
,
242 CSSM_KEYBLOB_FORMAT
&format
) // CSSM_KEYBLOB_RAW_FORMAT_PKCS1, etc.
245 case CSSM_KEYBLOB_RAW_FORMAT_NONE
: // default
246 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
: // the one we can do
249 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT
);
251 copyCssmData(mKeyData
, blob
, allocator
);
252 format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;