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
);
54 cspVerifyKeyTimes(key
.KeyHeader
);
56 /* extract raw bits one way or the other */
57 switch(key
.blobType()) {
58 case CSSM_KEYBLOB_RAW
:
59 /* easy case, the bits are right there in the CssmKey */
60 if(key
.blobFormat() != CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
) {
61 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
63 keyLen
= key
.length();
64 keyBits
= key
.KeyData
.Data
;
67 case CSSM_KEYBLOB_REFERENCE
:
69 /* do a lookup to get a binary key */
70 BinaryKey
&binKey
= mSession
.lookupRefKey(key
);
71 /* fails if this is not a SymmetricBinaryKey */
72 SymmetricBinaryKey
*symBinKey
=
73 dynamic_cast<SymmetricBinaryKey
*>(&binKey
);
74 if(symBinKey
== NULL
) {
75 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
77 keyLen
= symBinKey
->mKeyData
.Length
;
78 keyBits
= symBinKey
->mKeyData
.Data
;
82 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
87 // Called from subclass after it allocates its BinaryKeys.
88 // Caller frees BinaryKeys if we throw any exception.
89 void AppleKeyPairGenContext::generate(
90 const Context
&context
,
91 AppleCSPSession
&session
,
95 BinaryKey
*privBinKey
)
98 cspKeyStorage privStorage
;
99 cspKeyStorage pubStorage
;
100 CssmKey::Header
&pubHdr
= pubKey
.header();
101 CssmKey::Header
&privHdr
= privKey
.header();
103 // validate context and key header args
104 pubStorage
= cspParseKeyAttr(CKT_Public
, pubHdr
.KeyAttr
);
105 privStorage
= cspParseKeyAttr(CKT_Private
, privHdr
.KeyAttr
);
106 cspValidateKeyUsageBits(CKT_Public
, pubHdr
.KeyUsage
);
107 cspValidateKeyUsageBits(CKT_Private
, privHdr
.KeyUsage
);
109 // have subclass generate the key pairs in the form of
110 // its native BinaryKeys
111 generate(context
, *pubBinKey
, *privBinKey
, keySize
);
113 // FIXME - Any other header setup?
114 pubHdr
.LogicalKeySizeInBits
=
115 privHdr
.LogicalKeySizeInBits
= keySize
;
116 pubHdr
.KeyAttr
&= ~KEY_ATTR_RETURN_MASK
;
117 privHdr
.KeyAttr
&= ~KEY_ATTR_RETURN_MASK
;
119 // Handle key formatting. Delete the BinaryKeys if
120 // we're not creating ref keys, after safe completion of
121 // generateKeyBlob (which may throw, in which case the binary keys
122 // get deleted by our caller).
123 CSSM_KEYATTR_FLAGS attrFlags
= 0;
126 session
.addRefKey(*pubBinKey
, pubKey
);
129 pubHdr
.Format
= requestedKeyFormat(context
, pubKey
);
130 pubBinKey
->mKeyHeader
= pubHdr
;
131 pubBinKey
->generateKeyBlob(
132 session
.normAlloc(), // alloc in user space
133 CssmData::overlay(pubKey
.KeyData
),
136 NULL
, // no paramKey here!
142 switch(privStorage
) {
144 session
.addRefKey(*privBinKey
, privKey
);
147 privHdr
.Format
= requestedKeyFormat(context
, privKey
);
148 privBinKey
->mKeyHeader
= privHdr
;
149 privBinKey
->generateKeyBlob(
150 session
.normAlloc(), // alloc in user space
151 CssmData::overlay(privKey
.KeyData
),
160 if(pubStorage
!= CKS_Ref
) {
163 if(privStorage
!= CKS_Ref
) {
169 * Called from subclass's generate method. Subclass is also a
172 void AppleSymmKeyGenContext::generateSymKey(
173 const Context
&context
,
174 AppleCSPSession
&session
, // for ref keys
175 CssmKey
&cssmKey
) // RETURNED
177 /* there really is no legal way this should throw... */
178 uint32 reqKeySize
= context
.getInt(
179 CSSM_ATTRIBUTE_KEY_LENGTH
,
180 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH
);
181 if((reqKeySize
< minSizeInBits
) ||
182 (reqKeySize
> maxSizeInBits
)) {
183 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE
);
185 if(mustBeByteSized
) {
186 if((reqKeySize
& 0x7) != 0) {
187 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE
);
191 // validate KeyAtrr and KeyUsage already present in header
192 cspKeyStorage keyStorage
;
193 CssmKey::Header
&hdr
= cssmKey
.header();
195 keyStorage
= cspParseKeyAttr(CKT_Session
, hdr
.KeyAttr
);
196 cspValidateKeyUsageBits(CKT_Session
, hdr
.KeyUsage
);
197 hdr
.KeyAttr
&= ~KEY_ATTR_RETURN_MASK
;
199 hdr
.LogicalKeySizeInBits
= reqKeySize
;
200 uint32 keySizeInBytes
= (reqKeySize
+ 7) / 8;
201 SymmetricBinaryKey
*binKey
= NULL
;
202 CssmData
*keyData
= NULL
;
207 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
209 /* cook up a symmetric binary key */
210 binKey
= new SymmetricBinaryKey(reqKeySize
);
211 keyData
= &binKey
->mKeyData
;
214 /* key bytes --> caller's cssmKey */
215 keyData
= &(CssmData::overlay(cssmKey
.KeyData
));
216 setUpCssmData(*keyData
, keySizeInBytes
,
217 session
.normAlloc());
221 // in any case, fill key bytes with random data
222 session
.getRandomBytes(keySizeInBytes
, keyData
->Data
);
224 if(keyStorage
== CKS_Ref
) {
225 session
.addRefKey(*binKey
, cssmKey
);
229 hdr
.BlobType
= CSSM_KEYBLOB_RAW
;
230 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
233 // FIXME - any other header fields?
237 // Symmetric Binary Key support
239 SymmetricBinaryKey::SymmetricBinaryKey(
240 unsigned keySizeInBits
) :
241 mAllocator(CssmAllocator::standard(CssmAllocator::sensitive
))
243 setUpCssmData(mKeyData
, (keySizeInBits
+ 7) / 8, mAllocator
);
246 SymmetricBinaryKey::~SymmetricBinaryKey()
248 freeCssmData(mKeyData
, mAllocator
);
251 void SymmetricBinaryKey::generateKeyBlob(
252 CssmAllocator
&allocator
,
254 CSSM_KEYBLOB_FORMAT
&format
, // CSSM_KEYBLOB_RAW_FORMAT_PKCS1, etc.
255 AppleCSPSession
&session
,
256 const CssmKey
*paramKey
, /* optional, unused here */
257 CSSM_KEYATTR_FLAGS
&attrFlags
) /* IN/OUT */
260 case CSSM_KEYBLOB_RAW_FORMAT_NONE
: // default
261 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
: // the one we can do
262 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST
: // same thing
265 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT
);
267 copyCssmData(mKeyData
, blob
, allocator
);
268 format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;