]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / 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 (BN_is_one(rsaKey->e)) {
317 badKey = true;
318 rsaMiscDebug("rawCssmKeyToRsa: e = 1");
319 }
320 if(badKey) {
321 RSA_free(rsaKey);
322 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
323 }
324 return rsaKey;
325 }
326
327 /*
328 * Given a partially formed DSA public key (with no p, q, or g) and a
329 * CssmKey representing a supposedly fully-formed DSA key, populate
330 * the public key's p, g, and q with values from the fully formed key.
331 */
332 CSSM_RETURN dsaGetParamsFromKey(
333 DSA *partialKey,
334 const CssmKey &paramKey,
335 AppleCSPSession &session)
336 {
337 bool allocdKey;
338 DSA *dsaParamKey = cssmKeyToDsa(paramKey, session, allocdKey);
339 if(dsaParamKey == NULL) {
340 errorLog0("dsaGetParamsFromKey: bad paramKey\n");
341 return CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE;
342 }
343 CSSM_RETURN crtn = CSSM_OK;
344
345 /* require fully formed other key of course... */
346 if((dsaParamKey->p == NULL) ||
347 (dsaParamKey->q == NULL) ||
348 (dsaParamKey->g == NULL)) {
349 errorLog0("dsaGetParamsFromKey: incomplete paramKey\n");
350 crtn = CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE;
351 goto abort;
352 }
353 rsaMiscDebug("dsaGetParamsFromKey: partialKey %p paramKey %p",
354 partialKey, dsaParamKey);
355
356 partialKey->q = BN_dup(dsaParamKey->q);
357 partialKey->p = BN_dup(dsaParamKey->p);
358 partialKey->g = BN_dup(dsaParamKey->g);
359
360 abort:
361 if(allocdKey) {
362 DSA_free(dsaParamKey);
363 }
364 return crtn;
365 }
366
367 /*
368 * Given a Context:
369 * -- obtain CSSM key (there must only be one)
370 * -- validate keyClass
371 * -- validate keyUsage
372 * -- convert to DSA *, allocating the DSA key if necessary
373 */
374 DSA *contextToDsaKey(
375 const Context &context,
376 AppleCSPSession &session,
377 CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY
378 CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc.
379 bool &mallocdKey) // RETURNED
380 {
381 CssmKey &cssmKey =
382 context.get<CssmKey>(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY);
383 const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
384 if(hdr.AlgorithmId != CSSM_ALGID_DSA) {
385 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
386 }
387 if(hdr.KeyClass != keyClass) {
388 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
389 }
390 cspValidateIntendedKeyUsage(&hdr, usage);
391 cspVerifyKeyTimes(hdr);
392 DSA *rtnDsa = cssmKeyToDsa(cssmKey, session, mallocdKey);
393 if((keyClass == CSSM_KEYCLASS_PUBLIC_KEY) &&
394 (rtnDsa->p == NULL)) {
395 /*
396 * Special case: this specific key is only partially formed;
397 * it's missing the DSA parameters p, g, and q. To proceed with this
398 * key, the caller must pass in another fully formned DSA public key
399 * in raw form in the context. If it's there we use those parameters.
400 */
401 rsaMiscDebug("contextToDsaKey; partial DSA key %p", rtnDsa);
402 CssmKey *paramKey = context.get<CssmKey>(CSSM_ATTRIBUTE_PARAM_KEY);
403 if(paramKey == NULL) {
404 rsaMiscDebug("contextToDsaKey: missing DSA params, no pub key in "
405 "context");
406 if(mallocdKey) {
407 DSA_free(rtnDsa);
408 mallocdKey = false;
409 }
410 CssmError::throwMe(CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE);
411 }
412
413 /*
414 * If this is a ref key, we have to cook up a new DSA key to
415 * avoid modifying the existing key. If we started with a raw key,
416 * we can modify it directly since the underlying DSA key has
417 * a lifetime only as long as this context (and since the context
418 * contains the parameter-bearing key, the params are valid
419 * as long as the DSA key).
420 */
421 if(!mallocdKey) {
422 DSA *existKey = rtnDsa;
423 rtnDsa = DSA_new();
424 if(rtnDsa == NULL) {
425 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
426 }
427 rtnDsa->pub_key = BN_dup(existKey->pub_key);
428 rsaMiscDebug("contextToDsaKey; temp partial copy %p", rtnDsa);
429 mallocdKey = true;
430 }
431
432 /*
433 * Add params from paramKey into rtnDsa
434 */
435 CSSM_RETURN crtn = dsaGetParamsFromKey(rtnDsa, *paramKey, session);
436 if(crtn) {
437 if(mallocdKey) {
438 DSA_free(rtnDsa);
439 mallocdKey = false;
440 }
441 CssmError::throwMe(crtn);
442 }
443 }
444 return rtnDsa;
445 }
446
447 /*
448 * Convert a CssmKey to an DSA * key. May result in the creation of a new
449 * DSA (when cssmKey is a raw key); allocdKey is true in that case
450 * in which case the caller generally has to free the allocd key).
451 */
452 DSA *cssmKeyToDsa(
453 const CssmKey &cssmKey,
454 AppleCSPSession &session,
455 bool &allocdKey) // RETURNED
456 {
457 DSA *dsaKey = NULL;
458 allocdKey = false;
459
460 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
461 if(hdr->AlgorithmId != CSSM_ALGID_DSA) {
462 // someone else's key (should never happen)
463 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
464 }
465 switch(hdr->BlobType) {
466 case CSSM_KEYBLOB_RAW:
467 dsaKey = rawCssmKeyToDsa(cssmKey, session, NULL);
468 allocdKey = true;
469 break;
470 case CSSM_KEYBLOB_REFERENCE:
471 {
472 BinaryKey &binKey = session.lookupRefKey(cssmKey);
473 DSABinaryKey *dsaBinKey = dynamic_cast<DSABinaryKey *>(&binKey);
474 /* this cast failing means that this is some other
475 * kind of binary key */
476 if(dsaBinKey == NULL) {
477 rsaMiscDebug("cssmKeyToDsa: wrong BinaryKey subclass\n");
478 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
479 }
480 assert(dsaBinKey->mDsaKey != NULL);
481 dsaKey = dsaBinKey->mDsaKey;
482 break;
483 }
484 default:
485 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
486 }
487 return dsaKey;
488 }
489
490 /*
491 * Convert a raw CssmKey to a newly alloc'd DSA key.
492 */
493 DSA *rawCssmKeyToDsa(
494 const CssmKey &cssmKey,
495 AppleCSPSession &session,
496 const CssmKey *paramKey) // optional
497 {
498 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
499 bool isPub;
500
501 assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
502
503 if(hdr->AlgorithmId != CSSM_ALGID_DSA) {
504 // someone else's key (should never happen)
505 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
506 }
507 /* validate and figure out what we're dealing with */
508 switch(hdr->KeyClass) {
509 case CSSM_KEYCLASS_PUBLIC_KEY:
510 switch(hdr->Format) {
511 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
512 case CSSM_KEYBLOB_RAW_FORMAT_X509:
513 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2:
514 break;
515 default:
516 CssmError::throwMe(
517 CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
518 }
519 isPub = true;
520 break;
521 case CSSM_KEYCLASS_PRIVATE_KEY:
522 switch(hdr->Format) {
523 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: // default
524 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: // openssl style
525 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: // SMIME style
526 break;
527 /* openssh real soon now */
528 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
529 default:
530 CssmError::throwMe(
531 CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT);
532 }
533 isPub = false;
534 break;
535 default:
536 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
537 }
538
539 CSSM_RETURN crtn;
540 DSA *dsaKey = DSA_new();
541
542 if (dsaKey == NULL) {
543 crtn = CSSMERR_CSP_MEMORY_ERROR;
544 }
545 else {
546 if(dsaKey == NULL) {
547 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
548 }
549 if(isPub) {
550 crtn = DSAPublicKeyDecode(dsaKey, hdr->Format,
551 cssmKey.KeyData.Data,
552 cssmKey.KeyData.Length);
553 }
554 else {
555 crtn = DSAPrivateKeyDecode(dsaKey, hdr->Format,
556 cssmKey.KeyData.Data,
557 cssmKey.KeyData.Length);
558 }
559 }
560
561 if(crtn) {
562 if (dsaKey != NULL) {
563 DSA_free(dsaKey);
564 }
565
566 CssmError::throwMe(crtn);
567 }
568 /*
569 * Add in optional external parameters if this is not fully formed.
570 * This path is only taken from DSAKeyInfoProvider::CssmKeyToBinary,
571 * e.g., when doing a NULL unwrap of a partially formed DSA public
572 * key with the "complete the key with these params" option.
573 */
574 if(isPub && (dsaKey->p == NULL) && (paramKey != NULL)) {
575 rsaMiscDebug("rawCssmKeyToDsa; updating dsaKey %p", dsaKey);
576 crtn = dsaGetParamsFromKey(dsaKey, *paramKey, session);
577 if(crtn) {
578 DSA_free(dsaKey);
579 CssmError::throwMe(crtn);
580 }
581 }
582
583 if(dsaKey->p != NULL) {
584 /* avoid use of provided DSA key which exceeds the max size */
585 uint32 keySize = BN_num_bits(dsaKey->p);
586 if(keySize > DSA_MAX_KEY_SIZE) {
587 DSA_free(dsaKey);
588 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
589 }
590 }
591 return dsaKey;
592 }
593
594 /*
595 * Given a DSA private key, calculate its public component if it
596 * doesn't already exist. Used for calculating the key digest of
597 * an incoming raw private key.
598 */
599 void dsaKeyPrivToPub(
600 DSA *dsaKey)
601 {
602 assert(dsaKey != NULL);
603 assert(dsaKey->priv_key != NULL);
604
605 if(dsaKey->pub_key != NULL) {
606 return;
607 }
608
609 /* logic copied from DSA_generate_key() */
610 dsaKey->pub_key = BN_new();
611 if(dsaKey->pub_key == NULL) {
612 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
613 }
614 BN_CTX *ctx = BN_CTX_new();
615 if (ctx == NULL) {
616 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
617 }
618 int rtn = BN_mod_exp(dsaKey->pub_key,
619 dsaKey->g,
620 dsaKey->priv_key,
621 dsaKey->p,
622 ctx);
623 BN_CTX_free(ctx);
624 if(rtn == 0) {
625 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
626 }
627 }