]> git.saurik.com Git - apple/security.git/blob - libsecurity_apple_csp/lib/FEEKeys.cpp
Security-55471.14.18.tar.gz
[apple/security.git] / libsecurity_apple_csp / lib / 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 <security_cryptkit/feePublicKey.h>
31 #include <security_cryptkit/falloc.h>
32 #include <security_cdsa_utilities/cssmdata.h>
33 #include "AppleCSPSession.h"
34 #include "AppleCSPUtils.h"
35 #include <assert.h>
36 #include <security_utilities/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 Allocator &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 = FR_Internal;
75 bool freeTheKey = false;
76 feePubKey keyToEncode = mFeeKey;
77
78 assert(mFeeKey != NULL);
79 if((format == CSSM_KEYBLOB_RAW_FORMAT_DIGEST) &&
80 (mKeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY)) {
81 /* key digest calculation; special case for private keys: cook
82 * up the associated public key and encode that */
83 keyToEncode = feePubKeyAlloc();
84 if(keyToEncode == NULL) {
85 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
86 }
87 frtn = feePubKeyInitPubKeyFromPriv(mFeeKey, keyToEncode);
88 if(frtn) {
89 feePubKeyFree(keyToEncode);
90 throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv");
91 }
92 freeTheKey = true;
93 }
94
95 bool badFormat = false;
96 int isPrivate = feePubKeyIsPrivate(keyToEncode);
97
98 switch(mKeyHeader.AlgorithmId) {
99 case CSSM_ALGID_FEE:
100 if(isPrivate) {
101 /* FEE private key */
102 switch(format) {
103 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
104 format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
105 /* and drop thru */
106 case CSSM_KEYBLOB_RAW_FORMAT_NONE:
107 frtn = feePubKeyCreateDERPrivBlob(keyToEncode, &keyBlob, &len);
108 break;
109 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
110 frtn = feePubKeyCreatePrivBlob(keyToEncode, &keyBlob, &len);
111 break;
112 default:
113 badFormat = true;
114 break;
115 }
116 }
117 else {
118 /* FEE Public key */
119 switch(format) {
120 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
121 format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
122 /* and drop thru */
123 case CSSM_KEYBLOB_RAW_FORMAT_NONE:
124 frtn = feePubKeyCreateDERPubBlob(keyToEncode, &keyBlob, &len);
125 break;
126 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
127 frtn = feePubKeyCreatePubBlob(keyToEncode, &keyBlob, &len);
128 break;
129 default:
130 badFormat = true;
131 break;
132 }
133 }
134 /* end of base ALGID_FEE */
135 break;
136
137 case CSSM_ALGID_ECDSA:
138 if(isPrivate) {
139 /* ECDSA/ECDH private key */
140 switch(format) {
141 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
142 /* ECDSA private key: PKCS8 */
143 frtn = feePubKeyCreatePKCS8Blob(keyToEncode, &keyBlob, &len);
144 break;
145 case CSSM_KEYBLOB_RAW_FORMAT_NONE:
146 /* set to default format, drop thru */
147 format = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL;
148 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
149 /* ECDSA private key, SEC1/OpenSSL format */
150 frtn = feePubKeyCreateOpenSSLBlob(keyToEncode, &keyBlob, &len);
151 break;
152 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
153 format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
154 /* and drop thru */
155 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
156 /* raw private key bytes */
157 frtn = feeCreateECDSAPrivBlob(keyToEncode, &keyBlob, &len);
158 break;
159 default:
160 badFormat = true;
161 break;
162 }
163 }
164 else {
165 /*
166 * ECDSA public key.
167 * Note there is no OpenSSL case here, that format is only generated for
168 * private keys.
169 */
170 switch(format) {
171 case CSSM_KEYBLOB_RAW_FORMAT_NONE:
172 /* set to default format, drop thru */
173 format = CSSM_KEYBLOB_RAW_FORMAT_X509;
174 case CSSM_KEYBLOB_RAW_FORMAT_X509:
175 /* ECDSA, public key, default: X509 */
176 frtn = feePubKeyCreateX509Blob(keyToEncode, &keyBlob, &len);
177 break;
178 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
179 format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
180 /* and drop thru */
181 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
182 /* raw x|y string */
183 frtn = feeCreateECDSAPubBlob(keyToEncode, &keyBlob, &len);
184 break;
185 default:
186 badFormat = true;
187 break;
188 }
189 }
190 /* end of case CSSM_ALGID_ECDSA */
191 break;
192 default:
193 /* not reached */
194 break;
195 }
196
197 if(badFormat) {
198 CssmError::throwMe(isPrivate ?
199 CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT :
200 CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
201 }
202 if(frtn) {
203 throwCryptKit(frtn, "feePubKeyCreate*Blob");
204 }
205 setUpCssmData(blob, len, allocator);
206 memmove(blob.data(), keyBlob, len);
207 blob.length(len);
208 ffree(keyBlob);
209 if(freeTheKey) {
210 /* free the temp pub key we created here */
211 feePubKeyFree(keyToEncode);
212 }
213 }
214
215 /***
216 *** FEE-style AppleKeyPairGenContext
217 ***/
218
219 /*
220 * This one is specified in, and called from, CSPFullPluginSession. Our
221 * only job is to prepare two subclass-specific BinaryKeys and call up to
222 * AppleKeyPairGenContext.
223 */
224 void CryptKit::FEEKeyPairGenContext::generate(
225 const Context &context,
226 CssmKey &pubKey,
227 CssmKey &privKey)
228 {
229 FEEBinaryKey *pubBinKey = new FEEBinaryKey();
230 FEEBinaryKey *privBinKey = new FEEBinaryKey();
231
232 try {
233 AppleKeyPairGenContext::generate(context,
234 session(),
235 pubKey,
236 pubBinKey,
237 privKey,
238 privBinKey);
239 }
240 catch (...) {
241 delete pubBinKey;
242 delete privBinKey;
243 throw;
244 }
245
246 }
247
248 // this one is specified in, and called from, AppleKeyPairGenContext
249 void CryptKit::FEEKeyPairGenContext::generate(
250 const Context &context,
251 BinaryKey &pubBinKey,
252 BinaryKey &privBinKey,
253 uint32 &keyBits)
254 {
255 /*
256 * These casts throw exceptions if the keys are of the
257 * wrong classes, which would be a major bogon, since we created
258 * the keys in the above generate() function.
259 */
260 FEEBinaryKey &fPubBinKey =
261 dynamic_cast<FEEBinaryKey &>(pubBinKey);
262 FEEBinaryKey &fPrivBinKey =
263 dynamic_cast<FEEBinaryKey &>(privBinKey);
264
265 /*
266 * Two parameters from context. Key size in bits is required;
267 * seed is optional. If not present, we cook up random private data.
268 */
269 keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH,
270 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
271 CssmCryptoData *cseed = context.get<CssmCryptoData>(CSSM_ATTRIBUTE_SEED);
272 CssmData *seed;
273 bool haveSeed;
274 CssmAutoData aSeed(session()); // malloc on demand
275 if(cseed) {
276 /* caller specified seed */
277 haveSeed = true;
278 seed = &cseed->param();
279 }
280 else {
281 /* generate random seed */
282 haveSeed = false;
283 unsigned keyBytes = ((keyBits + 7) / 8) + 1;
284 aSeed.malloc(keyBytes);
285 session().getRandomBytes(keyBytes, aSeed);
286 seed = &aSeed.get();
287 }
288
289 CSSM_ALGORITHMS algId = context.algorithm();
290
291 /* Curve and prime types - optional */
292 feePrimeType primeType = FPT_Default;
293 uint32 uPrimeType = context.getInt(CSSM_ATTRIBUTE_FEE_PRIME_TYPE);
294 switch(uPrimeType) {
295 case CSSM_FEE_PRIME_TYPE_DEFAULT:
296 break;
297 case CSSM_FEE_PRIME_TYPE_MERSENNE:
298 primeType = FPT_Mersenne;
299 break;
300 case CSSM_FEE_PRIME_TYPE_FEE:
301 primeType = FPT_FEE;
302 break;
303 case CSSM_FEE_PRIME_TYPE_GENERAL:
304 primeType = FPT_General;
305 break;
306 default:
307 /* FIXME - maybe we should be more specific */
308 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
309 }
310 feeCurveType curveType = FCT_Default;
311 switch(algId) {
312 case CSSM_ALGID_ECDSA:
313 /* no options */
314 curveType = FCT_ANSI;
315 break;
316 default:
317 {
318 uint32 uCurveType = context.getInt(CSSM_ATTRIBUTE_FEE_CURVE_TYPE);
319 switch(uCurveType) {
320 case CSSM_FEE_CURVE_TYPE_DEFAULT:
321 break;
322 case CSSM_FEE_CURVE_TYPE_MONTGOMERY:
323 curveType = FCT_Montgomery;
324 break;
325 case CSSM_FEE_CURVE_TYPE_WEIERSTRASS:
326 curveType = FCT_Weierstrass;
327 break;
328 case CSSM_FEE_CURVE_TYPE_ANSI_X9_62:
329 curveType = FCT_ANSI;
330 break;
331 default:
332 /* FIXME - maybe we should be more specific */
333 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
334 }
335 break;
336 }
337 }
338 feeReturn frtn = feePubKeyInitFromPrivDataKeyBits(
339 fPrivBinKey.feeKey(),
340 (unsigned char *)seed->data(),
341 (unsigned int)seed->length(),
342 keyBits,
343 primeType,
344 curveType,
345 /*
346 * our random seed: trust it
347 * caller's seed: hash it
348 */
349 haveSeed ? 1 : 0);
350 if(frtn) {
351 throwCryptKit(frtn, "feePubKeyInitFromPrivDataKeyBits");
352 }
353 frtn = feePubKeyInitPubKeyFromPriv(fPrivBinKey.feeKey(),
354 fPubBinKey.feeKey());
355 if(frtn) {
356 throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv");
357 }
358 }
359
360
361 /***
362 *** FEE-style CSPKeyInfoProvider.
363 ***/
364 CryptKit::FEEKeyInfoProvider::FEEKeyInfoProvider(
365 const CssmKey &cssmKey,
366 AppleCSPSession &session) :
367 CSPKeyInfoProvider(cssmKey, session)
368 {
369 }
370 CSPKeyInfoProvider *FEEKeyInfoProvider::provider(
371 const CssmKey &cssmKey,
372 AppleCSPSession &session)
373 {
374 switch(cssmKey.algorithm()) {
375 case CSSM_ALGID_FEE:
376 case CSSM_ALGID_ECDSA:
377 break;
378 default:
379 return NULL;
380 }
381 switch(cssmKey.keyClass()) {
382 case CSSM_KEYCLASS_PUBLIC_KEY:
383 case CSSM_KEYCLASS_PRIVATE_KEY:
384 /* FIXME - verify proper CSSM_KEYBLOB_RAW_FORMAT_xx */
385 break;
386 default:
387 return NULL;
388 }
389 /* OK, we'll handle this one */
390 return new FEEKeyInfoProvider(cssmKey, session);
391 }
392
393 /* Given a raw key, cook up a Binary key */
394 void CryptKit::FEEKeyInfoProvider::CssmKeyToBinary(
395 CssmKey *paramKey, // optional, ignored
396 CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT
397 BinaryKey **binKey)
398 {
399 *binKey = NULL;
400 feePubKey feeKey = NULL;
401
402 /* first cook up a feePubKey, then drop that into a BinaryKey */
403 feeKey = rawCssmKeyToFee(mKey);
404 FEEBinaryKey *feeBinKey = new FEEBinaryKey(feeKey);
405 *binKey = feeBinKey;
406 }
407
408 /*
409 * Obtain key size in bits.
410 * Currently only raw public keys are dealt with (they're the ones
411 * which come from certs, the only current use for this function).
412 * Note that if we need to handle ref keys, we'll need a session ref...
413 */
414 void CryptKit::FEEKeyInfoProvider::QueryKeySizeInBits(
415 CSSM_KEY_SIZE &keySize)
416 {
417 feePubKey feeKey = NULL;
418
419 if(mKey.blobType() != CSSM_KEYBLOB_RAW) {
420 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
421 }
422 feeKey = rawCssmKeyToFee(mKey);
423 keySize.LogicalKeySizeInBits = feePubKeyBitsize(feeKey);
424 keySize.EffectiveKeySizeInBits = keySize.LogicalKeySizeInBits;
425 feePubKeyFree(feeKey);
426 }
427
428 /*
429 * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST
430 * passthrough.
431 */
432 bool CryptKit::FEEKeyInfoProvider::getHashableBlob(
433 Allocator &allocator,
434 CssmData &blob) // blob to hash goes here
435 {
436 /*
437 * The optimized case, a raw key in the "proper" format already.
438 * Currently this is:
439 * FEE public key in default/NONE form (which happens to be DER)
440 */
441 assert(mKey.blobType() == CSSM_KEYBLOB_RAW);
442 if((mKey.algorithm() == CSSM_ALGID_FEE) &&
443 (mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_NONE) &&
444 (mKey.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY)) {
445 const CssmData &keyBlob = CssmData::overlay(mKey.KeyData);
446 copyCssmData(keyBlob, blob, allocator);
447 return true;
448 }
449
450 /* caller converts to binary and proceeds */
451 return false;
452 }
453
454 #endif /* CRYPTKIT_CSP_ENABLE */