2 * Copyright (c) 2000-2001 Apple Computer, 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.
18 #ifdef BSAFE_CSP_ENABLE
22 // bsafeKeyGen.cpp - key generation routines
24 #include "bsafecspi.h"
25 #include "bsafePKCS1.h"
26 #include "cspdebugging.h"
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".
33 bool BSafe::bsafeAlgToInfoType(
36 B_INFO_TYPE
&infoType
, // RETURNED
37 CSSM_KEYBLOB_FORMAT
&format
) // RETURNED
42 infoType
= RSA_PUB_KEYINFO_TYPE
;
43 format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
46 infoType
= RSA_PRIV_KEYINFO_TYPE
;
47 format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;
51 format
= CSSM_KEYBLOB_RAW_FORMAT_FIPS186
;
53 infoType
= DSA_PUB_KEYINFO_TYPE
;
56 infoType
= DSA_PRIV_KEYINFO_TYPE
;
65 BSafe::BSafeBinaryKey::BSafeBinaryKey(
71 BSafe::check(B_CreateKeyObject(&mBsKey
), true);
74 BSafe::BSafeBinaryKey::~BSafeBinaryKey()
76 B_DestroyKeyObject(&mBsKey
);
79 void BSafe::BSafeBinaryKey::generateKeyBlob(
80 CssmAllocator
&allocator
,
82 CSSM_KEYBLOB_FORMAT
&format
) // input val ignored for now
84 assert(mBsKey
!= NULL
);
87 if(!bsafeAlgToInfoType(mAlg
, mIsPublic
, bsType
, format
)) {
88 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
90 if(format
== CSSM_KEYBLOB_RAW_FORMAT_PKCS1
) {
91 /* special case, encode the PKCS1 format blob */
93 CssmAllocator::standard(CssmAllocator::sensitive
), blob
);
94 BS_GetKeyPkcs1(mBsKey
, rData
);
100 B_GetKeyInfo((POINTER
*)&info
, mBsKey
, bsType
), true);
101 blob
= info
->copy
<CssmData
>(allocator
);
106 // This is called from CSPFullPluginSession
108 void BSafe::BSafeKeyPairGenContext::generate(
109 const Context
&context
,
113 BSafeBinaryKey
*pubBinKey
= new BSafeBinaryKey(true,
114 context
.algorithm());
115 BSafeBinaryKey
*privBinKey
= new BSafeBinaryKey(false,
116 context
.algorithm());
119 AppleKeyPairGenContext::generate(context
,
134 // Called from AppleKeyPairGenContext
136 void BSafe::BSafeKeyPairGenContext::generate(
137 const Context
&context
,
138 BinaryKey
&pubBinKey
, // valid on successful return
139 BinaryKey
&privBinKey
, // ditto
140 uint32
&keySize
) // ditto
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
);
151 setupAlgorithm(context
, keySize
);
152 check(B_GenerateInit(bsAlgorithm
, chooser(), bsSurrender
), true);
157 check(B_GenerateKeypair(bsAlgorithm
,
159 bsPrivBinKey
.bsKey(),
164 void BSafe::BSafeKeyPairGenContext::setupAlgorithm(
165 const Context
&context
,
168 switch(context
.algorithm()) {
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
);
179 static unsigned char exponent
[] = { 1, 0, 1 };
180 genParams
.publicExponent
= BSafeItem(exponent
, sizeof(exponent
));
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.
188 uint32 mode
= context
.getInt(CSSM_ATTRIBUTE_MODE
);
189 if(mode
== CSSM_ALGMODE_CUSTOM
) {
190 setAlgorithm(AI_RSAKeyGen
, &genParams
);
193 setAlgorithm(AI_RSAStrongKeyGen
, &genParams
);
199 A_DSA_PARAMS genParams
;
201 BSafeItem(context
.get
<CssmData
>(
202 CSSM_ATTRIBUTE_PRIME
,
203 CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS
));
205 BSafeItem(context
.get
<CssmData
>(
206 CSSM_ATTRIBUTE_SUBPRIME
,
207 CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS
));
209 BSafeItem(context
.get
<CssmData
>(
211 CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS
));
212 setAlgorithm(AI_DSAKeyGen
, &genParams
);
213 keySize
= B_IntegerBits(genParams
.prime
.data
, genParams
.prime
.len
);
217 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
222 // DSA Parameter Generation
224 void BSafe::BSafeKeyPairGenContext::generate(
225 const Context
&context
,
229 Context::Attr
* &attrs
)
231 assert(context
.algorithm() == CSSM_ALGID_DSA
);
233 B_ALGORITHM_OBJ genAlg
= NULL
;
234 B_ALGORITHM_OBJ result
= NULL
;
237 check(B_CreateAlgorithmObject(&genAlg
));
239 B_DSA_PARAM_GEN_PARAMS genParams
;
240 genParams
.primeBits
= bitSize
;
241 check(B_SetAlgorithmInfo(genAlg
, AI_DSAParamGen
, POINTER(&genParams
)));
243 check(B_GenerateInit(genAlg
, chooser(), bsSurrender
), true);
244 check(B_CreateAlgorithmObject(&result
));
245 check(B_GenerateParameters(genAlg
, result
, bsRandom
, bsSurrender
));
247 // get parameters out of algorithm object
248 A_DSA_PARAMS
*kParams
= NULL
;
249 check(B_GetAlgorithmInfo((POINTER
*)&kParams
, result
, AI_DSAKeyGen
), true);
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
));
262 B_DestroyAlgorithmObject(&result
);
263 B_DestroyAlgorithmObject(&genAlg
);
266 B_DestroyAlgorithmObject(&result
);
267 B_DestroyAlgorithmObject(&genAlg
);
273 * CSPKeyInfoProvider for asymmetric BSAFE keys.
275 BSafe::BSafeKeyInfoProvider::BSafeKeyInfoProvider(
276 const CssmKey
&cssmKey
) :
277 CSPKeyInfoProvider(cssmKey
)
281 CSPKeyInfoProvider
*BSafe::BSafeKeyInfoProvider::provider(
282 const CssmKey
&cssmKey
)
284 switch(cssmKey
.keyClass()) {
285 case CSSM_KEYCLASS_PUBLIC_KEY
:
286 case CSSM_KEYCLASS_PRIVATE_KEY
:
291 switch(mKey
.algorithm()) {
298 /* OK, we'll handle this one */
299 return new BSafeKeyInfoProvider(cssmKey
);
302 /* cook up a Binary key */
303 void BSafe::BSafeKeyInfoProvider::CssmKeyToBinary(
308 const CSSM_KEYHEADER
*hdr
= &mKey
.KeyHeader
;
309 assert(hdr
->BlobType
== CSSM_KEYBLOB_RAW
);
312 CSSM_KEYBLOB_FORMAT format
;
315 switch(hdr
->KeyClass
) {
316 case CSSM_KEYCLASS_PUBLIC_KEY
:
319 case CSSM_KEYCLASS_PRIVATE_KEY
:
323 // someone else's key
324 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
326 if(!bsafeAlgToInfoType(hdr
->AlgorithmId
, isPub
, bsType
, format
)) {
327 // someone else's key
328 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
330 if(hdr
->Format
!= format
) {
331 dprintf0("BSafe::cssmKeyToBinary: format mismatch\n");
332 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
335 BSafeBinaryKey
*bsBinKey
= new BSafeBinaryKey(isPub
,
338 // set up key material as appropriate
339 if(format
== CSSM_KEYBLOB_RAW_FORMAT_PKCS1
) {
340 /* special case, decode the PKCS1 format blob */
341 BS_setKeyPkcs1(mKey
, bsBinKey
->bsKey());
344 /* normal case, use key blob as is */
345 BSafeItem
item(mKey
.KeyData
);
347 B_SetKeyInfo(bsBinKey
->bsKey(), bsType
, POINTER(&item
)), true);
353 * Obtain key size in bits.
355 void BSafe::BSafeKeyInfoProvider::QueryKeySizeInBits(
356 CSSM_KEY_SIZE
&keySize
)
358 if(mKey
.blobType() != CSSM_KEYBLOB_RAW
) {
359 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
362 /* cook up BSAFE key */
364 A_RSA_KEY
*rsaKeyInfo
= NULL
;
365 A_DSA_PUBLIC_KEY
*dsaPubKeyInfo
= NULL
;
366 A_DSA_PRIVATE_KEY
*dsaPrivKeyInfo
= NULL
;
367 ITEM
*sizeItem
= NULL
;
368 BSafe::check(B_CreateKeyObject(&bKey
), true);
369 B_INFO_TYPE infoType
;
371 switch(mKey
.algorithm()) {
373 switch(mKey
.keyClass()) {
374 case CSSM_KEYCLASS_PUBLIC_KEY
:
375 if(mKey
.blobFormat() !=
376 CSSM_KEYBLOB_RAW_FORMAT_PKCS1
) {
377 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
380 /* convert from PKCS1 blob to raw key */
381 BS_setKeyPkcs1(mKey
, bKey
);
382 infoType
= KI_RSAPublic
;
383 /* break to common RSA code */
385 case CSSM_KEYCLASS_PRIVATE_KEY
:
387 if(mKey
.blobFormat() !=
388 CSSM_KEYBLOB_RAW_FORMAT_PKCS8
) {
389 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
392 /* convert from PKCS8 blob to raw key */
393 BSafeItem
item(mKey
.KeyData
);
395 B_SetKeyInfo(bKey
, KI_PKCS_RSAPrivateBER
,
396 POINTER(&item
)), true);
397 infoType
= KI_RSAPrivate
;
401 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
403 rsaKeyInfo
= getKey
<A_RSA_KEY
>(bKey
, infoType
);
404 sizeItem
= &rsaKeyInfo
->modulus
;
408 /* untested as of 9/11/00 */
409 if(mKey
.blobFormat() !=
410 CSSM_KEYBLOB_RAW_FORMAT_FIPS186
) {
411 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
413 switch(mKey
.keyClass()) {
414 case CSSM_KEYCLASS_PUBLIC_KEY
:
416 BSafeItem
item(mKey
.KeyData
);
417 BSafe::check(B_SetKeyInfo(bKey
,
418 DSA_PUB_KEYINFO_TYPE
,
419 (POINTER
)&item
), true);
421 /* get the key bits */
422 dsaPubKeyInfo
= getKey
<A_DSA_PUBLIC_KEY
>(bKey
,
424 sizeItem
= &dsaPubKeyInfo
->params
.prime
;
427 case CSSM_KEYCLASS_PRIVATE_KEY
:
429 BSafeItem
item(mKey
.KeyData
);
430 BSafe::check(B_SetKeyInfo(bKey
,
431 DSA_PRIV_KEYINFO_TYPE
,
432 (POINTER
)&item
), true);
434 /* get the key bits */
435 dsaPrivKeyInfo
= getKey
<A_DSA_PRIVATE_KEY
>(bKey
,
437 sizeItem
= &dsaPrivKeyInfo
->params
.prime
;
441 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
445 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
447 uint32 iSize
= B_IntegerBits(sizeItem
->data
, sizeItem
->len
);
448 keySize
.LogicalKeySizeInBits
= iSize
;
449 keySize
.EffectiveKeySizeInBits
= iSize
;
450 B_DestroyKeyObject(&bKey
);
453 #endif /* BSAFE_CSP_ENABLE */