]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_apple_csp / lib / RSA_DSA_utils.cpp
1 /*
2 * Copyright (c) 2000-2001,2011-2012,2014 Apple 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_utils.cpp
21 */
22
23 #include "RSA_DSA_utils.h"
24 #include "RSA_DSA_keys.h"
25 #include <opensslUtils/opensslAsn1.h>
26 #include <opensslUtils/opensslUtils.h>
27 #include <security_utilities/logging.h>
28 #include <security_utilities/debugging.h>
29 #include <openssl/bn.h>
30 #include <openssl/rsa.h>
31 #include <openssl/dsa.h>
32 #include <openssl/err.h>
33 #include <security_utilities/simpleprefs.h>
34 #include <security_utilities/threading.h>
35 #include <security_utilities/globalizer.h>
36 #include <CoreFoundation/CFNumber.h>
37
38 #define rsaMiscDebug(args...) secdebug("rsaMisc", ## args)
39
40 /*
41 * Obtain and cache max key sizes. System preferences only consulted
42 * at most once per process.
43 */
44
45 /*
46 * Do dictionary lookup, convert possible CFNumber to uint32.
47 * Does not alter val if valid number is not found.
48 */
49 static void rsaLookupVal(
50 Dictionary &prefs,
51 CFStringRef key,
52 uint32 &val)
53 {
54 CFNumberRef cfVal = (CFNumberRef)prefs.getValue(key);
55 if(cfVal == NULL) {
56 return;
57 }
58 if(CFGetTypeID(cfVal) != CFNumberGetTypeID()) {
59 return;
60 }
61
62 /* ensure the number is positive, not relying on gcc 64-bit arithmetic */
63 SInt32 s32 = 0;
64 CFNumberRef cfLimit = CFNumberCreate(NULL, kCFNumberSInt32Type, &s32);
65 CFComparisonResult result = CFNumberCompare(cfVal, cfLimit, NULL);
66 CFRelease(cfLimit);
67 if(result == kCFCompareLessThan) {
68 /* negative value in preference */
69 return;
70 }
71
72 /* ensure the number fits in 31 bits (the useful size of a SInt32 for us) */
73 s32 = 0x7fffffff;
74 cfLimit = CFNumberCreate(NULL, kCFNumberSInt32Type, &s32);
75 result = CFNumberCompare(cfVal, cfLimit, NULL);
76 CFRelease(cfLimit);
77 if(result == kCFCompareGreaterThan) {
78 /* too large; discard it */
79 return;
80 }
81 SInt64 s64;
82 if(!CFNumberGetValue(cfVal, kCFNumberSInt64Type, &s64)) {
83 /* impossible, right? We already range checked */
84 return;
85 }
86 val = (uint32)s64;
87 }
88
89 struct RSAKeySizes {
90 uint32 maxKeySize;
91 uint32 maxPubExponentSize;
92 RSAKeySizes();
93 };
94
95 /* one-time only prefs lookup */
96 RSAKeySizes::RSAKeySizes()
97 {
98 /* set defaults, these might get overridden */
99 maxKeySize = RSA_MAX_KEY_SIZE;
100 maxPubExponentSize = RSA_MAX_PUB_EXPONENT_SIZE;
101
102 /* now see if there are prefs set for either of these */
103 Dictionary* d = Dictionary::CreateDictionary(kRSAKeySizePrefsDomain, Dictionary::US_System, true);
104 if (!d)
105 {
106 return;
107 }
108
109 if (d->dict())
110 {
111 auto_ptr<Dictionary>apd(d);
112 rsaLookupVal(*apd, kRSAMaxKeySizePref, maxKeySize);
113 rsaLookupVal(*apd, kRSAMaxPublicExponentPref, maxPubExponentSize);
114 }
115 else
116 {
117 delete d;
118 }
119 }
120
121 static ModuleNexus<RSAKeySizes> rsaKeySizes;
122
123 /*
124 * Public functions to obtain the currently configured max sizes of
125 * RSA key and public exponent.
126 */
127 uint32 rsaMaxKeySize()
128 {
129 return rsaKeySizes().maxKeySize;
130 }
131
132 uint32 rsaMaxPubExponentSize()
133 {
134 return rsaKeySizes().maxPubExponentSize;
135 }
136
137 /*
138 * Given a Context:
139 * -- obtain CSSM key (there must only be one)
140 * -- validate keyClass
141 * -- validate keyUsage
142 * -- convert to RSA *, allocating the RSA key if necessary
143 */
144 RSA *contextToRsaKey(
145 const Context &context,
146 AppleCSPSession &session,
147 CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY
148 CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc.
149 bool &mallocdKey, // RETURNED
150 CSSM_DATA &label) // mallocd and RETURNED for OAEP
151 {
152 CssmKey &cssmKey =
153 context.get<CssmKey>(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY);
154 const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
155 if(hdr.AlgorithmId != CSSM_ALGID_RSA) {
156 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
157 }
158 if(hdr.KeyClass != keyClass) {
159 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
160 }
161 cspValidateIntendedKeyUsage(&hdr, usage);
162 cspVerifyKeyTimes(hdr);
163 return cssmKeyToRsa(cssmKey, session, mallocdKey, label);
164 }
165 /*
166 * Convert a CssmKey to an RSA * key. May result in the creation of a new
167 * RSA (when cssmKey is a raw key); allocdKey is true in that case
168 * in which case the caller generally has to free the allocd key).
169 */
170 RSA *cssmKeyToRsa(
171 const CssmKey &cssmKey,
172 AppleCSPSession &session,
173 bool &allocdKey, // RETURNED
174 CSSM_DATA &label) // mallocd and RETURNED for OAEP
175 {
176 RSA *rsaKey = NULL;
177 allocdKey = false;
178
179 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
180 if(hdr->AlgorithmId != CSSM_ALGID_RSA) {
181 // someone else's key (should never happen)
182 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
183 }
184 switch(hdr->BlobType) {
185 case CSSM_KEYBLOB_RAW:
186 rsaKey = rawCssmKeyToRsa(cssmKey, label);
187 allocdKey = true;
188 break;
189 case CSSM_KEYBLOB_REFERENCE:
190 {
191 BinaryKey &binKey = session.lookupRefKey(cssmKey);
192 RSABinaryKey *rsaBinKey = dynamic_cast<RSABinaryKey *>(&binKey);
193 /* this cast failing means that this is some other
194 * kind of binary key */
195 if(rsaBinKey == NULL) {
196 rsaMiscDebug("cssmKeyToRsa: wrong BinaryKey subclass\n");
197 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
198 }
199 assert(rsaBinKey->mRsaKey != NULL);
200 rsaKey = rsaBinKey->mRsaKey;
201 break;
202 }
203 default:
204 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
205 }
206 return rsaKey;
207 }
208
209 /*
210 * Convert a raw CssmKey to a newly alloc'd RSA key.
211 */
212 RSA *rawCssmKeyToRsa(
213 const CssmKey &cssmKey,
214 CSSM_DATA &label) // mallocd and RETURNED for OAEP keys
215 {
216 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
217 bool isPub;
218 bool isOaep = false;
219
220 assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
221
222 switch(hdr->AlgorithmId) {
223 case CSSM_ALGID_RSA:
224 break;
225 case CSSM_ALGMODE_PKCS1_EME_OAEP:
226 isOaep = true;
227 break;
228 default:
229 // someone else's key (should never happen)
230 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
231 }
232
233 /* validate and figure out what we're dealing with */
234 switch(hdr->KeyClass) {
235 case CSSM_KEYCLASS_PUBLIC_KEY:
236 switch(hdr->Format) {
237 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
238 case CSSM_KEYBLOB_RAW_FORMAT_X509:
239 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
240 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2:
241 break;
242 default:
243 CssmError::throwMe(
244 CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
245 }
246 if(isOaep && (hdr->Format != CSSM_KEYBLOB_RAW_FORMAT_X509)) {
247 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
248 }
249 isPub = true;
250 break;
251 case CSSM_KEYCLASS_PRIVATE_KEY:
252 switch(hdr->Format) {
253 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: // default
254 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: // openssl style
255 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
256 break;
257 default:
258 CssmError::throwMe(
259 CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT);
260 }
261 if(isOaep && (hdr->Format != CSSM_KEYBLOB_RAW_FORMAT_PKCS8)) {
262 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT);
263 }
264 isPub = false;
265 break;
266 default:
267 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
268 }
269
270 RSA *rsaKey = RSA_new();
271 if(rsaKey == NULL) {
272 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
273 }
274 CSSM_RETURN crtn;
275 if(isOaep) {
276 if(isPub) {
277 crtn = RSAOAEPPublicKeyDecode(rsaKey,
278 cssmKey.KeyData.Data, cssmKey.KeyData.Length,
279 &label);
280 }
281 else {
282 crtn = RSAOAEPPrivateKeyDecode(rsaKey,
283 cssmKey.KeyData.Data, cssmKey.KeyData.Length,
284 &label);
285 }
286 }
287 else {
288 if(isPub) {
289 crtn = RSAPublicKeyDecode(rsaKey, hdr->Format,
290 cssmKey.KeyData.Data, cssmKey.KeyData.Length);
291 }
292 else {
293 crtn = RSAPrivateKeyDecode(rsaKey, hdr->Format,
294 cssmKey.KeyData.Data, cssmKey.KeyData.Length);
295 }
296 }
297 if(crtn) {
298 RSA_free(rsaKey);
299 CssmError::throwMe(crtn);
300 }
301
302 /* enforce max key size and max public exponent size */
303 bool badKey = false;
304 uint32 keySize = RSA_size(rsaKey) * 8;
305 if(keySize > rsaMaxKeySize()) {
306 rsaMiscDebug("rawCssmKeyToRsa: key size exceeded");
307 badKey = true;
308 }
309 else {
310 keySize = BN_num_bytes(rsaKey->e) * 8;
311 if(keySize > rsaMaxPubExponentSize()) {
312 badKey = true;
313 rsaMiscDebug("rawCssmKeyToRsa: pub exponent size exceeded");
314 }
315 }
316 if(badKey) {
317 RSA_free(rsaKey);
318 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
319 }
320 return rsaKey;
321 }
322
323 /*
324 * Given a partially formed DSA public key (with no p, q, or g) and a
325 * CssmKey representing a supposedly fully-formed DSA key, populate
326 * the public key's p, g, and q with values from the fully formed key.
327 */
328 CSSM_RETURN dsaGetParamsFromKey(
329 DSA *partialKey,
330 const CssmKey &paramKey,
331 AppleCSPSession &session)
332 {
333 bool allocdKey;
334 DSA *dsaParamKey = cssmKeyToDsa(paramKey, session, allocdKey);
335 if(dsaParamKey == NULL) {
336 errorLog0("dsaGetParamsFromKey: bad paramKey\n");
337 return CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE;
338 }
339 CSSM_RETURN crtn = CSSM_OK;
340
341 /* require fully formed other key of course... */
342 if((dsaParamKey->p == NULL) ||
343 (dsaParamKey->q == NULL) ||
344 (dsaParamKey->g == NULL)) {
345 errorLog0("dsaGetParamsFromKey: incomplete paramKey\n");
346 crtn = CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE;
347 goto abort;
348 }
349 rsaMiscDebug("dsaGetParamsFromKey: partialKey %p paramKey %p",
350 partialKey, dsaParamKey);
351
352 partialKey->q = BN_dup(dsaParamKey->q);
353 partialKey->p = BN_dup(dsaParamKey->p);
354 partialKey->g = BN_dup(dsaParamKey->g);
355
356 abort:
357 if(allocdKey) {
358 DSA_free(dsaParamKey);
359 }
360 return crtn;
361 }
362
363 /*
364 * Given a Context:
365 * -- obtain CSSM key (there must only be one)
366 * -- validate keyClass
367 * -- validate keyUsage
368 * -- convert to DSA *, allocating the DSA key if necessary
369 */
370 DSA *contextToDsaKey(
371 const Context &context,
372 AppleCSPSession &session,
373 CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY
374 CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc.
375 bool &mallocdKey) // RETURNED
376 {
377 CssmKey &cssmKey =
378 context.get<CssmKey>(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY);
379 const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
380 if(hdr.AlgorithmId != CSSM_ALGID_DSA) {
381 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
382 }
383 if(hdr.KeyClass != keyClass) {
384 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
385 }
386 cspValidateIntendedKeyUsage(&hdr, usage);
387 cspVerifyKeyTimes(hdr);
388 DSA *rtnDsa = cssmKeyToDsa(cssmKey, session, mallocdKey);
389 if((keyClass == CSSM_KEYCLASS_PUBLIC_KEY) &&
390 (rtnDsa->p == NULL)) {
391 /*
392 * Special case: this specific key is only partially formed;
393 * it's missing the DSA parameters p, g, and q. To proceed with this
394 * key, the caller must pass in another fully formned DSA public key
395 * in raw form in the context. If it's there we use those parameters.
396 */
397 rsaMiscDebug("contextToDsaKey; partial DSA key %p", rtnDsa);
398 CssmKey *paramKey = context.get<CssmKey>(CSSM_ATTRIBUTE_PARAM_KEY);
399 if(paramKey == NULL) {
400 rsaMiscDebug("contextToDsaKey: missing DSA params, no pub key in "
401 "context");
402 if(mallocdKey) {
403 DSA_free(rtnDsa);
404 mallocdKey = false;
405 }
406 CssmError::throwMe(CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE);
407 }
408
409 /*
410 * If this is a ref key, we have to cook up a new DSA key to
411 * avoid modifying the existing key. If we started with a raw key,
412 * we can modify it directly since the underlying DSA key has
413 * a lifetime only as long as this context (and since the context
414 * contains the parameter-bearing key, the params are valid
415 * as long as the DSA key).
416 */
417 if(!mallocdKey) {
418 DSA *existKey = rtnDsa;
419 rtnDsa = DSA_new();
420 if(rtnDsa == NULL) {
421 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
422 }
423 rtnDsa->pub_key = BN_dup(existKey->pub_key);
424 rsaMiscDebug("contextToDsaKey; temp partial copy %p", rtnDsa);
425 mallocdKey = true;
426 }
427
428 /*
429 * Add params from paramKey into rtnDsa
430 */
431 CSSM_RETURN crtn = dsaGetParamsFromKey(rtnDsa, *paramKey, session);
432 if(crtn) {
433 if(mallocdKey) {
434 DSA_free(rtnDsa);
435 mallocdKey = false;
436 }
437 CssmError::throwMe(crtn);
438 }
439 }
440 return rtnDsa;
441 }
442
443 /*
444 * Convert a CssmKey to an DSA * key. May result in the creation of a new
445 * DSA (when cssmKey is a raw key); allocdKey is true in that case
446 * in which case the caller generally has to free the allocd key).
447 */
448 DSA *cssmKeyToDsa(
449 const CssmKey &cssmKey,
450 AppleCSPSession &session,
451 bool &allocdKey) // RETURNED
452 {
453 DSA *dsaKey = NULL;
454 allocdKey = false;
455
456 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
457 if(hdr->AlgorithmId != CSSM_ALGID_DSA) {
458 // someone else's key (should never happen)
459 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
460 }
461 switch(hdr->BlobType) {
462 case CSSM_KEYBLOB_RAW:
463 dsaKey = rawCssmKeyToDsa(cssmKey, session, NULL);
464 allocdKey = true;
465 break;
466 case CSSM_KEYBLOB_REFERENCE:
467 {
468 BinaryKey &binKey = session.lookupRefKey(cssmKey);
469 DSABinaryKey *dsaBinKey = dynamic_cast<DSABinaryKey *>(&binKey);
470 /* this cast failing means that this is some other
471 * kind of binary key */
472 if(dsaBinKey == NULL) {
473 rsaMiscDebug("cssmKeyToDsa: wrong BinaryKey subclass\n");
474 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
475 }
476 assert(dsaBinKey->mDsaKey != NULL);
477 dsaKey = dsaBinKey->mDsaKey;
478 break;
479 }
480 default:
481 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
482 }
483 return dsaKey;
484 }
485
486 /*
487 * Convert a raw CssmKey to a newly alloc'd DSA key.
488 */
489 DSA *rawCssmKeyToDsa(
490 const CssmKey &cssmKey,
491 AppleCSPSession &session,
492 const CssmKey *paramKey) // optional
493 {
494 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
495 bool isPub;
496
497 assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
498
499 if(hdr->AlgorithmId != CSSM_ALGID_DSA) {
500 // someone else's key (should never happen)
501 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
502 }
503 /* validate and figure out what we're dealing with */
504 switch(hdr->KeyClass) {
505 case CSSM_KEYCLASS_PUBLIC_KEY:
506 switch(hdr->Format) {
507 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
508 case CSSM_KEYBLOB_RAW_FORMAT_X509:
509 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2:
510 break;
511 default:
512 CssmError::throwMe(
513 CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
514 }
515 isPub = true;
516 break;
517 case CSSM_KEYCLASS_PRIVATE_KEY:
518 switch(hdr->Format) {
519 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: // default
520 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: // openssl style
521 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: // SMIME style
522 break;
523 /* openssh real soon now */
524 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
525 default:
526 CssmError::throwMe(
527 CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT);
528 }
529 isPub = false;
530 break;
531 default:
532 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
533 }
534
535 CSSM_RETURN crtn;
536 DSA *dsaKey = DSA_new();
537
538 if (dsaKey == NULL) {
539 crtn = CSSMERR_CSP_MEMORY_ERROR;
540 }
541 else {
542 if(dsaKey == NULL) {
543 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
544 }
545 if(isPub) {
546 crtn = DSAPublicKeyDecode(dsaKey, hdr->Format,
547 cssmKey.KeyData.Data,
548 cssmKey.KeyData.Length);
549 }
550 else {
551 crtn = DSAPrivateKeyDecode(dsaKey, hdr->Format,
552 cssmKey.KeyData.Data,
553 cssmKey.KeyData.Length);
554 }
555 }
556
557 if(crtn) {
558 if (dsaKey != NULL) {
559 DSA_free(dsaKey);
560 }
561
562 CssmError::throwMe(crtn);
563 }
564 /*
565 * Add in optional external parameters if this is not fully formed.
566 * This path is only taken from DSAKeyInfoProvider::CssmKeyToBinary,
567 * e.g., when doing a NULL unwrap of a partially formed DSA public
568 * key with the "complete the key with these params" option.
569 */
570 if(isPub && (dsaKey->p == NULL) && (paramKey != NULL)) {
571 rsaMiscDebug("rawCssmKeyToDsa; updating dsaKey %p", dsaKey);
572 crtn = dsaGetParamsFromKey(dsaKey, *paramKey, session);
573 if(crtn) {
574 DSA_free(dsaKey);
575 CssmError::throwMe(crtn);
576 }
577 }
578
579 if(dsaKey->p != NULL) {
580 /* avoid use of provided DSA key which exceeds the max size */
581 uint32 keySize = BN_num_bits(dsaKey->p);
582 if(keySize > DSA_MAX_KEY_SIZE) {
583 DSA_free(dsaKey);
584 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
585 }
586 }
587 return dsaKey;
588 }
589
590 /*
591 * Given a DSA private key, calculate its public component if it
592 * doesn't already exist. Used for calculating the key digest of
593 * an incoming raw private key.
594 */
595 void dsaKeyPrivToPub(
596 DSA *dsaKey)
597 {
598 assert(dsaKey != NULL);
599 assert(dsaKey->priv_key != NULL);
600
601 if(dsaKey->pub_key != NULL) {
602 return;
603 }
604
605 /* logic copied from DSA_generate_key() */
606 dsaKey->pub_key = BN_new();
607 if(dsaKey->pub_key == NULL) {
608 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
609 }
610 BN_CTX *ctx = BN_CTX_new();
611 if (ctx == NULL) {
612 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
613 }
614 int rtn = BN_mod_exp(dsaKey->pub_key,
615 dsaKey->g,
616 dsaKey->priv_key,
617 dsaKey->p,
618 ctx);
619 BN_CTX_free(ctx);
620 if(rtn == 0) {
621 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
622 }
623 }