]> git.saurik.com Git - apple/security.git/blame - AppleCSP/RSA_DSA/RSA_DSA_keys.cpp
Security-163.tar.gz
[apple/security.git] / AppleCSP / RSA_DSA / RSA_DSA_keys.cpp
CommitLineData
bac41a7b
A
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 * RSA_DSA_Keys.cpp - RSA, DSA related asymmetric key pair classes.
21 */
22
29654253 23#include "RSA_DSA_keys.h"
bac41a7b 24#include <opensslUtils/opensslUtils.h>
df0e469f 25#include <opensslUtils/opensslAsn1.h>
bac41a7b
A
26#include <Security/cssmdata.h>
27#include <AppleCSP/AppleCSPSession.h>
28#include <AppleCSP/AppleCSPUtils.h>
29#include <assert.h>
30#include <Security/debugging.h>
31#include "RSA_DSA_utils.h"
32#include <AppleCSP/YarrowConnection.h>
df0e469f 33#include <SecurityNssAsn1/SecNssCoder.h>
bac41a7b
A
34
35#define RSA_PUB_EXPONENT 0x10001 /* recommended by RSA */
36
df0e469f 37#define rsaKeyDebug(args...) secdebug("rsaKey", ## args)
bac41a7b
A
38
39/***
40 *** RSA-style BinaryKey
41 ***/
42
43/* constructor with optional existing RSA key */
44RSABinaryKey::RSABinaryKey(RSA *rsaKey)
45 : mRsaKey(rsaKey)
46{
47}
48
49RSABinaryKey::~RSABinaryKey()
50{
51 if(mRsaKey) {
52 RSA_free(mRsaKey);
53 mRsaKey = NULL;
54 }
55}
56
57void RSABinaryKey::generateKeyBlob(
58 CssmAllocator &allocator,
59 CssmData &blob,
df0e469f
A
60 CSSM_KEYBLOB_FORMAT &format, /* IN/OUT */
61 AppleCSPSession &session,
62 const CssmKey *paramKey, /* optional, unused here */
63 CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */
bac41a7b
A
64{
65 bool isPub;
66 CSSM_RETURN crtn;
67
df0e469f
A
68 /*
69 * Here, the incoming default of CSSM_KEYBLOB_RAW_FORMAT_NONE
70 * is translated to our AppleCSP-custom defaults. App can override.
71 */
bac41a7b
A
72 switch(mKeyHeader.KeyClass) {
73 case CSSM_KEYCLASS_PUBLIC_KEY:
74 isPub = true;
df0e469f
A
75 switch(format) {
76 case CSSM_KEYBLOB_RAW_FORMAT_NONE:
77 format = RSA_PUB_KEY_FORMAT; // default
78 break;
79 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
80 /* calculate digest on PKCS1 blob */
81 format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
82 break;
83 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
84 case CSSM_KEYBLOB_RAW_FORMAT_X509:
85 break;
86 default:
87 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT);
88 }
bac41a7b
A
89 break;
90 case CSSM_KEYCLASS_PRIVATE_KEY:
91 isPub = false;
df0e469f
A
92 switch(format) {
93 case CSSM_KEYBLOB_RAW_FORMAT_NONE: // default
94 format = RSA_PRIV_KEY_FORMAT;
95 break;
96 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
97 /* calculate digest on Public PKCS1 blob */
98 format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
99 isPub = true;
100 break;
101 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
102 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
103 break;
104 default:
105 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT);
106 }
bac41a7b
A
107 break;
108 default:
109 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
110 }
111
df0e469f 112 CssmAutoData encodedKey(allocator);
bac41a7b 113 if(isPub) {
df0e469f 114 crtn = RSAPublicKeyEncode(mRsaKey, format, encodedKey);
bac41a7b
A
115 }
116 else {
df0e469f 117 crtn = RSAPrivateKeyEncode(mRsaKey, format, encodedKey);
bac41a7b
A
118 }
119 if(crtn) {
120 CssmError::throwMe(crtn);
121 }
122 blob = encodedKey.release();
123}
124
125/***
126 *** RSA-style AppleKeyPairGenContext
127 ***/
128
129/*
130 * This one is specified in, and called from, CSPFullPluginSession. Our
131 * only job is to prepare two subclass-specific BinaryKeys and call up to
132 * AppleKeyPairGenContext.
133 */
134void RSAKeyPairGenContext::generate(
135 const Context &context,
136 CssmKey &pubKey,
137 CssmKey &privKey)
138{
139 RSABinaryKey *pubBinKey = new RSABinaryKey();
140 RSABinaryKey *privBinKey = new RSABinaryKey();
141
142 try {
143 AppleKeyPairGenContext::generate(context,
144 session(),
145 pubKey,
146 pubBinKey,
147 privKey,
148 privBinKey);
149 }
150 catch (...) {
151 delete pubBinKey;
152 delete privBinKey;
153 throw;
154 }
155
156}
157
158// this one is specified in, and called from, AppleKeyPairGenContext
159void RSAKeyPairGenContext::generate(
160 const Context &context,
161 BinaryKey &pubBinKey,
162 BinaryKey &privBinKey,
163 uint32 &keyBits)
164{
165 /*
166 * These casts throw exceptions if the keys are of the
167 * wrong classes, which would be a major bogon, since we created
168 * the keys in the above generate() function.
169 */
170 RSABinaryKey &rPubBinKey =
171 dynamic_cast<RSABinaryKey &>(pubBinKey);
172 RSABinaryKey &rPrivBinKey =
173 dynamic_cast<RSABinaryKey &>(privBinKey);
174
175 /*
176 * One parameter from context: Key size in bits is required.
177 * FIXME - get public exponent from context?
178 */
179 keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH,
180 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
181
182 /* generate the private key */
183 rPrivBinKey.mRsaKey = RSA_generate_key(keyBits,
184 RSA_PUB_EXPONENT,
185 NULL, // no callback
186 NULL);
187 if(rPrivBinKey.mRsaKey == NULL) {
188 rsaKeyDebug("RSA_generate_key returned NULL");
189 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); // ???
190 }
191
192 /* public key is subset of private key */
193 rPubBinKey.mRsaKey = RSA_new();
194 if(rPrivBinKey.mRsaKey == NULL) {
195 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
196 }
197 RSA *pub = rPubBinKey.mRsaKey;
198 RSA *priv = rPrivBinKey.mRsaKey;
199 pub->n = BN_dup(priv->n);
200 pub->e = BN_dup(priv->e);
201 if((pub->n == NULL) || (pub->e == NULL)) {
202 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
203 }
204}
205
206
207/***
208 *** RSA-style CSPKeyInfoProvider.
209 ***/
210RSAKeyInfoProvider::RSAKeyInfoProvider(
df0e469f
A
211 const CssmKey &cssmKey,
212 AppleCSPSession &session) :
213 CSPKeyInfoProvider(cssmKey, session)
29654253
A
214{
215}
216
217CSPKeyInfoProvider *RSAKeyInfoProvider::provider(
df0e469f
A
218 const CssmKey &cssmKey,
219 AppleCSPSession &session)
bac41a7b
A
220{
221 switch(cssmKey.algorithm()) {
222 case CSSM_ALGID_RSA:
223 break;
224 default:
29654253 225 return NULL;
bac41a7b
A
226 }
227 switch(cssmKey.keyClass()) {
228 case CSSM_KEYCLASS_PUBLIC_KEY:
229 case CSSM_KEYCLASS_PRIVATE_KEY:
230 break;
231 default:
29654253 232 return NULL;
bac41a7b
A
233 }
234 /* OK, we'll handle this one */
df0e469f 235 return new RSAKeyInfoProvider(cssmKey, session);
bac41a7b
A
236}
237
238/* Given a raw key, cook up a Binary key */
239void RSAKeyInfoProvider::CssmKeyToBinary(
df0e469f
A
240 CssmKey *paramKey, // ignored
241 CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT, unused here
242 BinaryKey **binKey)
bac41a7b
A
243{
244 *binKey = NULL;
245 RSA *rsaKey = NULL;
246
247 /* first cook up an RSA key, then drop that into a BinaryKey */
248 rsaKey = rawCssmKeyToRsa(mKey);
249 RSABinaryKey *rsaBinKey = new RSABinaryKey(rsaKey);
250 *binKey = rsaBinKey;
251}
252
253/*
254 * Obtain key size in bits.
255 */
256void RSAKeyInfoProvider::QueryKeySizeInBits(
257 CSSM_KEY_SIZE &keySize)
258{
259 RSA *rsaKey = NULL;
260
261 if(mKey.blobType() != CSSM_KEYBLOB_RAW) {
262 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
263 }
264 rsaKey = rawCssmKeyToRsa(mKey);
265 keySize.LogicalKeySizeInBits = RSA_size(rsaKey) * 8;
266 keySize.EffectiveKeySizeInBits = keySize.LogicalKeySizeInBits;
267 RSA_free(rsaKey);
268}
269
df0e469f
A
270/*
271 * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST
272 * passthrough.
273 */
274bool RSAKeyInfoProvider::getHashableBlob(
275 CssmAllocator &allocator,
276 CssmData &blob) // blob to hash goes here
277{
278 /*
279 * The optimized case, a raw key in the "proper" format already.
280 * Only public keys in PKCS1 format fit this bill.
281 */
282 assert(mKey.blobType() == CSSM_KEYBLOB_RAW);
283 bool useAsIs = false;
284
285 switch(mKey.keyClass()) {
286 case CSSM_KEYCLASS_PUBLIC_KEY:
287 if(mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
288 useAsIs = true;
289 }
290 break;
291 case CSSM_KEYCLASS_PRIVATE_KEY:
292 break;
293 default:
294 /* shouldn't be here */
295 assert(0);
296 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
297 }
298 if(useAsIs) {
299 const CssmData &keyBlob = CssmData::overlay(mKey.KeyData);
300 copyCssmData(keyBlob, blob, allocator);
301 return true;
302 }
303
304 /* caller converts to binary and proceeds */
305 return false;
306}
307
bac41a7b
A
308/***
309 *** DSA key support
310 ***/
311
312
313/***
314 *** DSA-style BinaryKey
315 ***/
316
317/* constructor with optional existing DSA key */
318DSABinaryKey::DSABinaryKey(DSA *dsaKey)
319 : mDsaKey(dsaKey)
320{
321}
322
323DSABinaryKey::~DSABinaryKey()
324{
325 if(mDsaKey) {
326 DSA_free(mDsaKey);
327 mDsaKey = NULL;
328 }
329}
330
331void DSABinaryKey::generateKeyBlob(
332 CssmAllocator &allocator,
333 CssmData &blob,
df0e469f
A
334 CSSM_KEYBLOB_FORMAT &format,
335 AppleCSPSession &session,
336 const CssmKey *paramKey, /* optional */
337 CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */
bac41a7b
A
338{
339 bool isPub;
340 CSSM_RETURN crtn;
341
df0e469f
A
342 /*
343 * Here, the incoming default of CSSM_KEYBLOB_RAW_FORMAT_NONE
344 * is translated to our AppleCSP-custom defaults. App can override.
345 */
bac41a7b
A
346 switch(mKeyHeader.KeyClass) {
347 case CSSM_KEYCLASS_PUBLIC_KEY:
348 isPub = true;
df0e469f
A
349 switch(format) {
350 case CSSM_KEYBLOB_RAW_FORMAT_NONE:
351 format = DSA_PUB_KEY_FORMAT; // default
352 break;
353 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
354 case CSSM_KEYBLOB_RAW_FORMAT_X509:
355 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
356 break;
357 default:
358 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT);
359 }
bac41a7b
A
360 break;
361 case CSSM_KEYCLASS_PRIVATE_KEY:
362 isPub = false;
df0e469f
A
363 switch(format) {
364 case CSSM_KEYBLOB_RAW_FORMAT_NONE:
365 format = DSA_PRIV_KEY_FORMAT; // default
366 break;
367 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
368 /*
369 * This is calculated on the public key, which
370 * is not part of a DSA private key's encoding...
371 * so first calculate the public key.
372 */
373 dsaKeyPrivToPub(mDsaKey);
374 isPub = true;
375 break;
376 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
377 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
378 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
379 break;
380 default:
381 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT);
382 }
bac41a7b
A
383 break;
384 default:
385 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
386 }
387
df0e469f
A
388 /* possible conversion from partial binary key to fully
389 * formed blob */
390 DSA *dsaToEncode = mDsaKey;
391 DSA *dsaUpgrade = NULL;
392 if(isPub &&
393 (mDsaKey->p == NULL) &&
394 (paramKey != NULL)) {
395 /*
396 * Don't modify BinaryKey; make a copy.
397 */
398 dsaUpgrade = DSA_new();
399 if(dsaUpgrade == NULL) {
400 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
401 }
402 dsaUpgrade->pub_key = BN_dup(mDsaKey->pub_key);
403 crtn = dsaGetParamsFromKey(dsaUpgrade, *paramKey, session);
404 if(crtn) {
405 DSA_free(dsaUpgrade);
406 CssmError::throwMe(crtn);
407 }
408
409 /* success - switch keys and inform caller of attr change */
410 dsaToEncode = dsaUpgrade;
411 attrFlags &= ~CSSM_KEYATTR_PARTIAL;
412 }
413
bac41a7b
A
414 CssmAutoData encodedKey(allocator);
415 if(isPub) {
df0e469f 416 crtn = DSAPublicKeyEncode(dsaToEncode, format, encodedKey);
bac41a7b
A
417 }
418 else {
df0e469f
A
419 crtn = DSAPrivateKeyEncode(dsaToEncode, format, encodedKey);
420 }
421 if(dsaUpgrade != NULL) {
422 /* temp key, get rid of it */
423 DSA_free(dsaUpgrade);
bac41a7b
A
424 }
425 if(crtn) {
426 CssmError::throwMe(crtn);
427 }
428 blob = encodedKey.release();
429}
df0e469f 430
bac41a7b
A
431/***
432 *** DSA-style AppleKeyPairGenContext
433 ***/
434
435/*
436 * This one is specified in, and called from, CSPFullPluginSession. Our
437 * only job is to prepare two subclass-specific BinaryKeys and call up to
438 * AppleKeyPairGenContext.
439 */
440void DSAKeyPairGenContext::generate(
441 const Context &context,
442 CssmKey &pubKey,
443 CssmKey &privKey)
444{
445 DSABinaryKey *pubBinKey = new DSABinaryKey();
446 DSABinaryKey *privBinKey = new DSABinaryKey();
447
448 try {
449 AppleKeyPairGenContext::generate(context,
450 session(),
451 pubKey,
452 pubBinKey,
453 privKey,
454 privBinKey);
455 }
456 catch (...) {
457 delete pubBinKey;
458 delete privBinKey;
459 throw;
460 }
461
462}
463
464/*
465 * This one is specified in, and called from, AppleKeyPairGenContext
466 */
467void DSAKeyPairGenContext::generate(
468 const Context &context,
469 BinaryKey &pubBinKey,
470 BinaryKey &privBinKey,
471 uint32 &keyBits)
472{
473 /*
474 * These casts throw exceptions if the keys are of the
475 * wrong classes, which would be a major bogon, since we created
476 * the keys in the above generate() function.
477 */
478 DSABinaryKey &rPubBinKey =
479 dynamic_cast<DSABinaryKey &>(pubBinKey);
480 DSABinaryKey &rPrivBinKey =
481 dynamic_cast<DSABinaryKey &>(privBinKey);
482
483 /*
484 * Parameters from context:
485 * Key size in bits, required;
486 * {p,q,g} from generateParams, optional
487 */
488 keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH,
489 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
490 CssmData *paramData = context.get<CssmData>(CSSM_ATTRIBUTE_ALG_PARAMS);
491
df0e469f
A
492 NSS_DSAAlgParams algParams;
493 SecNssCoder coder; // generated algParams mallocd from here
bac41a7b 494 if(paramData != NULL) {
df0e469f
A
495 /* this contains the DER encoding of a NSS_DSAAlgParams */
496 CSSM_RETURN crtn = DSADecodeAlgParams(algParams, paramData->Data,
497 paramData->Length, coder);
498 if(crtn) {
499 CssmError::throwMe(crtn);
bac41a7b
A
500 }
501 }
502 else {
503 /* no alg params specified; generate them now using null (random) seed */
df0e469f 504 dsaGenParams(keyBits, NULL, 0, algParams, coder);
bac41a7b
A
505 }
506
507 /* create key, stuff params into it */
508 rPrivBinKey.mDsaKey = DSA_new();
509 if(rPrivBinKey.mDsaKey == NULL) {
510 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
511 }
512 DSA *dsaKey = rPrivBinKey.mDsaKey;
df0e469f
A
513 dsaKey->p = cssmDataToBn(algParams.p);
514 dsaKey->q = cssmDataToBn(algParams.q);
515 dsaKey->g = cssmDataToBn(algParams.g);
bac41a7b
A
516
517 /* generate the key (both public and private capabilities) */
518 int irtn = DSA_generate_key(dsaKey);
519 if(!irtn) {
520 throwRsaDsa("DSA_generate_key");
521 }
522
523 /* public key is subset of private key */
524 rPubBinKey.mDsaKey = DSA_new();
525 if(rPrivBinKey.mDsaKey == NULL) {
526 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
527 }
528 DSA *pub = rPubBinKey.mDsaKey;
529 DSA *priv = rPrivBinKey.mDsaKey;
530 pub->p = BN_dup(priv->p);
531 pub->q = BN_dup(priv->q);
532 pub->g = BN_dup(priv->g);
533 pub->pub_key = BN_dup(priv->pub_key);
534 if((pub->p == NULL) || (pub->q == NULL) || (pub->g == NULL) ||
535 (pub->pub_key == NULL)) {
536 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
537 }
538}
539
540/*
541 * Generate keygen parameters, stash them in a context attr array for later use
542 * when actually generating the keys.
543 */
544void DSAKeyPairGenContext::generate(
545 const Context &context,
546 uint32 bitSize,
547 CssmData &params,
548 uint32 &attrCount,
549 Context::Attr * &attrs)
550{
551 void *seed = NULL;
552 unsigned seedLen = 0;
553
554 /* optional seed from context */
555 CssmData *seedData = context.get<CssmData>(CSSM_ATTRIBUTE_SEED);
556 if(seedData) {
557 seed = seedData->data();
558 seedLen = seedData->length();
559 }
560
df0e469f
A
561 /* generate the params, temp alloc from SecNssCoder */
562 NSS_DSAAlgParams algParams;
563 SecNssCoder coder;
564 dsaGenParams(bitSize, seed, seedLen, algParams, coder);
bac41a7b
A
565
566 /*
567 * Here comes the fun part.
568 * We "return" the DER encoding of these generated params in two ways:
569 * 1. Copy out to app via the params argument, mallocing if Data ptr is NULL.
570 * The app must free this.
571 * 2. Cook up a 1-element Context::attr array containing one ALG_PARAM attr,
572 * a CSSM_DATA_PTR containing the DER encoding. We have to save a ptr to
573 * this attr array and free it, the CSSM_DATA it points to, and the DER
574 * encoding *that* points to, in our destructor.
575 *
576 * First, DER encode.
577 */
bac41a7b 578 CssmAutoData aDerData(session());
df0e469f 579 DSAEncodeAlgParams(algParams, aDerData);
bac41a7b
A
580
581 /* copy/release that into a mallocd CSSM_DATA. */
582 CSSM_DATA_PTR derData = (CSSM_DATA_PTR)session().malloc(sizeof(CSSM_DATA));
583 *derData = aDerData.release();
584
585 /* stuff that into a one-element Attr array which we keep after returning */
586 freeGenAttrs();
587 mGenAttrs = (Context::Attr *)session().malloc(sizeof(Context::Attr));
588 mGenAttrs->AttributeType = CSSM_ATTRIBUTE_ALG_PARAMS;
589 mGenAttrs->AttributeLength = sizeof(CSSM_DATA);
590 mGenAttrs->Attribute.Data = derData;
591
592 /* and "return" this stuff */
593 copyCssmData(CssmData::overlay(*derData), params, session());
594 attrCount = 1;
595 attrs = mGenAttrs;
596}
597
598/* free mGenAttrs and its referents if present */
599void DSAKeyPairGenContext::freeGenAttrs()
600{
601 if(mGenAttrs == NULL) {
602 return;
603 }
604 if(mGenAttrs->Attribute.Data) {
605 if(mGenAttrs->Attribute.Data->Data) {
606 session().free(mGenAttrs->Attribute.Data->Data);
607 }
608 session().free(mGenAttrs->Attribute.Data);
609 }
610 session().free(mGenAttrs);
611}
612
613/*
614 * Generate DSA algorithm parameters from optional seed input, returning result
df0e469f 615 * into NSS_DSAAlgParamss.[pqg]. This is called from both GenerateParameters and from
bac41a7b
A
616 * KeyPairGenerate (if no GenerateParameters has yet been called).
617 */
618void DSAKeyPairGenContext::dsaGenParams(
df0e469f
A
619 uint32 keySizeInBits,
620 const void *inSeed, // optional
621 unsigned inSeedLen,
622 NSS_DSAAlgParams &algParams,
623 SecNssCoder &coder) // contents of algParams mallocd from here
bac41a7b
A
624{
625 unsigned char seedBuf[SHA1_DIGEST_SIZE];
626 void *seedPtr;
627
628 /* validate key size */
629 if((keySizeInBits < DSA_MIN_KEY_SIZE) ||
630 (keySizeInBits > DSA_MAX_KEY_SIZE) ||
631 (keySizeInBits & DSA_KEY_BITS_MASK)) {
632 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
633 }
634
635 /* seed from one of three sources */
636 if(inSeed == NULL) {
637 /* 20 random seed bytes */
638 session().getRandomBytes(SHA1_DIGEST_SIZE, seedBuf);
639 seedPtr = seedBuf;
640 }
641 else if(inSeedLen == SHA1_DIGEST_SIZE) {
642 /* perfect */
643 seedPtr = (void *)inSeed;
644 }
645 else {
646 /* hash caller's seed */
647 cspGenSha1Hash(inSeed, inSeedLen, seedBuf);
648 seedPtr = seedBuf;
649 }
650
651 DSA *dsaKey = DSA_generate_parameters(keySizeInBits,
652 (unsigned char *)seedPtr,
653 SHA1_DIGEST_SIZE,
654 NULL, // counter_ret
655 NULL, // h_ret
656 NULL,
657 NULL);
658 if(dsaKey == NULL) {
659 throwRsaDsa("DSA_generate_parameters");
660 }
661
df0e469f
A
662 /* stuff dsaKey->[pqg] into a caller's NSS_DSAAlgParams */
663 bnToCssmData(dsaKey->p, algParams.p, coder);
664 bnToCssmData(dsaKey->q, algParams.q, coder);
665 bnToCssmData(dsaKey->g, algParams.g, coder);
bac41a7b
A
666
667 DSA_free(dsaKey);
668}
669
670/***
671 *** DSA-style CSPKeyInfoProvider.
672 ***/
673DSAKeyInfoProvider::DSAKeyInfoProvider(
df0e469f
A
674 const CssmKey &cssmKey,
675 AppleCSPSession &session) :
676 CSPKeyInfoProvider(cssmKey, session)
bac41a7b 677{
29654253
A
678
679}
680CSPKeyInfoProvider *DSAKeyInfoProvider::provider(
df0e469f
A
681 const CssmKey &cssmKey,
682 AppleCSPSession &session)
29654253 683{
bac41a7b
A
684 switch(cssmKey.algorithm()) {
685 case CSSM_ALGID_DSA:
686 break;
687 default:
29654253 688 return NULL;
bac41a7b
A
689 }
690 switch(cssmKey.keyClass()) {
691 case CSSM_KEYCLASS_PUBLIC_KEY:
692 case CSSM_KEYCLASS_PRIVATE_KEY:
693 break;
694 default:
29654253 695 return NULL;
bac41a7b
A
696 }
697 /* OK, we'll handle this one */
df0e469f 698 return new DSAKeyInfoProvider(cssmKey, session);
bac41a7b
A
699}
700
701/* Given a raw key, cook up a Binary key */
702void DSAKeyInfoProvider::CssmKeyToBinary(
df0e469f
A
703 CssmKey *paramKey, // optional
704 CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT
705 BinaryKey **binKey)
bac41a7b
A
706{
707 *binKey = NULL;
708 DSA *dsaKey = NULL;
709
710 /* first cook up an DSA key, then drop that into a BinaryKey */
df0e469f
A
711 dsaKey = rawCssmKeyToDsa(mKey, mSession, paramKey);
712 if(dsaKey->p == NULL) {
713 attrFlags |= CSSM_KEYATTR_PARTIAL;
714 }
715 else {
716 attrFlags &= ~CSSM_KEYATTR_PARTIAL;
717 }
bac41a7b
A
718 DSABinaryKey *dsaBinKey = new DSABinaryKey(dsaKey);
719 *binKey = dsaBinKey;
720}
721
722/*
723 * Obtain key size in bits.
724 */
725void DSAKeyInfoProvider::QueryKeySizeInBits(
726 CSSM_KEY_SIZE &keySize)
727{
728 DSA *dsaKey = NULL;
729
730 if(mKey.blobType() != CSSM_KEYBLOB_RAW) {
731 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
732 }
df0e469f
A
733 dsaKey = rawCssmKeyToDsa(mKey,
734 mSession,
735 NULL); // no param key allowed here
736 if(dsaKey->p != NULL) {
737 /* normal fully-formed key */
738 keySize.LogicalKeySizeInBits = BN_num_bits(dsaKey->p);
739 keySize.EffectiveKeySizeInBits = keySize.LogicalKeySizeInBits;
740 DSA_free(dsaKey);
741 }
742 else {
743 /* partial key, get an approximation from pub_key */
744 keySize.LogicalKeySizeInBits = BN_num_bits(dsaKey->pub_key);
745 DSA_free(dsaKey);
746 /* and indicate this anomaly like so */
747 CssmError::throwMe(CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE);
748 }
749}
750
751/*
752 * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST
753 * passthrough.
754 */
755bool DSAKeyInfoProvider::getHashableBlob(
756 CssmAllocator &allocator,
757 CssmData &blob) // blob to hash goes here
758{
759 /* No optimized case for DSA keys */
760 return false;
bac41a7b 761}