2 * Copyright (c) 2000-2001,2011,2014 Apple 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(
82 CSSM_KEYBLOB_FORMAT
&format
, // input val ignored for now
83 AppleCSPSession
&session
,
84 const CssmKey
*paramKey
, // optional, unused here
85 CSSM_KEYATTR_FLAGS
&attrFlags
) // IN/OUT
87 assert(mBsKey
!= NULL
);
90 if(!bsafeAlgToInfoType(mAlg
, mIsPublic
, bsType
, format
)) {
91 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
93 if(format
== CSSM_KEYBLOB_RAW_FORMAT_PKCS1
) {
94 /* special case, encode the PKCS1 format blob */
96 Allocator::standard(Allocator::sensitive
), blob
);
97 BS_GetKeyPkcs1(mBsKey
, rData
);
103 B_GetKeyInfo((POINTER
*)&info
, mBsKey
, bsType
), true);
104 blob
= info
->copy
<CssmData
>(allocator
);
109 // This is called from CSPFullPluginSession
111 void BSafe::BSafeKeyPairGenContext::generate(
112 const Context
&context
,
116 BSafeBinaryKey
*pubBinKey
= new BSafeBinaryKey(true,
117 context
.algorithm());
118 BSafeBinaryKey
*privBinKey
= new BSafeBinaryKey(false,
119 context
.algorithm());
122 AppleKeyPairGenContext::generate(context
,
137 // Called from AppleKeyPairGenContext
139 void BSafe::BSafeKeyPairGenContext::generate(
140 const Context
&context
,
141 BinaryKey
&pubBinKey
, // valid on successful return
142 BinaryKey
&privBinKey
, // ditto
143 uint32
&keySize
) // ditto
145 /* these casts throw exceptions if the keys are of the
146 * wrong classes, which is a major bogon, since we created
147 * the keys in the above generate() function */
148 BSafeBinaryKey
&bsPubBinKey
=
149 dynamic_cast<BSafeBinaryKey
&>(pubBinKey
);
150 BSafeBinaryKey
&bsPrivBinKey
=
151 dynamic_cast<BSafeBinaryKey
&>(privBinKey
);
154 setupAlgorithm(context
, keySize
);
155 check(B_GenerateInit(bsAlgorithm
, chooser(), bsSurrender
), true);
160 check(B_GenerateKeypair(bsAlgorithm
,
162 bsPrivBinKey
.bsKey(),
167 void BSafe::BSafeKeyPairGenContext::setupAlgorithm(
168 const Context
&context
,
171 switch(context
.algorithm()) {
174 A_RSA_KEY_GEN_PARAMS genParams
;
175 keySize
= genParams
.modulusBits
=
176 context
.getInt(CSSM_ATTRIBUTE_KEY_LENGTH
,
177 CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH
);
178 if (CssmData
*params
=
179 context
.get
<CssmData
>(CSSM_ATTRIBUTE_ALG_PARAMS
)) {
180 genParams
.publicExponent
= BSafeItem(*params
);
182 static unsigned char exponent
[] = { 1, 0, 1 };
183 genParams
.publicExponent
= BSafeItem(exponent
, sizeof(exponent
));
186 * For test purposes, we avoid the 'strong' key generate
187 * algorithm if a CSSM_ALGMODE_CUSTOM mode atrtribute
188 * is present in the context. This is not published and
189 * not supported in the real world.
191 uint32 mode
= context
.getInt(CSSM_ATTRIBUTE_MODE
);
192 if(mode
== CSSM_ALGMODE_CUSTOM
) {
193 setAlgorithm(AI_RSAKeyGen
, &genParams
);
196 setAlgorithm(AI_RSAStrongKeyGen
, &genParams
);
202 A_DSA_PARAMS genParams
;
204 BSafeItem(context
.get
<CssmData
>(
205 CSSM_ATTRIBUTE_PRIME
,
206 CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS
));
208 BSafeItem(context
.get
<CssmData
>(
209 CSSM_ATTRIBUTE_SUBPRIME
,
210 CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS
));
212 BSafeItem(context
.get
<CssmData
>(
214 CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS
));
215 setAlgorithm(AI_DSAKeyGen
, &genParams
);
216 keySize
= B_IntegerBits(genParams
.prime
.data
, genParams
.prime
.len
);
220 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
225 // DSA Parameter Generation
227 void BSafe::BSafeKeyPairGenContext::generate(
228 const Context
&context
,
232 Context::Attr
* &attrs
)
234 assert(context
.algorithm() == CSSM_ALGID_DSA
);
236 B_ALGORITHM_OBJ genAlg
= NULL
;
237 B_ALGORITHM_OBJ result
= NULL
;
240 check(B_CreateAlgorithmObject(&genAlg
));
242 B_DSA_PARAM_GEN_PARAMS genParams
;
243 genParams
.primeBits
= bitSize
;
244 check(B_SetAlgorithmInfo(genAlg
, AI_DSAParamGen
, POINTER(&genParams
)));
246 check(B_GenerateInit(genAlg
, chooser(), bsSurrender
), true);
247 check(B_CreateAlgorithmObject(&result
));
248 check(B_GenerateParameters(genAlg
, result
, bsRandom
, bsSurrender
));
250 // get parameters out of algorithm object
251 A_DSA_PARAMS
*kParams
= NULL
;
252 check(B_GetAlgorithmInfo((POINTER
*)&kParams
, result
, AI_DSAKeyGen
), true);
254 // shred them into context attribute form
255 attrs
= normAllocator
->alloc
<Context::Attr
>(3);
256 attrs
[0] = Context::Attr(CSSM_ATTRIBUTE_PRIME
,
257 *BSafeItem(kParams
->prime
).copyp
<CssmData
>(*normAllocator
));
258 attrs
[1] = Context::Attr(CSSM_ATTRIBUTE_SUBPRIME
,
259 *BSafeItem(kParams
->subPrime
).copyp
<CssmData
>(*normAllocator
));
260 attrs
[2] = Context::Attr(CSSM_ATTRIBUTE_BASE
,
261 *BSafeItem(kParams
->base
).copyp
<CssmData
>(*normAllocator
));
265 B_DestroyAlgorithmObject(&result
);
266 B_DestroyAlgorithmObject(&genAlg
);
269 B_DestroyAlgorithmObject(&result
);
270 B_DestroyAlgorithmObject(&genAlg
);
276 * CSPKeyInfoProvider for asymmetric BSAFE keys.
278 BSafe::BSafeKeyInfoProvider::BSafeKeyInfoProvider(
279 const CssmKey
&cssmKey
,
280 AppleCSPSession
&session
) :
281 CSPKeyInfoProvider(cssmKey
, session
)
285 CSPKeyInfoProvider
*BSafe::BSafeKeyInfoProvider::provider(
286 const CssmKey
&cssmKey
,
287 AppleCSPSession
&session
)
289 switch(cssmKey
.keyClass()) {
290 case CSSM_KEYCLASS_PUBLIC_KEY
:
291 case CSSM_KEYCLASS_PRIVATE_KEY
:
296 switch(mKey
.algorithm()) {
303 /* OK, we'll handle this one */
304 return new BSafeKeyInfoProvider(cssmKey
, session
);
307 /* cook up a Binary key */
308 void BSafe::BSafeKeyInfoProvider::CssmKeyToBinary(
309 CssmKey
*paramKey
, // optional, ignored
310 CSSM_KEYATTR_FLAGS
&attrFlags
, // IN/OUT
315 const CSSM_KEYHEADER
*hdr
= &mKey
.KeyHeader
;
316 assert(hdr
->BlobType
== CSSM_KEYBLOB_RAW
);
319 CSSM_KEYBLOB_FORMAT format
;
322 switch(hdr
->KeyClass
) {
323 case CSSM_KEYCLASS_PUBLIC_KEY
:
326 case CSSM_KEYCLASS_PRIVATE_KEY
:
330 // someone else's key
331 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
333 if(!bsafeAlgToInfoType(hdr
->AlgorithmId
, isPub
, bsType
, format
)) {
334 // someone else's key
335 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
337 if(hdr
->Format
!= format
) {
338 dprintf0("BSafe::cssmKeyToBinary: format mismatch\n");
339 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
342 BSafeBinaryKey
*bsBinKey
= new BSafeBinaryKey(isPub
,
345 // set up key material as appropriate
346 if(format
== CSSM_KEYBLOB_RAW_FORMAT_PKCS1
) {
347 /* special case, decode the PKCS1 format blob */
348 BS_setKeyPkcs1(mKey
, bsBinKey
->bsKey());
351 /* normal case, use key blob as is */
352 BSafeItem
item(mKey
.KeyData
);
354 B_SetKeyInfo(bsBinKey
->bsKey(), bsType
, POINTER(&item
)), true);
360 * Obtain key size in bits.
362 void BSafe::BSafeKeyInfoProvider::QueryKeySizeInBits(
363 CSSM_KEY_SIZE
&keySize
)
365 if(mKey
.blobType() != CSSM_KEYBLOB_RAW
) {
366 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
369 /* cook up BSAFE key */
371 A_RSA_KEY
*rsaKeyInfo
= NULL
;
372 A_DSA_PUBLIC_KEY
*dsaPubKeyInfo
= NULL
;
373 A_DSA_PRIVATE_KEY
*dsaPrivKeyInfo
= NULL
;
374 ITEM
*sizeItem
= NULL
;
375 BSafe::check(B_CreateKeyObject(&bKey
), true);
376 B_INFO_TYPE infoType
;
378 switch(mKey
.algorithm()) {
380 switch(mKey
.keyClass()) {
381 case CSSM_KEYCLASS_PUBLIC_KEY
:
382 if(mKey
.blobFormat() !=
383 CSSM_KEYBLOB_RAW_FORMAT_PKCS1
) {
384 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
387 /* convert from PKCS1 blob to raw key */
388 BS_setKeyPkcs1(mKey
, bKey
);
389 infoType
= KI_RSAPublic
;
390 /* break to common RSA code */
392 case CSSM_KEYCLASS_PRIVATE_KEY
:
394 if(mKey
.blobFormat() !=
395 CSSM_KEYBLOB_RAW_FORMAT_PKCS8
) {
396 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
399 /* convert from PKCS8 blob to raw key */
400 BSafeItem
item(mKey
.KeyData
);
402 B_SetKeyInfo(bKey
, KI_PKCS_RSAPrivateBER
,
403 POINTER(&item
)), true);
404 infoType
= KI_RSAPrivate
;
408 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
410 rsaKeyInfo
= getKey
<A_RSA_KEY
>(bKey
, infoType
);
411 sizeItem
= &rsaKeyInfo
->modulus
;
415 /* untested as of 9/11/00 */
416 if(mKey
.blobFormat() !=
417 CSSM_KEYBLOB_RAW_FORMAT_FIPS186
) {
418 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT
);
420 switch(mKey
.keyClass()) {
421 case CSSM_KEYCLASS_PUBLIC_KEY
:
423 BSafeItem
item(mKey
.KeyData
);
424 BSafe::check(B_SetKeyInfo(bKey
,
425 DSA_PUB_KEYINFO_TYPE
,
426 (POINTER
)&item
), true);
428 /* get the key bits */
429 dsaPubKeyInfo
= getKey
<A_DSA_PUBLIC_KEY
>(bKey
,
431 sizeItem
= &dsaPubKeyInfo
->params
.prime
;
434 case CSSM_KEYCLASS_PRIVATE_KEY
:
436 BSafeItem
item(mKey
.KeyData
);
437 BSafe::check(B_SetKeyInfo(bKey
,
438 DSA_PRIV_KEYINFO_TYPE
,
439 (POINTER
)&item
), true);
441 /* get the key bits */
442 dsaPrivKeyInfo
= getKey
<A_DSA_PRIVATE_KEY
>(bKey
,
444 sizeItem
= &dsaPrivKeyInfo
->params
.prime
;
448 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
452 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
454 uint32 iSize
= B_IntegerBits(sizeItem
->data
, sizeItem
->len
);
455 keySize
.LogicalKeySizeInBits
= iSize
;
456 keySize
.EffectiveKeySizeInBits
= iSize
;
457 B_DestroyKeyObject(&bKey
);
460 #endif /* BSAFE_CSP_ENABLE */