]> git.saurik.com Git - apple/security.git/blob - AppleCSP/CryptKitCSP/FEEKeys.cpp
Security-179.tar.gz
[apple/security.git] / AppleCSP / CryptKitCSP / FEEKeys.cpp
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 * FEEKeys.cpp - FEE-related asymmetric key pair classes.
21 *
22 * Created 2/21/2001 by dmitch.
23 */
24
25 #ifdef CRYPTKIT_CSP_ENABLE
26
27 #include "FEEKeys.h"
28 #include "FEECSPUtils.h"
29 #include "CryptKitSpace.h"
30 #include <CryptKit/feePublicKey.h>
31 #include <CryptKit/falloc.h>
32 #include <Security/cssmdata.h>
33 #include "AppleCSPSession.h"
34 #include "AppleCSPUtils.h"
35 #include <assert.h>
36 #include <Security/debugging.h>
37
38 #define feeKeyDebug(args...) secdebug("feeKey", ## args)
39
40 /***
41 *** FEE-style BinaryKey
42 ***/
43
44 /* constructor with optional existing feePubKey */
45 CryptKit::FEEBinaryKey::FEEBinaryKey(feePubKey feeKey)
46 : mFeeKey(feeKey)
47 {
48 if(mFeeKey == NULL) {
49 mFeeKey = feePubKeyAlloc();
50 if(mFeeKey == NULL) {
51 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
52 }
53 }
54 }
55
56 CryptKit::FEEBinaryKey::~FEEBinaryKey()
57 {
58 if(mFeeKey) {
59 feePubKeyFree(mFeeKey);
60 mFeeKey = NULL;
61 }
62 }
63
64 void CryptKit::FEEBinaryKey::generateKeyBlob(
65 CssmAllocator &allocator,
66 CssmData &blob,
67 CSSM_KEYBLOB_FORMAT &format,
68 AppleCSPSession &session,
69 const CssmKey *paramKey, /* optional, unused here */
70 CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */
71 {
72 unsigned char *keyBlob;
73 unsigned len;
74 feeReturn frtn;
75 bool derBlob;
76 bool freeTheKey = false;
77 feePubKey keyToEncode = mFeeKey;
78
79 assert(mFeeKey != NULL);
80 switch(format) {
81 /* also case FEE_KEYBLOB_DEFAULT_FORMAT: */
82 case CSSM_KEYBLOB_RAW_FORMAT_NONE:
83 derBlob = true;
84 break;
85 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
86 {
87 /* key digest calculation; special case for private keys: cook
88 * up the associated public key and encode that */
89 if(mKeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) {
90 keyToEncode = feePubKeyAlloc();
91 if(keyToEncode == NULL) {
92 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
93 }
94 frtn = feePubKeyInitPubKeyFromPriv(mFeeKey, keyToEncode);
95 if(frtn) {
96 feePubKeyFree(keyToEncode);
97 throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv");
98 }
99 freeTheKey = true;
100 }
101 /* in any case, DER-encode a public key */
102 derBlob = true;
103 break;
104 }
105 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
106 /* native non-DER-encoded blob */
107 derBlob = false;
108 break;
109 default:
110 feeKeyDebug("FEEBinaryKey::generateKeyBlob: bad format (%ld)\n", format);
111 CssmError::throwMe(feePubKeyIsPrivate(mFeeKey) ?
112 CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT :
113 CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
114 }
115 if(feePubKeyIsPrivate(keyToEncode)) {
116 if(derBlob) {
117 frtn = feePubKeyCreateDERPrivBlob(keyToEncode, &keyBlob, &len);
118 }
119 else {
120 frtn = feePubKeyCreatePrivBlob(keyToEncode, &keyBlob, &len);
121 }
122 }
123 else {
124 if(derBlob) {
125 frtn = feePubKeyCreateDERPubBlob(keyToEncode, &keyBlob, &len);
126 }
127 else {
128 frtn = feePubKeyCreatePubBlob(keyToEncode, &keyBlob, &len);
129 }
130 }
131 if(frtn) {
132 throwCryptKit(frtn, "feePubKeyCreate*Blob");
133 }
134 setUpCssmData(blob, len, allocator);
135 memmove(blob.data(), keyBlob, len);
136 blob.length(len);
137 ffree(keyBlob);
138 format = derBlob ? FEE_KEYBLOB_DEFAULT_FORMAT :
139 CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
140 if(freeTheKey) {
141 /* free the temp pub key we created here */
142 feePubKeyFree(keyToEncode);
143 }
144 }
145
146 /***
147 *** FEE-style AppleKeyPairGenContext
148 ***/
149
150 /*
151 * This one is specified in, and called from, CSPFullPluginSession. Our
152 * only job is to prepare two subclass-specific BinaryKeys and call up to
153 * AppleKeyPairGenContext.
154 */
155 void CryptKit::FEEKeyPairGenContext::generate(
156 const Context &context,
157 CssmKey &pubKey,
158 CssmKey &privKey)
159 {
160 FEEBinaryKey *pubBinKey = new FEEBinaryKey();
161 FEEBinaryKey *privBinKey = new FEEBinaryKey();
162
163 try {
164 AppleKeyPairGenContext::generate(context,
165 session(),
166 pubKey,
167 pubBinKey,
168 privKey,
169 privBinKey);
170 }
171 catch (...) {
172 delete pubBinKey;
173 delete privBinKey;
174 throw;
175 }
176
177 }
178
179 // this one is specified in, and called from, AppleKeyPairGenContext
180 void CryptKit::FEEKeyPairGenContext::generate(
181 const Context &context,
182 BinaryKey &pubBinKey,
183 BinaryKey &privBinKey,
184 uint32 &keyBits)
185 {
186 /*
187 * These casts throw exceptions if the keys are of the
188 * wrong classes, which would be a major bogon, since we created
189 * the keys in the above generate() function.
190 */
191 FEEBinaryKey &fPubBinKey =
192 dynamic_cast<FEEBinaryKey &>(pubBinKey);
193 FEEBinaryKey &fPrivBinKey =
194 dynamic_cast<FEEBinaryKey &>(privBinKey);
195
196 /*
197 * Two parameters from context. Key size in bits is required;
198 * seed is optional. If not present, we cook up random private data.
199 */
200 keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH,
201 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
202 CssmCryptoData *cseed = context.get<CssmCryptoData>(CSSM_ATTRIBUTE_SEED);
203 CssmData *seed;
204 bool haveSeed;
205 CssmAutoData aSeed(session()); // malloc on demand
206 if(cseed) {
207 /* caller specified seed */
208 haveSeed = true;
209 seed = &cseed->param();
210 }
211 else {
212 /* generate random seed */
213 haveSeed = false;
214 unsigned keyBytes = ((keyBits + 7) / 8) + 1;
215 aSeed.malloc(keyBytes);
216 session().getRandomBytes(keyBytes, aSeed);
217 seed = &aSeed.get();
218 }
219
220 /* Curve and prime types - optional */
221 feePrimeType primeType = FPT_Default;
222 uint32 uPrimeType = context.getInt(CSSM_ATTRIBUTE_FEE_PRIME_TYPE);
223 switch(uPrimeType) {
224 case CSSM_FEE_PRIME_TYPE_DEFAULT:
225 break;
226 case CSSM_FEE_PRIME_TYPE_MERSENNE:
227 primeType = FPT_Mersenne;
228 break;
229 case CSSM_FEE_PRIME_TYPE_FEE:
230 primeType = FPT_FEE;
231 break;
232 case CSSM_FEE_PRIME_TYPE_GENERAL:
233 primeType = FPT_General;
234 break;
235 default:
236 /* FIXME - maybe we should be more specific */
237 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
238 }
239 feeCurveType curveType = FCT_Default;
240 uint32 uCurveType = context.getInt(CSSM_ATTRIBUTE_FEE_CURVE_TYPE);
241 switch(uCurveType) {
242 case CSSM_FEE_CURVE_TYPE_DEFAULT:
243 break;
244 case CSSM_FEE_CURVE_TYPE_MONTGOMERY:
245 curveType = FCT_Montgomery;
246 break;
247 case CSSM_FEE_CURVE_TYPE_WEIERSTRASS:
248 curveType = FCT_Weierstrass;
249 break;
250 default:
251 /* FIXME - maybe we should be more specific */
252 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
253 }
254 feeReturn frtn = feePubKeyInitFromPrivDataKeyBits(
255 fPrivBinKey.feeKey(),
256 (unsigned char *)seed->data(),
257 seed->length(),
258 keyBits,
259 primeType,
260 curveType,
261 /*
262 * our random seed: trust it
263 * caller's seed: hash it
264 */
265 haveSeed ? 1 : 0);
266 if(frtn) {
267 throwCryptKit(frtn, "feePubKeyInitFromPrivDataKeyBits");
268 }
269 frtn = feePubKeyInitPubKeyFromPriv(fPrivBinKey.feeKey(),
270 fPubBinKey.feeKey());
271 if(frtn) {
272 throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv");
273 }
274 }
275
276
277 /***
278 *** FEE-style CSPKeyInfoProvider.
279 ***/
280 CryptKit::FEEKeyInfoProvider::FEEKeyInfoProvider(
281 const CssmKey &cssmKey,
282 AppleCSPSession &session) :
283 CSPKeyInfoProvider(cssmKey, session)
284 {
285 }
286 CSPKeyInfoProvider *FEEKeyInfoProvider::provider(
287 const CssmKey &cssmKey,
288 AppleCSPSession &session)
289 {
290 switch(cssmKey.algorithm()) {
291 case CSSM_ALGID_FEE:
292 break;
293 default:
294 return NULL;
295 }
296 switch(cssmKey.keyClass()) {
297 case CSSM_KEYCLASS_PUBLIC_KEY:
298 case CSSM_KEYCLASS_PRIVATE_KEY:
299 /* FIXME - verify proper CSSM_KEYBLOB_RAW_FORMAT_xx */
300 break;
301 default:
302 return NULL;
303 }
304 /* OK, we'll handle this one */
305 return new FEEKeyInfoProvider(cssmKey, session);
306 }
307
308 /* Given a raw key, cook up a Binary key */
309 void CryptKit::FEEKeyInfoProvider::CssmKeyToBinary(
310 CssmKey *paramKey, // optional, ignored
311 CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT
312 BinaryKey **binKey)
313 {
314 *binKey = NULL;
315 feePubKey feeKey = NULL;
316
317 /* first cook up a feePubKey, then drop that into a BinaryKey */
318 feeKey = rawCssmKeyToFee(mKey);
319 FEEBinaryKey *feeBinKey = new FEEBinaryKey(feeKey);
320 *binKey = feeBinKey;
321 }
322
323 /*
324 * Obtain key size in bits.
325 * Currently only raw public keys are dealt with (they're the ones
326 * which come from certs, the only current use for this function).
327 * Note that if we need to handle ref keys, we'll need a session ref...
328 */
329 void CryptKit::FEEKeyInfoProvider::QueryKeySizeInBits(
330 CSSM_KEY_SIZE &keySize)
331 {
332 feePubKey feeKey = NULL;
333
334 if(mKey.blobType() != CSSM_KEYBLOB_RAW) {
335 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
336 }
337 feeKey = rawCssmKeyToFee(mKey);
338 keySize.LogicalKeySizeInBits = feePubKeyBitsize(feeKey);
339 keySize.EffectiveKeySizeInBits = keySize.LogicalKeySizeInBits;
340 feePubKeyFree(feeKey);
341 }
342
343 /*
344 * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST
345 * passthrough.
346 */
347 bool CryptKit::FEEKeyInfoProvider::getHashableBlob(
348 CssmAllocator &allocator,
349 CssmData &blob) // blob to hash goes here
350 {
351 /*
352 * The optimized case, a raw key in the "proper" format already.
353 */
354 assert(mKey.blobType() == CSSM_KEYBLOB_RAW);
355 if((mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_NONE) &&
356 (mKey.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY)) {
357 const CssmData &keyBlob = CssmData::overlay(mKey.KeyData);
358 copyCssmData(keyBlob, blob, allocator);
359 return true;
360 }
361
362 /* caller converts to binary and proceeds */
363 return false;
364 }
365
366 #endif /* CRYPTKIT_CSP_ENABLE */