]> git.saurik.com Git - apple/security.git/blob - AppleCSP/BSafeCSP/bsafeKeyGen.cpp
Security-29.tar.gz
[apple/security.git] / AppleCSP / BSafeCSP / bsafeKeyGen.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 #ifdef BSAFE_CSP_ENABLE
19
20
21 //
22 // bsafeKeyGen.cpp - key generation routines
23 //
24 #include "bsafecspi.h"
25 #include "bsafePKCS1.h"
26 #include "cspdebugging.h"
27
28 /*
29 * Stateless, private function to map a CSSM alg and pub/priv state
30 * to B_INFO_TYPE and format. Returns true on success, false on
31 * "I don't understand this algorithm".
32 */
33 bool BSafe::bsafeAlgToInfoType(
34 CSSM_ALGORITHMS alg,
35 bool isPublic,
36 B_INFO_TYPE &infoType, // RETURNED
37 CSSM_KEYBLOB_FORMAT &format) // RETURNED
38 {
39 switch(alg) {
40 case CSSM_ALGID_RSA:
41 if(isPublic) {
42 infoType = RSA_PUB_KEYINFO_TYPE;
43 format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
44 }
45 else {
46 infoType = RSA_PRIV_KEYINFO_TYPE;
47 format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
48 }
49 return true;
50 case CSSM_ALGID_DSA:
51 format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
52 if(isPublic) {
53 infoType = DSA_PUB_KEYINFO_TYPE;
54 }
55 else {
56 infoType = DSA_PRIV_KEYINFO_TYPE;
57 }
58 return true;
59 default:
60 return false;
61 }
62 }
63
64
65 BSafe::BSafeBinaryKey::BSafeBinaryKey(
66 bool isPub,
67 uint32 Alg)
68 : mIsPublic(isPub),
69 mAlg(Alg)
70 {
71 BSafe::check(B_CreateKeyObject(&mBsKey), true);
72 }
73
74 BSafe::BSafeBinaryKey::~BSafeBinaryKey()
75 {
76 B_DestroyKeyObject(&mBsKey);
77 }
78
79 void BSafe::BSafeBinaryKey::generateKeyBlob(
80 CssmAllocator &allocator,
81 CssmData &blob,
82 CSSM_KEYBLOB_FORMAT &format) // input val ignored for now
83 {
84 assert(mBsKey != NULL);
85
86 B_INFO_TYPE bsType;
87 if(!bsafeAlgToInfoType(mAlg, mIsPublic, bsType, format)) {
88 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
89 }
90 if(format == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
91 /* special case, encode the PKCS1 format blob */
92 CssmRemoteData rData(
93 CssmAllocator::standard(CssmAllocator::sensitive), blob);
94 BS_GetKeyPkcs1(mBsKey, rData);
95 rData.release();
96 }
97 else {
98 BSafeItem *info;
99 BSafe::check(
100 B_GetKeyInfo((POINTER *)&info, mBsKey, bsType), true);
101 blob = info->copy<CssmData>(allocator);
102 }
103 }
104
105 //
106 // This is called from CSPFullPluginSession
107 //
108 void BSafe::BSafeKeyPairGenContext::generate(
109 const Context &context,
110 CssmKey &pubKey,
111 CssmKey &privKey)
112 {
113 BSafeBinaryKey *pubBinKey = new BSafeBinaryKey(true,
114 context.algorithm());
115 BSafeBinaryKey *privBinKey = new BSafeBinaryKey(false,
116 context.algorithm());
117
118 try {
119 AppleKeyPairGenContext::generate(context,
120 session(),
121 pubKey,
122 pubBinKey,
123 privKey,
124 privBinKey);
125 }
126 catch (...) {
127 delete pubBinKey;
128 delete privBinKey;
129 throw;
130 }
131 }
132
133 //
134 // Called from AppleKeyPairGenContext
135 //
136 void BSafe::BSafeKeyPairGenContext::generate(
137 const Context &context,
138 BinaryKey &pubBinKey, // valid on successful return
139 BinaryKey &privBinKey, // ditto
140 uint32 &keySize) // ditto
141 {
142 /* these casts throw exceptions if the keys are of the
143 * wrong classes, which is a major bogon, since we created
144 * the keys in the above generate() function */
145 BSafeBinaryKey &bsPubBinKey =
146 dynamic_cast<BSafeBinaryKey &>(pubBinKey);
147 BSafeBinaryKey &bsPrivBinKey =
148 dynamic_cast<BSafeBinaryKey &>(privBinKey);
149
150 if (!initialized) {
151 setupAlgorithm(context, keySize);
152 check(B_GenerateInit(bsAlgorithm, chooser(), bsSurrender), true);
153 initialized = true;
154 }
155
156 setRandom();
157 check(B_GenerateKeypair(bsAlgorithm,
158 bsPubBinKey.bsKey(),
159 bsPrivBinKey.bsKey(),
160 bsRandom,
161 bsSurrender), true);
162 }
163
164 void BSafe::BSafeKeyPairGenContext::setupAlgorithm(
165 const Context &context,
166 uint32 &keySize)
167 {
168 switch(context.algorithm()) {
169 case CSSM_ALGID_RSA:
170 {
171 A_RSA_KEY_GEN_PARAMS genParams;
172 keySize = genParams.modulusBits =
173 context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH,
174 CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
175 if (CssmData *params =
176 context.get<CssmData>(CSSM_ATTRIBUTE_ALG_PARAMS)) {
177 genParams.publicExponent = BSafeItem(*params);
178 } else {
179 static unsigned char exponent[] = { 1, 0, 1 };
180 genParams.publicExponent = BSafeItem(exponent, sizeof(exponent));
181 }
182 /*
183 * For test purposes, we avoid the 'strong' key generate
184 * algorithm if a CSSM_ALGMODE_CUSTOM mode atrtribute
185 * is present in the context. This is not published and
186 * not supported in the real world.
187 */
188 uint32 mode = context.getInt(CSSM_ATTRIBUTE_MODE);
189 if(mode == CSSM_ALGMODE_CUSTOM) {
190 setAlgorithm(AI_RSAKeyGen, &genParams);
191 }
192 else {
193 setAlgorithm(AI_RSAStrongKeyGen, &genParams);
194 }
195 }
196 break;
197 case CSSM_ALGID_DSA:
198 {
199 A_DSA_PARAMS genParams;
200 genParams.prime =
201 BSafeItem(context.get<CssmData>(
202 CSSM_ATTRIBUTE_PRIME,
203 CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS));
204 genParams.subPrime =
205 BSafeItem(context.get<CssmData>(
206 CSSM_ATTRIBUTE_SUBPRIME,
207 CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS));
208 genParams.base =
209 BSafeItem(context.get<CssmData>(
210 CSSM_ATTRIBUTE_BASE,
211 CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS));
212 setAlgorithm(AI_DSAKeyGen, &genParams);
213 keySize = B_IntegerBits(genParams.prime.data, genParams.prime.len);
214 }
215 break;
216 default:
217 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
218 }
219 }
220
221 //
222 // DSA Parameter Generation
223 //
224 void BSafe::BSafeKeyPairGenContext::generate(
225 const Context &context,
226 uint32 bitSize,
227 CssmData &params,
228 uint32 &attrCount,
229 Context::Attr * &attrs)
230 {
231 assert(context.algorithm() == CSSM_ALGID_DSA);
232
233 B_ALGORITHM_OBJ genAlg = NULL;
234 B_ALGORITHM_OBJ result = NULL;
235
236 try {
237 check(B_CreateAlgorithmObject(&genAlg));
238
239 B_DSA_PARAM_GEN_PARAMS genParams;
240 genParams.primeBits = bitSize;
241 check(B_SetAlgorithmInfo(genAlg, AI_DSAParamGen, POINTER(&genParams)));
242 setRandom();
243 check(B_GenerateInit(genAlg, chooser(), bsSurrender), true);
244 check(B_CreateAlgorithmObject(&result));
245 check(B_GenerateParameters(genAlg, result, bsRandom, bsSurrender));
246
247 // get parameters out of algorithm object
248 A_DSA_PARAMS *kParams = NULL;
249 check(B_GetAlgorithmInfo((POINTER *)&kParams, result, AI_DSAKeyGen), true);
250
251 // shred them into context attribute form
252 attrs = normAllocator->alloc<Context::Attr>(3);
253 attrs[0] = Context::Attr(CSSM_ATTRIBUTE_PRIME,
254 *BSafeItem(kParams->prime).copyp<CssmData>(*normAllocator));
255 attrs[1] = Context::Attr(CSSM_ATTRIBUTE_SUBPRIME,
256 *BSafeItem(kParams->subPrime).copyp<CssmData>(*normAllocator));
257 attrs[2] = Context::Attr(CSSM_ATTRIBUTE_BASE,
258 *BSafeItem(kParams->base).copyp<CssmData>(*normAllocator));
259 attrCount = 3;
260
261 // clean up
262 B_DestroyAlgorithmObject(&result);
263 B_DestroyAlgorithmObject(&genAlg);
264 } catch (...) {
265 // clean up
266 B_DestroyAlgorithmObject(&result);
267 B_DestroyAlgorithmObject(&genAlg);
268 throw;
269 }
270 }
271
272 /*
273 * CSPKeyInfoProvider for asymmetric BSAFE keys.
274 */
275 BSafe::BSafeKeyInfoProvider::BSafeKeyInfoProvider(
276 const CssmKey &cssmKey) :
277 CSPKeyInfoProvider(cssmKey)
278 {
279 switch(mKey.keyClass()) {
280 case CSSM_KEYCLASS_PUBLIC_KEY:
281 case CSSM_KEYCLASS_PRIVATE_KEY:
282 break;
283 default:
284 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
285 }
286 switch(mKey.algorithm()) {
287 case CSSM_ALGID_RSA:
288 case CSSM_ALGID_DSA:
289 break;
290 default:
291 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
292 }
293 /* OK, we'll handle this one */
294 return;
295 }
296
297 /* cook up a Binary key */
298 void BSafe::BSafeKeyInfoProvider::CssmKeyToBinary(
299 BinaryKey **binKey)
300 {
301 *binKey = NULL;
302
303 const CSSM_KEYHEADER *hdr = &mKey.KeyHeader;
304 assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
305
306 B_INFO_TYPE bsType;
307 CSSM_KEYBLOB_FORMAT format;
308 bool isPub;
309
310 switch(hdr->KeyClass) {
311 case CSSM_KEYCLASS_PUBLIC_KEY:
312 isPub = true;
313 break;
314 case CSSM_KEYCLASS_PRIVATE_KEY:
315 isPub = false;
316 break;
317 default:
318 // someone else's key
319 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
320 }
321 if(!bsafeAlgToInfoType(hdr->AlgorithmId, isPub, bsType, format)) {
322 // someone else's key
323 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
324 }
325 if(hdr->Format != format) {
326 dprintf0("BSafe::cssmKeyToBinary: format mismatch\n");
327 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
328 }
329
330 BSafeBinaryKey *bsBinKey = new BSafeBinaryKey(isPub,
331 hdr->AlgorithmId);
332
333 // set up key material as appropriate
334 if(format == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
335 /* special case, decode the PKCS1 format blob */
336 BS_setKeyPkcs1(mKey, bsBinKey->bsKey());
337 }
338 else {
339 /* normal case, use key blob as is */
340 BSafeItem item(mKey.KeyData);
341 BSafe::check(
342 B_SetKeyInfo(bsBinKey->bsKey(), bsType, POINTER(&item)), true);
343 }
344 *binKey = bsBinKey;
345 }
346
347 /*
348 * Obtain key size in bits.
349 */
350 void BSafe::BSafeKeyInfoProvider::QueryKeySizeInBits(
351 CSSM_KEY_SIZE &keySize)
352 {
353 if(mKey.blobType() != CSSM_KEYBLOB_RAW) {
354 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
355 }
356
357 /* cook up BSAFE key */
358 B_KEY_OBJ bKey;
359 A_RSA_KEY *rsaKeyInfo = NULL;
360 A_DSA_PUBLIC_KEY *dsaPubKeyInfo = NULL;
361 A_DSA_PRIVATE_KEY *dsaPrivKeyInfo = NULL;
362 ITEM *sizeItem = NULL;
363 BSafe::check(B_CreateKeyObject(&bKey), true);
364 B_INFO_TYPE infoType;
365
366 switch(mKey.algorithm()) {
367 case CSSM_ALGID_RSA:
368 switch(mKey.keyClass()) {
369 case CSSM_KEYCLASS_PUBLIC_KEY:
370 if(mKey.blobFormat() !=
371 CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
372 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
373 }
374
375 /* convert from PKCS1 blob to raw key */
376 BS_setKeyPkcs1(mKey, bKey);
377 infoType = KI_RSAPublic;
378 /* break to common RSA code */
379 break;
380 case CSSM_KEYCLASS_PRIVATE_KEY:
381 {
382 if(mKey.blobFormat() !=
383 CSSM_KEYBLOB_RAW_FORMAT_PKCS8) {
384 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
385 }
386
387 /* convert from PKCS8 blob to raw key */
388 BSafeItem item(mKey.KeyData);
389 BSafe::check(
390 B_SetKeyInfo(bKey, KI_PKCS_RSAPrivateBER,
391 POINTER(&item)), true);
392 infoType = KI_RSAPrivate;
393 break;
394 }
395 default:
396 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
397 }
398 rsaKeyInfo = getKey<A_RSA_KEY>(bKey, infoType);
399 sizeItem = &rsaKeyInfo->modulus;
400 break;
401
402 case CSSM_ALGID_DSA:
403 /* untested as of 9/11/00 */
404 if(mKey.blobFormat() !=
405 CSSM_KEYBLOB_RAW_FORMAT_FIPS186) {
406 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
407 }
408 switch(mKey.keyClass()) {
409 case CSSM_KEYCLASS_PUBLIC_KEY:
410 {
411 BSafeItem item(mKey.KeyData);
412 BSafe::check(B_SetKeyInfo(bKey,
413 DSA_PUB_KEYINFO_TYPE,
414 (POINTER)&item), true);
415
416 /* get the key bits */
417 dsaPubKeyInfo = getKey<A_DSA_PUBLIC_KEY>(bKey,
418 KI_DSAPublic);
419 sizeItem = &dsaPubKeyInfo->params.prime;
420 break;
421 }
422 case CSSM_KEYCLASS_PRIVATE_KEY:
423 {
424 BSafeItem item(mKey.KeyData);
425 BSafe::check(B_SetKeyInfo(bKey,
426 DSA_PRIV_KEYINFO_TYPE,
427 (POINTER)&item), true);
428
429 /* get the key bits */
430 dsaPrivKeyInfo = getKey<A_DSA_PRIVATE_KEY>(bKey,
431 KI_DSAPrivate);
432 sizeItem = &dsaPrivKeyInfo->params.prime;
433 break;
434 }
435 default:
436 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
437 }
438 break;
439 default:
440 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
441 }
442 uint32 iSize = B_IntegerBits(sizeItem->data, sizeItem->len);
443 keySize.LogicalKeySizeInBits = iSize;
444 keySize.EffectiveKeySizeInBits = iSize;
445 B_DestroyKeyObject(&bKey);
446 }
447
448 #endif /* BSAFE_CSP_ENABLE */
449