2 * Copyright (c) 2000-2001,2011,2014 Apple 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 AppleCSPSession
&session
,
40 CSSM_ALGORITHMS requiredAlg
, // throws if this doesn't match key alg
41 CSSM_KEYUSE intendedUse
, // throws if key usage doesn't match this
42 uint8
*&keyBits
, // RETURNED (not mallocd or copied)
43 CSSM_SIZE
&keyLen
) // RETURNED
45 /* key must be present and it must be a session key matching caller's spec */
47 context
.get
<CssmKey
>(CSSM_ATTRIBUTE_KEY
, CSSMERR_CSP_MISSING_ATTR_KEY
);
48 if(key
.keyClass() != CSSM_KEYCLASS_SESSION_KEY
) {
49 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
51 if(key
.algorithm() != requiredAlg
) {
52 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH
);
54 cspValidateIntendedKeyUsage(&key
.KeyHeader
, intendedUse
);
55 cspVerifyKeyTimes(key
.KeyHeader
);
57 /* extract raw bits one way or the other */
58 switch(key
.blobType()) {
59 case CSSM_KEYBLOB_RAW
:
60 /* easy case, the bits are right there in the CssmKey */
61 if(key
.blobFormat() != CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
) {
62 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
64 keyLen
= key
.length();
65 keyBits
= key
.KeyData
.Data
;
68 case CSSM_KEYBLOB_REFERENCE
:
70 /* do a lookup to get a binary key */
71 BinaryKey
&binKey
= session
.lookupRefKey(key
);
72 /* fails if this is not a SymmetricBinaryKey */
73 SymmetricBinaryKey
*symBinKey
=
74 dynamic_cast<SymmetricBinaryKey
*>(&binKey
);
75 if(symBinKey
== NULL
) {
76 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
78 keyLen
= symBinKey
->mKeyData
.Length
;
79 keyBits
= symBinKey
->mKeyData
.Data
;
83 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
88 AppleKeyPairGenContext::~AppleKeyPairGenContext()
91 // Called from subclass after it allocates its BinaryKeys.
92 // Caller frees BinaryKeys if we throw any exception.
93 void AppleKeyPairGenContext::generate(
94 const Context
&context
,
95 AppleCSPSession
&session
,
99 BinaryKey
*privBinKey
)
102 cspKeyStorage privStorage
;
103 cspKeyStorage pubStorage
;
104 CssmKey::Header
&pubHdr
= pubKey
.header();
105 CssmKey::Header
&privHdr
= privKey
.header();
107 // validate context and key header args
108 pubStorage
= cspParseKeyAttr(CKT_Public
, pubHdr
.KeyAttr
);
109 privStorage
= cspParseKeyAttr(CKT_Private
, privHdr
.KeyAttr
);
110 cspValidateKeyUsageBits(CKT_Public
, pubHdr
.KeyUsage
);
111 cspValidateKeyUsageBits(CKT_Private
, privHdr
.KeyUsage
);
113 // have subclass generate the key pairs in the form of
114 // its native BinaryKeys
115 generate(context
, *pubBinKey
, *privBinKey
, keySize
);
117 // FIXME - Any other header setup?
118 pubHdr
.LogicalKeySizeInBits
=
119 privHdr
.LogicalKeySizeInBits
= keySize
;
120 pubHdr
.KeyAttr
&= ~KEY_ATTR_RETURN_MASK
;
121 privHdr
.KeyAttr
&= ~KEY_ATTR_RETURN_MASK
;
123 // Handle key formatting. Delete the BinaryKeys if
124 // we're not creating ref keys, after safe completion of
125 // generateKeyBlob (which may throw, in which case the binary keys
126 // get deleted by our caller).
127 CSSM_KEYATTR_FLAGS attrFlags
= 0;
130 session
.addRefKey(*pubBinKey
, pubKey
);
133 pubHdr
.Format
= requestedKeyFormat(context
, pubKey
);
134 pubBinKey
->mKeyHeader
= pubHdr
;
135 pubBinKey
->generateKeyBlob(
136 session
.normAlloc(), // alloc in user space
137 CssmData::overlay(pubKey
.KeyData
),
140 NULL
, // no paramKey here!
146 switch(privStorage
) {
148 session
.addRefKey(*privBinKey
, privKey
);
151 privHdr
.Format
= requestedKeyFormat(context
, privKey
);
152 privBinKey
->mKeyHeader
= privHdr
;
153 privBinKey
->generateKeyBlob(
154 session
.normAlloc(), // alloc in user space
155 CssmData::overlay(privKey
.KeyData
),
164 if(pubStorage
!= CKS_Ref
) {
167 if(privStorage
!= CKS_Ref
) {
173 * Called from subclass's generate method. Subclass is also a
176 void AppleSymmKeyGenContext::generateSymKey(
177 const Context
&context
,
178 AppleCSPSession
&session
, // for ref keys
179 CssmKey
&cssmKey
) // RETURNED
181 /* there really is no legal way this should throw... */
182 uint32 reqKeySize
= context
.getInt(
183 CSSM_ATTRIBUTE_KEY_LENGTH
,
184 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH
);
185 if((reqKeySize
< minSizeInBits
) ||
186 (reqKeySize
> maxSizeInBits
)) {
187 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE
);
189 if(mustBeByteSized
) {
190 if((reqKeySize
& 0x7) != 0) {
191 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE
);
195 // validate KeyAtrr and KeyUsage already present in header
196 cspKeyStorage keyStorage
;
197 CssmKey::Header
&hdr
= cssmKey
.header();
199 keyStorage
= cspParseKeyAttr(CKT_Session
, hdr
.KeyAttr
);
200 cspValidateKeyUsageBits(CKT_Session
, hdr
.KeyUsage
);
201 hdr
.KeyAttr
&= ~KEY_ATTR_RETURN_MASK
;
203 hdr
.LogicalKeySizeInBits
= reqKeySize
;
204 uint32 keySizeInBytes
= (reqKeySize
+ 7) / 8;
205 SymmetricBinaryKey
*binKey
= NULL
;
206 CssmData
*keyData
= NULL
;
211 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
213 /* cook up a symmetric binary key */
214 binKey
= new SymmetricBinaryKey(reqKeySize
);
215 keyData
= &binKey
->mKeyData
;
218 /* key bytes --> caller's cssmKey */
219 keyData
= &(CssmData::overlay(cssmKey
.KeyData
));
220 setUpCssmData(*keyData
, keySizeInBytes
,
221 session
.normAlloc());
225 // in any case, fill key bytes with random data
226 session
.getRandomBytes(keySizeInBytes
, keyData
->Data
);
228 if(keyStorage
== CKS_Ref
) {
229 session
.addRefKey(*binKey
, cssmKey
);
233 hdr
.BlobType
= CSSM_KEYBLOB_RAW
;
234 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
237 // FIXME - any other header fields?
241 // Symmetric Binary Key support
243 SymmetricBinaryKey::SymmetricBinaryKey(
244 unsigned keySizeInBits
) :
245 mAllocator(Allocator::standard(Allocator::sensitive
))
247 setUpCssmData(mKeyData
, (keySizeInBits
+ 7) / 8, mAllocator
);
250 SymmetricBinaryKey::~SymmetricBinaryKey()
252 freeCssmData(mKeyData
, mAllocator
);
255 void SymmetricBinaryKey::generateKeyBlob(
256 Allocator
&allocator
,
258 CSSM_KEYBLOB_FORMAT
&format
, // CSSM_KEYBLOB_RAW_FORMAT_PKCS1, etc.
259 AppleCSPSession
&session
,
260 const CssmKey
*paramKey
, /* optional, unused here */
261 CSSM_KEYATTR_FLAGS
&attrFlags
) /* IN/OUT */
264 case CSSM_KEYBLOB_RAW_FORMAT_NONE
: // default
265 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
: // the one we can do
266 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST
: // same thing
269 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT
);
271 copyCssmData(mKeyData
, blob
, allocator
);
272 format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;