]>
Commit | Line | Data |
---|---|---|
29654253 A |
1 | /* |
2 | * Copyright (c) 2000-2002 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 | * DH_keys.cpp - Diffie-Hellman key pair support. | |
21 | */ | |
22 | ||
23 | #include "DH_keys.h" | |
24 | #include "DH_utils.h" | |
25 | #include <opensslUtils/opensslUtils.h> | |
df0e469f | 26 | #include <opensslUtils/opensslAsn1.h> |
29654253 A |
27 | #include <Security/cssmdata.h> |
28 | #include <AppleCSP/AppleCSPSession.h> | |
29 | #include <AppleCSP/AppleCSPUtils.h> | |
30 | #include <assert.h> | |
31 | #include <Security/debugging.h> | |
df0e469f | 32 | #include <Security/oidsalg.h> |
29654253 | 33 | #include <AppleCSP/YarrowConnection.h> |
29654253 | 34 | |
df0e469f | 35 | #define dhKeyDebug(args...) secdebug("dhKey", ## args) |
29654253 A |
36 | |
37 | /* | |
38 | * FIXME - the CDSA Algorithm Guide claims that the incoming params argument | |
39 | * for a GenerateAlgorithmParameters call is ignored for D-H. This means | |
40 | * that there is no way for the caller to specify 'g' (typically 2, 3, or | |
41 | * 5). This seems WAY bogus but we'll code to the spec for now, assuming | |
42 | * a hard-coded default generator. | |
43 | */ | |
44 | #define DH_GENERATOR_DEFAULT DH_GENERATOR_2 | |
45 | ||
46 | ||
47 | /*** | |
48 | *** Diffie-Hellman-style BinaryKey | |
49 | ***/ | |
50 | ||
df0e469f | 51 | /* constructor with optional existing DSA key */ |
29654253 A |
52 | DHBinaryKey::DHBinaryKey(DH *dhKey) |
53 | : mDhKey(dhKey) | |
54 | { | |
29654253 A |
55 | } |
56 | ||
57 | DHBinaryKey::~DHBinaryKey() | |
58 | { | |
59 | if(mDhKey) { | |
29654253 A |
60 | DH_free(mDhKey); |
61 | mDhKey = NULL; | |
62 | } | |
29654253 A |
63 | } |
64 | ||
65 | void DHBinaryKey::generateKeyBlob( | |
66 | CssmAllocator &allocator, | |
67 | CssmData &blob, | |
df0e469f A |
68 | CSSM_KEYBLOB_FORMAT &format, |
69 | AppleCSPSession &session, | |
70 | const CssmKey *paramKey, /* optional, unused here */ | |
71 | CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ | |
29654253 | 72 | { |
df0e469f | 73 | |
29654253 A |
74 | switch(mKeyHeader.KeyClass) { |
75 | case CSSM_KEYCLASS_PUBLIC_KEY: | |
76 | { | |
df0e469f A |
77 | switch(format) { |
78 | case CSSM_KEYBLOB_RAW_FORMAT_NONE: | |
79 | // take default | |
80 | format = DH_PUB_KEY_FORMAT; | |
81 | break; | |
82 | case DH_PUB_KEY_FORMAT: | |
83 | case CSSM_KEYBLOB_RAW_FORMAT_X509: | |
84 | // proceed | |
85 | break; | |
86 | case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: | |
87 | /* use PKCS3 - caller won't care if we change this...right? */ | |
88 | format = DH_PUB_KEY_FORMAT; | |
89 | break; | |
90 | default: | |
91 | CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); | |
92 | } | |
93 | ||
94 | assert(mDhKey != NULL); | |
95 | CssmAutoData encodedKey(allocator); | |
96 | CSSM_RETURN crtn = DHPublicKeyEncode(mDhKey, format, | |
97 | encodedKey); | |
98 | if(crtn) { | |
99 | CssmError::throwMe(crtn); | |
100 | } | |
101 | blob = encodedKey.release(); | |
29654253 A |
102 | break; |
103 | } | |
104 | case CSSM_KEYCLASS_PRIVATE_KEY: | |
105 | { | |
df0e469f A |
106 | switch(format) { |
107 | case CSSM_KEYBLOB_RAW_FORMAT_NONE: | |
108 | // i.e., use default | |
109 | format = DH_PRIV_KEY_FORMAT; | |
110 | break; | |
111 | case DH_PRIV_KEY_FORMAT: | |
112 | case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: | |
113 | // proceed | |
114 | break; | |
115 | ||
116 | case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: | |
117 | { | |
118 | /* | |
119 | * Use public blob; calculate it if we | |
120 | * don't already have it. | |
121 | */ | |
122 | assert(mDhKey != NULL); | |
123 | if(mDhKey->pub_key == NULL) { | |
124 | int irtn = DH_generate_key(mDhKey); | |
125 | if(!irtn) { | |
126 | throwRsaDsa("DH_generate_key"); | |
127 | } | |
128 | } | |
129 | assert(mDhKey->pub_key != NULL); | |
130 | setUpData(blob, | |
131 | BN_num_bytes(mDhKey->pub_key), | |
132 | *DH_Factory::privAllocator); | |
133 | BN_bn2bin(mDhKey->pub_key, blob); | |
134 | format = DH_PUB_KEY_FORMAT; | |
135 | return; | |
136 | } | |
137 | ||
138 | default: | |
139 | CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); | |
140 | } | |
29654253 | 141 | assert(mDhKey != NULL); |
29654253 | 142 | CssmAutoData encodedKey(allocator); |
df0e469f A |
143 | CSSM_RETURN crtn = DHPrivateKeyEncode(mDhKey, format, |
144 | encodedKey); | |
29654253 A |
145 | if(crtn) { |
146 | CssmError::throwMe(crtn); | |
147 | } | |
148 | blob = encodedKey.release(); | |
149 | break; | |
150 | } | |
151 | default: | |
152 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); | |
153 | } | |
154 | } | |
155 | ||
29654253 A |
156 | /*** |
157 | *** Diffie-Hellman style AppleKeyPairGenContext | |
158 | ***/ | |
159 | ||
160 | /* | |
161 | * This one is specified in, and called from, CSPFullPluginSession. Our | |
162 | * only job is to prepare two subclass-specific BinaryKeys and call up to | |
163 | * AppleKeyPairGenContext. | |
164 | */ | |
165 | void DHKeyPairGenContext::generate( | |
166 | const Context &context, | |
167 | CssmKey &pubKey, | |
168 | CssmKey &privKey) | |
169 | { | |
170 | DHBinaryKey *pubBinKey = new DHBinaryKey(); | |
171 | DHBinaryKey *privBinKey = new DHBinaryKey(); | |
172 | ||
173 | try { | |
174 | AppleKeyPairGenContext::generate(context, | |
175 | session(), | |
176 | pubKey, | |
177 | pubBinKey, | |
178 | privKey, | |
179 | privBinKey); | |
180 | } | |
181 | catch (...) { | |
182 | delete pubBinKey; | |
183 | delete privBinKey; | |
184 | throw; | |
185 | } | |
186 | } | |
187 | ||
29654253 A |
188 | /* |
189 | * This one is specified in, and called from, AppleKeyPairGenContext | |
190 | */ | |
191 | void DHKeyPairGenContext::generate( | |
192 | const Context &context, | |
193 | BinaryKey &pubBinKey, | |
194 | BinaryKey &privBinKey, | |
195 | uint32 &keyBits) | |
196 | { | |
197 | /* | |
198 | * These casts throw exceptions if the keys are of the | |
199 | * wrong classes, which would be a major bogon, since we created | |
200 | * the keys in the above generate() function. | |
201 | */ | |
202 | DHBinaryKey &rPubBinKey = | |
203 | dynamic_cast<DHBinaryKey &>(pubBinKey); | |
204 | DHBinaryKey &rPrivBinKey = | |
205 | dynamic_cast<DHBinaryKey &>(privBinKey); | |
206 | ||
207 | /* | |
208 | * Parameters from context: | |
209 | * Key size in bits, required; | |
210 | * {p,g,privKeyLength} from generateParams, optional | |
211 | * NOTE: currently the openssl D-H imnplementation ignores the | |
212 | * privKeyLength field. | |
213 | */ | |
214 | keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, | |
215 | CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); | |
216 | CssmData *paramData = context.get<CssmData>(CSSM_ATTRIBUTE_ALG_PARAMS); | |
217 | ||
df0e469f A |
218 | NSS_DHParameterBlock algParamBlock; |
219 | NSS_DHParameter &algParams = algParamBlock.params; | |
29654253 A |
220 | uint32 privValueLen = 0; // only nonzero from externally generated |
221 | // params | |
df0e469f | 222 | SecNssCoder coder; // for temp allocs of decoded parameters |
29654253 A |
223 | |
224 | if(paramData != NULL) { | |
225 | /* this contains the DER encoding of a DHParameterBlock */ | |
df0e469f A |
226 | CSSM_RETURN crtn; |
227 | crtn = DHParamBlockDecode(*paramData, algParamBlock, coder); | |
228 | if(crtn) { | |
229 | CssmError::throwMe(crtn); | |
29654253 A |
230 | } |
231 | ||
232 | /* snag the optional private key length field */ | |
df0e469f A |
233 | if(algParams.privateValueLength.Data) { |
234 | privValueLen = cssmDataToInt(algParams.privateValueLength); | |
29654253 A |
235 | } |
236 | ||
237 | /* ensure caller's key size matches the incoming params */ | |
238 | uint32 paramKeyBytes; | |
239 | if(privValueLen) { | |
240 | paramKeyBytes = (privValueLen + 7) / 8; | |
241 | } | |
242 | else { | |
df0e469f | 243 | paramKeyBytes = algParams.prime.Length; |
29654253 A |
244 | /* trim off possible m.s. byte of zero */ |
245 | const unsigned char *uo = | |
df0e469f | 246 | (const unsigned char *)algParams.prime.Data; |
29654253 A |
247 | if(*uo == 0) { |
248 | paramKeyBytes--; | |
249 | } | |
250 | } | |
251 | uint32 reqBytes = (keyBits + 7) / 8; | |
252 | if(paramKeyBytes != reqBytes) { | |
253 | dhKeyDebug("DH key size mismatch (req %d param %d)", | |
254 | (int)reqBytes, (int)paramKeyBytes); | |
255 | CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); | |
256 | } | |
257 | } | |
258 | else { | |
259 | /* no alg params specified; generate them now */ | |
260 | dhKeyDebug("DH implicit alg param calculation"); | |
df0e469f A |
261 | memset(&algParamBlock, 0, sizeof(algParamBlock)); |
262 | dhGenParams(keyBits, DH_GENERATOR_DEFAULT, 0, algParams, coder); | |
29654253 A |
263 | } |
264 | ||
265 | /* create key, stuff params into it */ | |
266 | rPrivBinKey.mDhKey = DH_new(); | |
267 | if(rPrivBinKey.mDhKey == NULL) { | |
268 | CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); | |
269 | } | |
270 | DH *dhKey = rPrivBinKey.mDhKey; | |
df0e469f A |
271 | dhKey->p = cssmDataToBn(algParams.prime); |
272 | dhKey->g = cssmDataToBn(algParams.base); | |
29654253 | 273 | dhKey->length = privValueLen; |
df0e469f | 274 | cspDhDebug("private DH binary key dhKey %p", dhKey); |
29654253 A |
275 | |
276 | /* generate the key (both public and private capabilities) */ | |
277 | int irtn = DH_generate_key(dhKey); | |
278 | if(!irtn) { | |
279 | throwRsaDsa("DH_generate_key"); | |
280 | } | |
281 | ||
df0e469f A |
282 | /* public key is a subset */ |
283 | rPubBinKey.mDhKey = DH_new(); | |
284 | if(rPubBinKey.mDhKey == NULL) { | |
285 | CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); | |
286 | } | |
287 | DH *pubDhKey = rPubBinKey.mDhKey; | |
288 | pubDhKey->pub_key = BN_dup(dhKey->pub_key); | |
289 | /* these params used for X509 style key blobs */ | |
290 | pubDhKey->p = BN_dup(dhKey->p); | |
291 | pubDhKey->g = BN_dup(dhKey->g); | |
292 | cspDhDebug("public DH binary key pubDhKey %p", pubDhKey); | |
29654253 A |
293 | } |
294 | ||
295 | ||
296 | ||
297 | /*** | |
298 | *** Diffie-Hellman CSPKeyInfoProvider. | |
299 | ***/ | |
300 | DHKeyInfoProvider::DHKeyInfoProvider( | |
df0e469f A |
301 | const CssmKey &cssmKey, |
302 | AppleCSPSession &session) : | |
303 | CSPKeyInfoProvider(cssmKey, session) | |
304 | { | |
305 | } | |
306 | ||
307 | CSPKeyInfoProvider *DHKeyInfoProvider::provider( | |
308 | const CssmKey &cssmKey, | |
309 | AppleCSPSession &session) | |
29654253 A |
310 | { |
311 | switch(cssmKey.algorithm()) { | |
312 | case CSSM_ALGID_DH: | |
313 | break; | |
314 | default: | |
315 | CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); | |
316 | } | |
317 | switch(cssmKey.keyClass()) { | |
318 | case CSSM_KEYCLASS_PUBLIC_KEY: | |
319 | case CSSM_KEYCLASS_PRIVATE_KEY: | |
320 | break; | |
321 | default: | |
322 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); | |
323 | } | |
324 | /* OK, we'll handle this one */ | |
df0e469f | 325 | return new DHKeyInfoProvider(cssmKey, session); |
29654253 A |
326 | } |
327 | ||
328 | /* Given a raw key, cook up a Binary key */ | |
329 | void DHKeyInfoProvider::CssmKeyToBinary( | |
df0e469f A |
330 | CssmKey *paramKey, // optional, ignored here |
331 | CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT | |
332 | BinaryKey **binKey) | |
29654253 A |
333 | { |
334 | *binKey = NULL; | |
335 | ||
336 | assert(mKey.blobType() == CSSM_KEYBLOB_RAW); | |
337 | switch(mKey.keyClass()) { | |
338 | case CSSM_KEYCLASS_PUBLIC_KEY: | |
29654253 | 339 | case CSSM_KEYCLASS_PRIVATE_KEY: |
29654253 | 340 | break; |
29654253 A |
341 | default: |
342 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); | |
343 | } | |
df0e469f A |
344 | |
345 | /* first cook up an DH key, then drop that into a BinaryKey */ | |
346 | DH *dhKey = rawCssmKeyToDh(mKey); | |
347 | DHBinaryKey *dhBinKey = new DHBinaryKey(dhKey); | |
348 | *binKey = dhBinKey; | |
349 | cspDhDebug("CssmKeyToBinary dhKey %p", dhKey); | |
29654253 A |
350 | } |
351 | ||
352 | /* | |
353 | * Obtain key size in bits. | |
354 | * FIXME - I doubt that this is, or can be, exactly accurate..... | |
355 | */ | |
356 | void DHKeyInfoProvider::QueryKeySizeInBits( | |
357 | CSSM_KEY_SIZE &keySize) | |
358 | { | |
359 | uint32 numBits = 0; | |
360 | ||
361 | if(mKey.blobType() != CSSM_KEYBLOB_RAW) { | |
362 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); | |
363 | } | |
df0e469f A |
364 | DH *dhKey = rawCssmKeyToDh(mKey); |
365 | ||
366 | /* DH_size requires the p parameter, which some public keys don't have */ | |
367 | if(dhKey->p != NULL) { | |
368 | numBits = DH_size(dhKey) * 8; | |
369 | } | |
370 | else { | |
371 | assert(dhKey->pub_key != NULL); | |
372 | numBits = BN_num_bytes(dhKey->pub_key) * 8; | |
373 | } | |
374 | DH_free(dhKey); | |
375 | keySize.LogicalKeySizeInBits = numBits; | |
376 | keySize.EffectiveKeySizeInBits = numBits; | |
377 | } | |
378 | ||
379 | /* | |
380 | * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST | |
381 | * passthrough. | |
382 | */ | |
383 | bool DHKeyInfoProvider::getHashableBlob( | |
384 | CssmAllocator &allocator, | |
385 | CssmData &blob) // blob to hash goes here | |
386 | { | |
387 | /* | |
388 | * The optimized case, a raw key in the "proper" format already. | |
389 | */ | |
390 | assert(mKey.blobType() == CSSM_KEYBLOB_RAW); | |
391 | bool useAsIs = false; | |
392 | ||
29654253 A |
393 | switch(mKey.keyClass()) { |
394 | case CSSM_KEYCLASS_PUBLIC_KEY: | |
df0e469f A |
395 | if(mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_PKCS3) { |
396 | useAsIs = true; | |
397 | } | |
29654253 A |
398 | break; |
399 | case CSSM_KEYCLASS_PRIVATE_KEY: | |
29654253 | 400 | break; |
29654253 | 401 | default: |
df0e469f A |
402 | /* shouldn't be here */ |
403 | assert(0); | |
404 | CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); | |
29654253 | 405 | } |
df0e469f A |
406 | if(useAsIs) { |
407 | const CssmData &keyBlob = CssmData::overlay(mKey.KeyData); | |
408 | copyCssmData(keyBlob, blob, allocator); | |
409 | return true; | |
410 | } | |
411 | ||
412 | /* caller converts to binary and proceeds */ | |
413 | return false; | |
29654253 A |
414 | } |
415 | ||
29654253 A |
416 | /* |
417 | * Generate keygen parameters, stash them in a context attr array for later use | |
418 | * when actually generating the keys. | |
419 | */ | |
420 | ||
421 | void DHKeyPairGenContext::generate( | |
422 | const Context &context, | |
423 | uint32 bitSize, | |
424 | CssmData ¶ms, // RETURNED here, | |
425 | uint32 &attrCount, // here, | |
426 | Context::Attr * &attrs) // and here | |
427 | { | |
428 | /* generate the params */ | |
df0e469f A |
429 | NSS_DHParameterBlock algParamBlock; |
430 | SecNssCoder coder; | |
431 | NSS_DHParameter &algParams = algParamBlock.params; | |
432 | dhGenParams(bitSize, DH_GENERATOR_DEFAULT, 0, algParams, coder); | |
29654253 A |
433 | |
434 | /* drop in the required OID */ | |
df0e469f | 435 | algParamBlock.oid = CSSMOID_PKCS3; |
29654253 A |
436 | |
437 | /* | |
438 | * Here comes the fun part. | |
439 | * We "return" the DER encoding of these generated params in two ways: | |
440 | * 1. Copy out to app via the params argument, mallocing if Data ptr is NULL. | |
441 | * The app must free this. | |
442 | * 2. Cook up a 1-element Context::attr array containing one ALG_PARAM attr, | |
443 | * a CSSM_DATA_PTR containing the DER encoding. We have to save a ptr to | |
444 | * this attr array and free it, the CSSM_DATA it points to, and the DER | |
445 | * encoding *that* points to, in our destructor. | |
446 | * | |
447 | * First, DER encode. | |
448 | */ | |
29654253 | 449 | CssmAutoData aDerData(session()); |
df0e469f A |
450 | PRErrorCode perr; |
451 | perr = SecNssEncodeItemOdata(&algParamBlock, NSS_DHParameterBlockTemplate, | |
452 | aDerData); | |
453 | if(perr) { | |
454 | /* only known error... */ | |
455 | CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); | |
456 | } | |
29654253 A |
457 | |
458 | /* copy/release that into a mallocd CSSM_DATA. */ | |
459 | CSSM_DATA_PTR derData = (CSSM_DATA_PTR)session().malloc(sizeof(CSSM_DATA)); | |
460 | *derData = aDerData.release(); | |
461 | ||
462 | /* stuff that into a one-element Attr array which we keep after returning */ | |
463 | freeGenAttrs(); | |
464 | mGenAttrs = (Context::Attr *)session().malloc(sizeof(Context::Attr)); | |
465 | mGenAttrs->AttributeType = CSSM_ATTRIBUTE_ALG_PARAMS; | |
466 | mGenAttrs->AttributeLength = sizeof(CSSM_DATA); | |
467 | mGenAttrs->Attribute.Data = derData; | |
468 | ||
469 | /* and "return" this stuff */ | |
470 | copyCssmData(CssmData::overlay(*derData), params, session()); | |
471 | attrCount = 1; | |
472 | attrs = mGenAttrs; | |
473 | } | |
474 | ||
475 | /* free mGenAttrs and its referents if present */ | |
476 | void DHKeyPairGenContext::freeGenAttrs() | |
477 | { | |
478 | if(mGenAttrs == NULL) { | |
479 | return; | |
480 | } | |
481 | if(mGenAttrs->Attribute.Data) { | |
482 | if(mGenAttrs->Attribute.Data->Data) { | |
483 | session().free(mGenAttrs->Attribute.Data->Data); | |
484 | } | |
485 | session().free(mGenAttrs->Attribute.Data); | |
486 | } | |
487 | session().free(mGenAttrs); | |
488 | } | |
489 | ||
490 | /* | |
491 | * Generate DSA algorithm parameters returning result | |
492 | * into DHParameter.{prime,base,privateValueLength]. | |
493 | * This is called from both GenerateParameters and from | |
494 | * KeyPairGenerate (if no GenerateParameters has yet been called). | |
495 | * | |
496 | * FIXME - privateValueLength not implemented in openssl, not here | |
497 | * either for now. | |
498 | */ | |
499 | ||
500 | void DHKeyPairGenContext::dhGenParams( | |
501 | uint32 keySizeInBits, | |
502 | unsigned g, // probably should be BIGNUM | |
503 | int privValueLength, // optional | |
df0e469f A |
504 | NSS_DHParameter &algParams, |
505 | SecNssCoder &coder) // temp contents of algParams | |
506 | // mallocd here | |
29654253 A |
507 | { |
508 | /* validate key size */ | |
509 | if((keySizeInBits < DH_MIN_KEY_SIZE) || | |
510 | (keySizeInBits > DH_MAX_KEY_SIZE)) { | |
511 | CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); | |
512 | } | |
513 | ||
514 | /* create an openssl-style DH key with minimal setup */ | |
515 | DH *dhKey = DH_generate_parameters(keySizeInBits, g, NULL, NULL); | |
516 | if(dhKey == NULL) { | |
517 | throwRsaDsa("DSA_generate_parameters"); | |
518 | } | |
519 | ||
df0e469f A |
520 | /* stuff dhKey->{p,g,length}] into a caller's NSS_DHParameter */ |
521 | bnToCssmData(dhKey->p, algParams.prime, coder); | |
522 | bnToCssmData(dhKey->g, algParams.base, coder); | |
523 | CSSM_DATA &privValData = algParams.privateValueLength; | |
29654253 | 524 | if(privValueLength) { |
df0e469f A |
525 | intToCssmData(privValueLength, privValData, coder); |
526 | } | |
527 | else { | |
528 | privValData.Data = NULL; | |
529 | privValData.Length = 0; | |
29654253 A |
530 | } |
531 | DH_free(dhKey); | |
532 | } | |
533 |