]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
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 | // AppleCSPContext.cpp - CSP-wide contexts | |
21 | // | |
22 | ||
23 | #include "AppleCSPContext.h" | |
24 | #include "AppleCSPSession.h" | |
25 | #include "AppleCSPUtils.h" | |
26 | ||
27 | /* | |
28 | * Empty destructor (just to avoid out-of-line copies) | |
29 | */ | |
30 | AppleCSPContext::~AppleCSPContext() | |
31 | { } | |
32 | ||
33 | /* | |
34 | * get symmetric key bits - context.key can be either ref or raw. | |
35 | * A convenience routine typically used by subclass's init(). | |
36 | */ | |
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 | |
44 | { | |
45 | /* key must be present and it must be a session key matching caller's spec */ | |
46 | CssmKey &key = | |
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); | |
50 | } | |
51 | if(key.algorithm() != requiredAlg) { | |
52 | CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH); | |
53 | } | |
54 | cspValidateIntendedKeyUsage(&key.KeyHeader, intendedUse); | |
55 | cspVerifyKeyTimes(key.KeyHeader); | |
56 | ||
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); | |
63 | } | |
64 | keyLen = key.length(); | |
65 | keyBits = key.KeyData.Data; | |
66 | break; | |
67 | ||
68 | case CSSM_KEYBLOB_REFERENCE: | |
69 | { | |
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); | |
77 | } | |
78 | keyLen = symBinKey->mKeyData.Length; | |
79 | keyBits = symBinKey->mKeyData.Data; | |
80 | break; | |
81 | } | |
82 | default: | |
83 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); | |
84 | } | |
85 | return; | |
86 | } | |
87 | ||
88 | AppleKeyPairGenContext::~AppleKeyPairGenContext() | |
89 | { /* virtual */ } | |
90 | ||
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, | |
96 | CssmKey &pubKey, | |
97 | BinaryKey *pubBinKey, | |
98 | CssmKey &privKey, | |
99 | BinaryKey *privBinKey) | |
100 | { | |
101 | uint32 keySize; | |
102 | cspKeyStorage privStorage; | |
103 | cspKeyStorage pubStorage; | |
104 | CssmKey::Header &pubHdr = pubKey.header(); | |
105 | CssmKey::Header &privHdr = privKey.header(); | |
106 | ||
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); | |
112 | ||
113 | // have subclass generate the key pairs in the form of | |
114 | // its native BinaryKeys | |
115 | generate(context, *pubBinKey, *privBinKey, keySize); | |
116 | ||
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; | |
122 | ||
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; | |
128 | switch(pubStorage) { | |
129 | case CKS_Ref: | |
130 | session.addRefKey(*pubBinKey, pubKey); | |
131 | break; | |
132 | case CKS_Data: | |
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), | |
138 | pubHdr.Format, | |
139 | session, | |
140 | NULL, // no paramKey here! | |
141 | attrFlags); | |
142 | break; | |
143 | case CKS_None: | |
144 | break; | |
145 | } | |
146 | switch(privStorage) { | |
147 | case CKS_Ref: | |
148 | session.addRefKey(*privBinKey, privKey); | |
149 | break; | |
150 | case CKS_Data: | |
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), | |
156 | privHdr.Format, | |
157 | session, | |
158 | NULL, | |
159 | attrFlags); | |
160 | break; | |
161 | case CKS_None: | |
162 | break; | |
163 | } | |
164 | if(pubStorage != CKS_Ref) { | |
165 | delete pubBinKey; | |
166 | } | |
167 | if(privStorage != CKS_Ref) { | |
168 | delete privBinKey; | |
169 | } | |
170 | } | |
171 | ||
172 | /* | |
173 | * Called from subclass's generate method. Subclass is also a | |
174 | * AppleCSPContext. | |
175 | */ | |
176 | void AppleSymmKeyGenContext::generateSymKey( | |
177 | const Context &context, | |
178 | AppleCSPSession &session, // for ref keys | |
179 | CssmKey &cssmKey) // RETURNED | |
180 | { | |
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); | |
188 | } | |
189 | if(mustBeByteSized) { | |
190 | if((reqKeySize & 0x7) != 0) { | |
191 | CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); | |
192 | } | |
193 | } | |
194 | ||
195 | // validate KeyAtrr and KeyUsage already present in header | |
196 | cspKeyStorage keyStorage; | |
197 | CssmKey::Header &hdr = cssmKey.header(); | |
198 | ||
199 | keyStorage = cspParseKeyAttr(CKT_Session, hdr.KeyAttr); | |
200 | cspValidateKeyUsageBits(CKT_Session, hdr.KeyUsage); | |
201 | hdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK; | |
202 | ||
203 | hdr.LogicalKeySizeInBits = reqKeySize; | |
204 | uint32 keySizeInBytes = (reqKeySize + 7) / 8; | |
205 | SymmetricBinaryKey *binKey = NULL; | |
206 | CssmData *keyData = NULL; | |
207 | ||
208 | switch(keyStorage) { | |
209 | case CKS_None: | |
210 | /* no way */ | |
211 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); | |
212 | case CKS_Ref: | |
213 | /* cook up a symmetric binary key */ | |
214 | binKey = new SymmetricBinaryKey(reqKeySize); | |
215 | keyData = &binKey->mKeyData; | |
216 | break; | |
217 | case CKS_Data: | |
218 | /* key bytes --> caller's cssmKey */ | |
219 | keyData = &(CssmData::overlay(cssmKey.KeyData)); | |
220 | setUpCssmData(*keyData, keySizeInBytes, | |
221 | session.normAlloc()); | |
222 | break; | |
223 | } | |
224 | ||
225 | // in any case, fill key bytes with random data | |
226 | session.getRandomBytes(keySizeInBytes, keyData->Data); | |
227 | ||
228 | if(keyStorage == CKS_Ref) { | |
229 | session.addRefKey(*binKey, cssmKey); | |
230 | } | |
231 | else { | |
232 | /* Raw data */ | |
233 | hdr.BlobType = CSSM_KEYBLOB_RAW; | |
234 | hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; | |
235 | } | |
236 | ||
237 | // FIXME - any other header fields? | |
238 | } | |
239 | ||
240 | // | |
241 | // Symmetric Binary Key support | |
242 | // | |
243 | SymmetricBinaryKey::SymmetricBinaryKey( | |
244 | unsigned keySizeInBits) : | |
245 | mAllocator(Allocator::standard(Allocator::sensitive)) | |
246 | { | |
247 | setUpCssmData(mKeyData, (keySizeInBits + 7) / 8, mAllocator); | |
248 | } | |
249 | ||
250 | SymmetricBinaryKey::~SymmetricBinaryKey() | |
251 | { | |
252 | freeCssmData(mKeyData, mAllocator); | |
253 | } | |
254 | ||
255 | void SymmetricBinaryKey::generateKeyBlob( | |
256 | Allocator &allocator, | |
257 | CssmData &blob, | |
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 */ | |
262 | { | |
263 | switch(format) { | |
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 | |
267 | break; | |
268 | default: | |
269 | CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT); | |
270 | } | |
271 | copyCssmData(mKeyData, blob, allocator); | |
272 | format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; | |
273 | } | |
274 |