]> git.saurik.com Git - apple/security.git/blob - AppleCSP/open_ssl/opensslUtils/opensslAsn1.cpp
Security-179.tar.gz
[apple/security.git] / AppleCSP / open_ssl / opensslUtils / opensslAsn1.cpp
1 /*
2 * Copyright (c) 2003 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 * opensslAsn1.h - ANS1 encode/decode of openssl object, libssnasn1 version
21 */
22 #include "opensslAsn1.h"
23 #include "BinaryKey.h"
24 #include "AppleCSPUtils.h"
25 #include "osKeyTemplates.h"
26 #include <openssl/err.h>
27 #include <openssl/bn.h>
28 #include <openssl/crypto.h>
29
30 #include <SecurityNssAsn1/SecNssCoder.h>
31 #include <SecurityNssAsn1/secerr.h>
32 #include <SecurityNssAsn1/keyTemplates.h>
33 #include <Security/debugging.h>
34 #include <Security/oidsalg.h>
35
36 #include <assert.h>
37
38 #define sslAsn1Debug(args...) secdebug("sslAsn1", ##args)
39
40 #ifndef NDEBUG
41 #include <stdio.h>
42 #include <SecurityNssAsn1/secerr.h>
43
44 static void logAsnErr(
45 const char *op,
46 PRErrorCode perr)
47 {
48 printf("Error on %s: %s\n", op, SECErrorString(perr));
49 }
50 #else
51 #define logAsnErr(op, perr)
52 #endif
53
54 /* CSSM_DATA --> BIGNUM */
55 BIGNUM *cssmDataToBn(
56 const CSSM_DATA &cdata)
57 {
58 BIGNUM *bn = BN_new();
59 BIGNUM *rtn;
60
61 rtn = BN_bin2bn(cdata.Data, cdata.Length, bn);
62 if(rtn == NULL) {
63 BN_free(bn);
64 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
65 }
66 return bn;
67 }
68
69 /* BIGNUM --> CSSM_DATA, mallocing from a SecNssCoder's PL_ArenaPool */
70 void bnToCssmData(
71 const BIGNUM *bn,
72 CSSM_DATA &cdata,
73 SecNssCoder &coder)
74 {
75 assert(bn != NULL);
76 unsigned numBytes = BN_num_bytes(bn);
77 cdata.Data = (uint8 *)coder.malloc(numBytes);
78 if(cdata.Data == NULL) {
79 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
80 }
81 cdata.Length = numBytes;
82 BN_bn2bin(bn, cdata.Data);
83 }
84
85 /*
86 * CSSM_DATA --> unsigned int
87 */
88 unsigned cssmDataToInt(
89 const CSSM_DATA &cdata)
90 {
91 if((cdata.Length == 0) || (cdata.Data == NULL)) {
92 return 0;
93 }
94 unsigned len = (unsigned)cdata.Length;
95 if(len > sizeof(int)) {
96 logAsnErr("cssmDataToInt: Length error (%u)", len);
97 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
98 }
99
100 unsigned rtn = 0;
101 uint8 *cp = cdata.Data;
102 for(unsigned i=0; i<len; i++) {
103 rtn = (rtn << 8) | *cp++;
104 }
105 return rtn;
106 }
107
108 /*
109 * unsigned int --> CSSM_DATA, mallocing from an SecNssCoder
110 */
111 void intToCssmData(
112 unsigned num,
113 CSSM_DATA &cdata,
114 SecNssCoder &coder)
115 {
116 unsigned len = 0;
117
118 if(num < 0x100) {
119 len = 1;
120 }
121 else if(num < 0x10000) {
122 len = 2;
123 }
124 else if(num < 0x1000000) {
125 len = 3;
126 }
127 else {
128 len = 4;
129 }
130 cdata.Data = (uint8 *)coder.malloc(len);
131 cdata.Length = len;
132 uint8 *cp = &cdata.Data[len - 1];
133 for(unsigned i=0; i<len; i++) {
134 *cp-- = num & 0xff;
135 num >>= 8;
136 }
137 }
138
139 /*
140 * Set up a encoded NULL for AlgorithmIdentifier.parameters,
141 * required for RSA
142 */
143 static void nullAlgParams(
144 CSSM_X509_ALGORITHM_IDENTIFIER &algId)
145 {
146 static const uint8 encNull[2] = { SEC_ASN1_NULL, 0 };
147 CSSM_DATA encNullData;
148 encNullData.Data = (uint8 *)encNull;
149 encNullData.Length = 2;
150
151 algId.parameters = encNullData;
152 }
153
154 #pragma mark -
155 #pragma mark *** RSA key encode/decode ***
156
157 /*
158 * DER encode/decode RSA keys in various formats.
159 *
160 * Public key, CSSM_KEYBLOB_RAW_FORMAT_PKCS1
161 * -- compatible with BSAFE
162 * -- used for CSSM_KEYBLOB_RAW_FORMAT_DIGEST on both keys
163 */
164 static CSSM_RETURN RSAPublicKeyDecodePKCS1(
165 SecNssCoder &coder,
166 RSA *openKey,
167 void *p,
168 size_t length)
169 {
170 NSS_RSAPublicKeyPKCS1 nssPubKey;
171
172 memset(&nssPubKey, 0, sizeof(nssPubKey));
173 PRErrorCode perr = coder.decode(p, length,
174 NSS_RSAPublicKeyPKCS1Template, &nssPubKey);
175 if(perr) {
176 logAsnErr("decode(RSAPublicKeyPKCS1)", perr);
177 return CSSMERR_CSP_INVALID_KEY;
178 }
179
180 try {
181 openKey->n = cssmDataToBn(nssPubKey.modulus);
182 openKey->e = cssmDataToBn(nssPubKey.publicExponent);
183 }
184 catch(...) {
185 return CSSMERR_CSP_MEMORY_ERROR;
186 }
187 return 0;
188 }
189
190 static CSSM_RETURN RSAPublicKeyEncodePKCS1(
191 SecNssCoder &coder,
192 RSA *openKey,
193 CssmOwnedData &encodedKey)
194 {
195 /* convert to NSS_RSAPublicKeyPKCS1 */
196 NSS_RSAPublicKeyPKCS1 nssPubKey;
197
198 try {
199 bnToCssmData(openKey->n, nssPubKey.modulus, coder);
200 bnToCssmData(openKey->e, nssPubKey.publicExponent, coder);
201 }
202 catch(...) {
203 return CSSMERR_CSP_MEMORY_ERROR;
204 }
205
206 PRErrorCode prtn;
207 prtn = SecNssEncodeItemOdata(&nssPubKey,
208 NSS_RSAPublicKeyPKCS1Template, encodedKey);
209 if(prtn) {
210 return CSSMERR_CSP_MEMORY_ERROR;
211 }
212 return CSSM_OK;
213 }
214
215 /*
216 * SubjectPublicKeyInfo, as used by openssl.
217 * The subjectPublicKey component is a PKCS1-style RSAPublicKey.
218 */
219 static CSSM_RETURN RSAPublicKeyDecodeX509(
220 SecNssCoder &coder,
221 RSA *openKey,
222 void *p,
223 size_t length)
224 {
225 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo;
226 PRErrorCode perr;
227
228 memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo));
229 perr = coder.decode(p, length, NSS_SubjectPublicKeyInfoTemplate,
230 &nssPubKeyInfo);
231 if(perr) {
232 logAsnErr("decode(RSA SubjectPublicKeyInfo)", perr);
233 return CSSMERR_CSP_INVALID_KEY;
234 }
235
236 /* verify alg identifier */
237 const CSSM_OID *oid = &nssPubKeyInfo.algorithm.algorithm;
238 if(!cspCompareCssmData(oid, &CSSMOID_RSA)) {
239 sslAsn1Debug("RSAPublicKeyDecodeX509: bad OID");
240 return CSSMERR_CSP_INVALID_KEY;
241 }
242
243 /* decode the raw bits */
244 CSSM_DATA *pubKey = &nssPubKeyInfo.subjectPublicKey;
245 /* decoded length was in bits */
246 pubKey->Length = (pubKey->Length + 7) / 8;
247 return RSAPublicKeyDecodePKCS1(coder, openKey, pubKey->Data,
248 pubKey->Length);
249 }
250
251 static CSSM_RETURN RSAPublicKeyEncodeX509(
252 SecNssCoder &coder,
253 RSA *openKey,
254 CssmOwnedData &encodedKey)
255 {
256 CssmAutoData aData(CssmAllocator::standard());
257 CSSM_RETURN crtn;
258
259 /* First get an encoded PKCS1-style RSAPublicKey */
260 crtn = RSAPublicKeyEncodePKCS1(coder, openKey, aData);
261 if(crtn) {
262 return crtn;
263 }
264
265 /*
266 * That's the AsnBits subjectPublicKey component of a
267 * SubjectPublicKeyInfo
268 */
269 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo;
270 memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo));
271 nssPubKeyInfo.subjectPublicKey.Data = (uint8 *)aData.data();
272 nssPubKeyInfo.subjectPublicKey.Length = aData.length() * 8;
273
274 CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPubKeyInfo.algorithm;
275 algId.algorithm = CSSMOID_RSA;
276
277 /* NULL algorithm paramneters, always in this case */
278 nullAlgParams(algId);
279
280 /* DER encode */
281 PRErrorCode perr;
282 perr = SecNssEncodeItemOdata(&nssPubKeyInfo,
283 NSS_SubjectPublicKeyInfoTemplate, encodedKey);
284
285 if(perr) {
286 logAsnErr("encode(RSA SubjectPublicKeyInfo)", perr);
287 return CSSMERR_CSP_MEMORY_ERROR;
288 }
289 return CSSM_OK;
290 }
291
292 /*
293 * RSA private key, PKCS1 format, used by openssl.
294 */
295 static CSSM_RETURN RSAPrivateKeyDecodePKCS1(
296 SecNssCoder &coder,
297 RSA *openKey,
298 void *p,
299 size_t length)
300 {
301 NSS_RSAPrivateKeyPKCS1 nssPrivKey;
302 PRErrorCode perr;
303
304 memset(&nssPrivKey, 0, sizeof(nssPrivKey));
305 perr = coder.decode(p, length, NSS_RSAPrivateKeyPKCS1Template, &nssPrivKey);
306 if(perr) {
307 logAsnErr("decode(RSAPrivateKeyPKCS)", perr);
308 return CSSMERR_CSP_INVALID_KEY;
309 }
310
311 /* convert nssPrivKey fields to RSA key fields */
312 try {
313 openKey->version = cssmDataToInt(nssPrivKey.version);
314 openKey->n = cssmDataToBn(nssPrivKey.modulus);
315 openKey->e = cssmDataToBn(nssPrivKey.publicExponent);
316 openKey->d = cssmDataToBn(nssPrivKey.privateExponent);
317 openKey->p = cssmDataToBn(nssPrivKey.prime1);
318 openKey->q = cssmDataToBn(nssPrivKey.prime2);
319 openKey->dmp1 = cssmDataToBn(nssPrivKey.exponent1);
320 openKey->dmq1 = cssmDataToBn(nssPrivKey.exponent2);
321 openKey->iqmp = cssmDataToBn(nssPrivKey.coefficient);
322 }
323 catch(...) {
324 return CSSMERR_CSP_MEMORY_ERROR;
325 }
326 return 0;
327 }
328
329 static CSSM_RETURN RSAPrivateKeyEncodePKCS1(
330 SecNssCoder &coder,
331 RSA *openKey,
332 CssmOwnedData &encodedKey)
333 {
334 NSS_RSAPrivateKeyPKCS1 nssPrivKey;
335 PRErrorCode perr;
336
337 /* convert to NSS_RSAPrivateKeyPKCS1 */
338 try {
339 intToCssmData(openKey->version, nssPrivKey.version, coder);
340 bnToCssmData(openKey->n, nssPrivKey.modulus, coder);
341 bnToCssmData(openKey->e, nssPrivKey.publicExponent, coder);
342 bnToCssmData(openKey->d, nssPrivKey.privateExponent, coder);
343 bnToCssmData(openKey->p, nssPrivKey.prime1, coder);
344 bnToCssmData(openKey->q, nssPrivKey.prime2, coder);
345 bnToCssmData(openKey->dmp1, nssPrivKey.exponent1, coder);
346 bnToCssmData(openKey->dmq1, nssPrivKey.exponent2, coder);
347 bnToCssmData(openKey->iqmp, nssPrivKey.coefficient, coder);
348 }
349 catch(...) {
350 /* ? */
351 return CSSMERR_CSP_MEMORY_ERROR;
352 }
353
354 /* DER encode */
355 perr = SecNssEncodeItemOdata(&nssPrivKey, NSS_RSAPrivateKeyPKCS1Template,
356 encodedKey);
357 if(perr) {
358 logAsnErr("encode(RSAPrivateKeyPKCS1)", perr);
359 return CSSMERR_CSP_MEMORY_ERROR;
360 }
361 return CSSM_OK;
362 }
363
364 /*
365 * RSA private key, PKCS8, compatible with BSAFE.
366 */
367 static CSSM_RETURN RSAPrivateKeyDecodePKCS8(
368 SecNssCoder &coder,
369 RSA *openKey,
370 void *p,
371 size_t length)
372 {
373 NSS_PrivateKeyInfo nssPrivKeyInfo;
374 PRErrorCode perr;
375
376 memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
377 perr = coder.decode(p, length, NSS_PrivateKeyInfoTemplate, &nssPrivKeyInfo);
378 if(perr) {
379 logAsnErr("decode(PrivateKeyInfo)", perr);
380 return CSSMERR_CSP_INVALID_KEY;
381 }
382
383 /* verify alg identifier */
384 const CSSM_OID *oid = &nssPrivKeyInfo.algorithm.algorithm;
385 if(!cspCompareCssmData(oid, &CSSMOID_RSA)) {
386 sslAsn1Debug("RSAPrivateKeyDecodePKCS8: bad OID");
387 return CSSMERR_CSP_INVALID_KEY;
388 }
389
390 /*
391 * nssPrivKeyInfo.privateKey is an octet string which needs
392 * subsequent decoding
393 */
394 CSSM_DATA *privKey = &nssPrivKeyInfo.privateKey;
395 return RSAPrivateKeyDecodePKCS1(coder, openKey,
396 privKey->Data, privKey->Length);
397 }
398
399 static CSSM_RETURN RSAPrivateKeyEncodePKCS8(
400 SecNssCoder &coder,
401 RSA *openKey,
402 CssmOwnedData &encodedKey)
403 {
404
405 /* First get PKCS1-style encoding */
406 CssmAutoData aData(CssmAllocator::standard());
407 CSSM_RETURN crtn = RSAPrivateKeyEncodePKCS1(coder, openKey, aData);
408 if(crtn) {
409 return crtn;
410 }
411
412 /* that encoding is the privateKey field of a NSS_PrivateKeyInfo */
413 NSS_PrivateKeyInfo nssPrivKeyInfo;
414 memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
415 nssPrivKeyInfo.privateKey.Data = (uint8 *)aData.data();
416 nssPrivKeyInfo.privateKey.Length = aData.length();
417
418 CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPrivKeyInfo.algorithm;
419 algId.algorithm = CSSMOID_RSA;
420
421 /* NULL algorithm paramneters, always in this case */
422 nullAlgParams(algId);
423
424 /* FIXME : attributes? */
425
426 uint8 vers = 0;
427 nssPrivKeyInfo.version.Data = &vers;
428 nssPrivKeyInfo.version.Length = 1;
429
430 /* DER encode */
431 PRErrorCode perr;
432 perr = SecNssEncodeItemOdata(&nssPrivKeyInfo,
433 NSS_PrivateKeyInfoTemplate, encodedKey);
434
435 if(perr) {
436 logAsnErr("encode(RSA PrivateKeyInfo)", perr);
437 return CSSMERR_CSP_MEMORY_ERROR;
438 }
439 return CSSM_OK;
440 }
441
442 CSSM_RETURN RSAPublicKeyDecode(
443 RSA *openKey,
444 CSSM_KEYBLOB_FORMAT format,
445 void *p,
446 size_t length)
447 {
448 SecNssCoder coder;
449
450 switch(format) {
451 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
452 return RSAPublicKeyDecodePKCS1(coder, openKey, p, length);
453 case CSSM_KEYBLOB_RAW_FORMAT_X509:
454 return RSAPublicKeyDecodeX509(coder, openKey, p, length);
455 default:
456 assert(0);
457 return CSSMERR_CSP_INTERNAL_ERROR;
458 }
459 }
460
461 CSSM_RETURN RSAPublicKeyEncode(
462 RSA *openKey,
463 CSSM_KEYBLOB_FORMAT format,
464 CssmOwnedData &encodedKey)
465 {
466 SecNssCoder coder;
467
468 switch(format) {
469 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
470 return RSAPublicKeyEncodePKCS1(coder, openKey, encodedKey);
471 case CSSM_KEYBLOB_RAW_FORMAT_X509:
472 return RSAPublicKeyEncodeX509(coder, openKey, encodedKey);
473 default:
474 assert(0);
475 return CSSMERR_CSP_INTERNAL_ERROR;
476 }
477 }
478
479 CSSM_RETURN RSAPrivateKeyDecode(
480 RSA *openKey,
481 CSSM_KEYBLOB_FORMAT format,
482 void *p,
483 size_t length)
484 {
485 SecNssCoder coder;
486
487 switch(format) {
488 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
489 return RSAPrivateKeyDecodePKCS1(coder, openKey, p, length);
490 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
491 return RSAPrivateKeyDecodePKCS8(coder, openKey, p, length);
492 default:
493 assert(0);
494 return CSSMERR_CSP_INTERNAL_ERROR;
495 }
496 }
497
498 CSSM_RETURN RSAPrivateKeyEncode(
499 RSA *openKey,
500 CSSM_KEYBLOB_FORMAT format,
501 CssmOwnedData &encodedKey)
502 {
503 SecNssCoder coder;
504
505 switch(format) {
506 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
507 return RSAPrivateKeyEncodePKCS1(coder, openKey, encodedKey);
508 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
509 return RSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey);
510 default:
511 assert(0);
512 return CSSMERR_CSP_INTERNAL_ERROR;
513 }
514 }
515
516 #pragma mark -
517 #pragma mark *** DSA key encode/decode ***
518
519 /***
520 *** DSA
521 ***/
522
523 /* NSS_DSAAlgorithmIdBSAFE <--> DSA->{p,g,q} */
524 static void dsaToNssAlgIdBSAFE(
525 const DSA *openKey,
526 NSS_DSAAlgorithmIdBSAFE &algId,
527 SecNssCoder &coder)
528 {
529 /* non-standard, BSAFE-specific OID */
530 algId.algorithm = CSSMOID_DSA; // not mallocd
531 unsigned numBits = BN_num_bits(openKey->p);
532 intToCssmData(numBits, algId.params.keySizeInBits, coder);
533 bnToCssmData(openKey->p, algId.params.p, coder);
534 bnToCssmData(openKey->q, algId.params.q, coder);
535 bnToCssmData(openKey->g, algId.params.g, coder);
536 }
537
538 static CSSM_RETURN nssAlgIdToDsaBSAFE(
539 NSS_DSAAlgorithmIdBSAFE &algId,
540 DSA *openKey)
541 {
542 /* non-standard, BSAFE-specific OID */
543 if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA)) {
544 sslAsn1Debug("nssAlgIdToDsaBSAFE: bad OID");
545 return CSSMERR_CSP_INVALID_KEY;
546 }
547 openKey->p = cssmDataToBn(algId.params.p);
548 openKey->q = cssmDataToBn(algId.params.q);
549 openKey->g = cssmDataToBn(algId.params.g);
550 return CSSM_OK;
551 }
552
553 /* NSS_DSAAlgorithmIdX509 <--> DSA->{p,g,q} */
554 static void dsaToNssAlgIdX509(
555 const DSA *openKey,
556 NSS_DSAAlgorithmIdX509 &algId,
557 SecNssCoder &coder)
558 {
559 algId.algorithm = CSSMOID_DSA_CMS; // not mallocd
560 bnToCssmData(openKey->p, algId.params->p, coder);
561 bnToCssmData(openKey->q, algId.params->q, coder);
562 bnToCssmData(openKey->g, algId.params->g, coder);
563 }
564
565 static CSSM_RETURN nssAlgIdToDsaX509(
566 NSS_DSAAlgorithmIdX509 &algId,
567 DSA *openKey)
568 {
569 if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_CMS) &&
570 !cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_JDK)) {
571 sslAsn1Debug("nssAlgIdToDsaX509: bad OID");
572 return CSSMERR_CSP_INVALID_KEY;
573 }
574 /* these might be absent per CMS */
575 if(algId.params == NULL) {
576 return CSSM_OK;
577 }
578 openKey->p = cssmDataToBn(algId.params->p);
579 openKey->q = cssmDataToBn(algId.params->q);
580 openKey->g = cssmDataToBn(algId.params->g);
581 return CSSM_OK;
582 }
583
584 /*
585 * DSA public keys, FIPS186 format.
586 * Compatible with BSAFE.
587 */
588 CSSM_RETURN DSAPublicKeyDecodeFIPS186(
589 SecNssCoder &coder,
590 DSA *openKey,
591 void *p,
592 unsigned length)
593 {
594 NSS_DSAPublicKeyBSAFE nssPubKey;
595 PRErrorCode perr;
596 CSSM_RETURN crtn;
597
598 memset(&nssPubKey, 0, sizeof(nssPubKey));
599 perr = coder.decode(p, length, NSS_DSAPublicKeyBSAFETemplate,
600 &nssPubKey);
601 if(perr) {
602 logAsnErr("decode(DSAPublicKeyBSAFE)", perr);
603 return CSSMERR_CSP_INVALID_KEY;
604 }
605
606 /* BSAFE style DSA-specific alg params */
607 NSS_DSAAlgorithmIdBSAFE &algId = nssPubKey.dsaAlg;
608 crtn = nssAlgIdToDsaBSAFE(algId, openKey);
609 if(crtn) {
610 return crtn;
611 }
612
613 /* inside of nssPubKey.publicKey is the DER-encoding of a
614 * ASN Integer; decoded length was in bits */
615 nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8;
616 CSSM_DATA pubKeyBytes;
617 perr = coder.decodeItem(nssPubKey.publicKey,
618 SEC_UnsignedIntegerTemplate,
619 &pubKeyBytes);
620 if(perr) {
621 logAsnErr("decode(NSS_DSAPublicKeyBSAFE.publicKey)", perr);
622 return CSSMERR_CSP_INVALID_KEY;
623 }
624 openKey->pub_key = cssmDataToBn(pubKeyBytes);
625
626 if(openKey->pub_key == NULL) {
627 return CSSMERR_CSP_INVALID_KEY;
628 }
629 return 0;
630 }
631
632 CSSM_RETURN DSAPublicKeyEncodeFIPS186(
633 SecNssCoder &coder,
634 DSA *openKey,
635 CssmOwnedData &encodedKey)
636 {
637 try {
638 /* convert to NSS_DSAPublicKeyBSAFE */
639 NSS_DSAPublicKeyBSAFE nssPubKey;
640 memset(&nssPubKey, 0, sizeof(nssPubKey));
641 dsaToNssAlgIdBSAFE(openKey, nssPubKey.dsaAlg, coder);
642
643 /*
644 * publicKey is the DER-encoding of a ASN INTEGER wrapped in
645 * an AsnBits
646 */
647 CSSM_DATA pubKeyRaw;
648 PRErrorCode perr;
649 bnToCssmData(openKey->pub_key, pubKeyRaw, coder);
650 perr = coder.encodeItem(&pubKeyRaw, SEC_UnsignedIntegerTemplate,
651 nssPubKey.publicKey);
652 if(perr) {
653 logAsnErr("encodeItem(DSAPublicKeyBSAFE.publicKey)", perr);
654 return CSSMERR_CSP_MEMORY_ERROR;
655 }
656 nssPubKey.publicKey.Length *= 8;
657
658 /* DER encode */
659 SecNssEncodeItemOdata(&nssPubKey, NSS_DSAPublicKeyBSAFETemplate,
660 encodedKey);
661 return CSSM_OK;
662 }
663 catch(...) {
664 /* ? */
665 return CSSMERR_CSP_MEMORY_ERROR;
666 }
667 }
668
669 /*
670 * DSA private keys, FIPS186 format.
671 * Compatible with BSAFE.
672 */
673 CSSM_RETURN DSAPrivateKeyDecodeFIPS186(
674 SecNssCoder &coder,
675 DSA *openKey,
676 void *p,
677 unsigned length)
678 {
679 NSS_DSAPrivateKeyBSAFE nssPrivKeyInfo;
680 PRErrorCode perr;
681
682 memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
683 perr = coder.decode(p, length, NSS_DSAPrivateKeyBSAFETemplate,
684 &nssPrivKeyInfo);
685 if(perr) {
686 logAsnErr("decode(DSA PrivateKeyInfo)", perr);
687 return CSSMERR_CSP_INVALID_KEY;
688 }
689
690 CSSM_RETURN crtn = nssAlgIdToDsaBSAFE(nssPrivKeyInfo.dsaAlg, openKey);
691 if(crtn) {
692 return crtn;
693 }
694
695 /* nssPrivKeyInfo.privateKey is the DER-encoding of a
696 * DSAPrivateKeyOcts... */
697 try {
698 PRErrorCode perr;
699 NSS_DSAPrivateKeyOcts keyOcts;
700
701 perr = coder.decodeItem(nssPrivKeyInfo.privateKey,
702 NSS_DSAPrivateKeyOctsTemplate, &keyOcts);
703 if(perr) {
704 logAsnErr("decode(DSA PrivateKeyInfoOcts)", perr);
705 return CSSMERR_CSP_INVALID_KEY;
706 }
707
708 openKey->priv_key = cssmDataToBn(keyOcts.privateKey);
709 if(openKey->priv_key == NULL) {
710 return CSSMERR_CSP_INVALID_KEY;
711 }
712 return 0;
713 }
714 catch(...) {
715 return CSSMERR_CSP_INVALID_KEY;
716 }
717 }
718
719 CSSM_RETURN DSAPrivateKeyEncodeFIPS186(
720 SecNssCoder &coder,
721 DSA *openKey,
722 CssmOwnedData &encodedKey)
723 {
724 try {
725 /* First convert into a NSS_DSAPrivateKeyBSAFE */
726 NSS_DSAPrivateKeyBSAFE nssPrivKey;
727 intToCssmData(openKey->version, nssPrivKey.version, coder);
728 dsaToNssAlgIdBSAFE(openKey, nssPrivKey.dsaAlg, coder);
729
730 /* nssPrivKey.privateKey is the DER-encoding of one of these... */
731 NSS_DSAPrivateKeyOcts privKeyOcts;
732 bnToCssmData(openKey->priv_key, privKeyOcts.privateKey, coder);
733
734 /* DER encode the privateKey portion into arena pool memory
735 * into NSS_DSAPrivateKeyPKCS8.privateKey */
736 coder.encodeItem(&privKeyOcts, NSS_DSAPrivateKeyOctsTemplate,
737 nssPrivKey.privateKey);
738
739 /* DER encode the whole thing */
740 PRErrorCode perr;
741 perr = SecNssEncodeItemOdata(&nssPrivKey,
742 NSS_DSAPrivateKeyBSAFETemplate, encodedKey);
743 return 0;
744 }
745 catch(...) {
746 /* ? */
747 return CSSMERR_CSP_MEMORY_ERROR;
748 }
749 }
750
751 /*
752 * DSA private keys, PKCS8/SMIME format.
753 */
754 CSSM_RETURN DSAPrivateKeyDecodePKCS8(
755 SecNssCoder &coder,
756 DSA *openKey,
757 void *p,
758 unsigned length)
759 {
760 NSS_DSAPrivateKeyPKCS8 nssPrivKeyInfo;
761 PRErrorCode perr;
762
763 memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
764 perr = coder.decode(p, length, NSS_DSAPrivateKeyPKCS8Template,
765 &nssPrivKeyInfo);
766 if(perr) {
767 logAsnErr("decode(DSA NSS_DSAPrivateKeyPKCS8)", perr);
768 return CSSMERR_CSP_INVALID_KEY;
769 }
770
771 CSSM_RETURN crtn = nssAlgIdToDsaX509(nssPrivKeyInfo.dsaAlg, openKey);
772 if(crtn) {
773 return crtn;
774 }
775
776 /*
777 * Post-decode, nssPrivKeyInfo.privateKey is the DER-encoding of a
778 * an ASN integer.
779 */
780 try {
781 PRErrorCode perr;
782 CSSM_DATA privKeyInt = {0, NULL};
783
784 perr = coder.decodeItem(nssPrivKeyInfo.privateKey,
785 SEC_UnsignedIntegerTemplate, &privKeyInt);
786 if(perr) {
787 logAsnErr("decode(DSA nssPrivKeyInfo.privateKey)", perr);
788 return CSSMERR_CSP_INVALID_KEY;
789 }
790
791 openKey->priv_key = cssmDataToBn(privKeyInt);
792 if(openKey->priv_key == NULL) {
793 return CSSMERR_CSP_INVALID_KEY;
794 }
795 return 0;
796 }
797 catch(...) {
798 return CSSMERR_CSP_INVALID_KEY;
799 }
800 }
801
802 CSSM_RETURN DSAPrivateKeyEncodePKCS8(
803 SecNssCoder &coder,
804 DSA *openKey,
805 CssmOwnedData &encodedKey)
806 {
807 try {
808 /* First convert into a NSS_DSAPrivateKeyPKCS8 */
809 NSS_DSAPrivateKeyPKCS8 nssPrivKey;
810 NSS_DSAAlgParams algParams;
811 memset(&nssPrivKey, 0, sizeof(nssPrivKey));
812 memset(&algParams, 0, sizeof(algParams));
813 nssPrivKey.dsaAlg.params = &algParams;
814 intToCssmData(openKey->version, nssPrivKey.version, coder);
815 dsaToNssAlgIdX509(openKey, nssPrivKey.dsaAlg, coder);
816
817 /* pre-encode, nssPrivKey.privateKey is the DER-encoding of
818 * an ASN integer... */
819 CSSM_DATA privKeyInt;
820 bnToCssmData(openKey->priv_key, privKeyInt, coder);
821
822 /* DER encode the privateKey portion into arena pool memory
823 * into NSS_DSAPrivateKeyPKCS8.privateKey */
824 coder.encodeItem(&privKeyInt, SEC_UnsignedIntegerTemplate,
825 nssPrivKey.privateKey);
826
827 /* DER encode the whole thing */
828 PRErrorCode perr;
829 perr = SecNssEncodeItemOdata(&nssPrivKey,
830 NSS_DSAPrivateKeyPKCS8Template, encodedKey);
831 return 0;
832 }
833 catch(...) {
834 /* ? */
835 return CSSMERR_CSP_MEMORY_ERROR;
836 }
837 }
838
839 /*
840 * DSA public key, X509/openssl format.
841 */
842 static CSSM_RETURN DSAPublicKeyDecodeX509(
843 SecNssCoder &coder,
844 DSA *openKey,
845 void *p,
846 size_t length)
847 {
848 NSS_DSAPublicKeyX509 nssPubKey;
849 PRErrorCode perr;
850 CSSM_RETURN crtn;
851
852 memset(&nssPubKey, 0, sizeof(nssPubKey));
853 perr = coder.decode(p, length, NSS_DSAPublicKeyX509Template,
854 &nssPubKey);
855 if(perr) {
856 logAsnErr("decode(DSAPublicKeyX509)", perr);
857 return CSSMERR_CSP_INVALID_KEY;
858 }
859
860 /* X509 style DSA-specific alg params */
861 NSS_DSAAlgorithmIdX509 &algId = nssPubKey.dsaAlg;
862 crtn = nssAlgIdToDsaX509(algId, openKey);
863 if(crtn) {
864 return crtn;
865 }
866
867 /* inside of nssPubKey.publicKey is the DER-encoding of a
868 * ASN Integer; decoded length was in bits */
869 nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8;
870 CSSM_DATA pubKeyBytes = {0, NULL};
871 perr = coder.decodeItem(nssPubKey.publicKey,
872 SEC_UnsignedIntegerTemplate,
873 &pubKeyBytes);
874 if(perr) {
875 logAsnErr("decode(NSS_DSAPublicKeyX509.publicKey)", perr);
876 return CSSMERR_CSP_INVALID_KEY;
877 }
878 openKey->pub_key = cssmDataToBn(pubKeyBytes);
879
880 if(openKey->pub_key == NULL) {
881 return CSSMERR_CSP_INVALID_KEY;
882 }
883 return 0;
884 }
885
886 static CSSM_RETURN DSAPublicKeyEncodeX509(
887 SecNssCoder &coder,
888 DSA *openKey,
889 CssmOwnedData &encodedKey)
890 {
891 try {
892 /* convert to NSS_DSAPublicKeyX509 */
893 NSS_DSAPublicKeyX509 nssPubKey;
894 NSS_DSAAlgParams algParams;
895 memset(&nssPubKey, 0, sizeof(nssPubKey));
896 memset(&algParams, 0, sizeof(algParams));
897 nssPubKey.dsaAlg.params = &algParams;
898 dsaToNssAlgIdX509(openKey, nssPubKey.dsaAlg, coder);
899
900 /*
901 * publicKey is the DER-encoding of a ASN INTEGER wrapped in
902 * an AsnBits
903 */
904 CSSM_DATA pubKeyRaw;
905 PRErrorCode perr;
906 bnToCssmData(openKey->pub_key, pubKeyRaw, coder);
907 perr = coder.encodeItem(&pubKeyRaw, SEC_UnsignedIntegerTemplate,
908 nssPubKey.publicKey);
909 if(perr) {
910 logAsnErr("encodeItem(DSAPublicKeyX509.publicKey)", perr);
911 return CSSMERR_CSP_MEMORY_ERROR;
912 }
913 nssPubKey.publicKey.Length *= 8;
914
915 /* DER encode */
916 SecNssEncodeItemOdata(&nssPubKey, NSS_DSAPublicKeyX509Template,
917 encodedKey);
918 return CSSM_OK;
919 }
920 catch(...) {
921 /* ? */
922 return CSSMERR_CSP_MEMORY_ERROR;
923 }
924 }
925
926 /*
927 * Encode public key portion only for calculating key digest.
928 * Note this works just fine on a partial DSA public key, i.e.,
929 * A DSA public key's digest-capable blob is the same whether or
930 * not the DSA key has its DSA parameters p, q, and g.
931 */
932 static CSSM_RETURN DSAPublicKeyEncodeHashable(
933 SecNssCoder &coder,
934 DSA *openKey,
935 CssmOwnedData &encodedKey)
936 {
937 try {
938 /*
939 * publicKey is the DER-encoding of an ASN integer
940 */
941 CSSM_DATA pubKey;
942 bnToCssmData(openKey->pub_key, pubKey, coder);
943 PRErrorCode perr;
944
945 perr = SecNssEncodeItemOdata(&pubKey, SEC_UnsignedIntegerTemplate,
946 encodedKey);
947 if(perr) {
948 logAsnErr("encode(DSAPubHashable)", perr);
949 return CSSMERR_CSP_MEMORY_ERROR;
950 }
951 return CSSM_OK;
952 }
953 catch(...) {
954 /* ? */
955 return CSSMERR_CSP_MEMORY_ERROR;
956 }
957 }
958
959 /*
960 * DSA private key, custom openssl format.
961 */
962 static CSSM_RETURN DSAPrivateKeyDecodeOpenssl(
963 SecNssCoder &coder,
964 DSA *openKey,
965 void *p,
966 size_t length)
967 {
968 NSS_DSAPrivateKeyOpenssl nssPrivKey;
969 PRErrorCode perr;
970
971 memset(&nssPrivKey, 0, sizeof(nssPrivKey));
972 perr = coder.decode(p, length, NSS_DSAPrivateKeyOpensslTemplate,
973 &nssPrivKey);
974 if(perr) {
975 logAsnErr("decode(DSAPrivateKeyOpenssl)", perr);
976 return CSSMERR_CSP_INVALID_KEY;
977 }
978
979 /* convert nssPrivKey fields to RSA key fields */
980 try {
981 openKey->version = cssmDataToInt(nssPrivKey.version);
982 openKey->p = cssmDataToBn(nssPrivKey.p);
983 openKey->q = cssmDataToBn(nssPrivKey.q);
984 openKey->g = cssmDataToBn(nssPrivKey.g);
985 openKey->pub_key = cssmDataToBn(nssPrivKey.pub);
986 openKey->priv_key = cssmDataToBn(nssPrivKey.priv);
987 }
988 catch(...) {
989 return CSSMERR_CSP_MEMORY_ERROR;
990 }
991 return 0;
992 }
993
994 static CSSM_RETURN DSAPrivateKeyEncodeOpenssl(
995 SecNssCoder &coder,
996 DSA *openKey,
997 CssmOwnedData &encodedKey)
998 {
999 NSS_DSAPrivateKeyOpenssl nssPrivKey;
1000 PRErrorCode perr;
1001
1002 /* convert to NSS_DSAPrivateKeyOpenssl */
1003 try {
1004 intToCssmData(openKey->version, nssPrivKey.version, coder);
1005 bnToCssmData(openKey->p, nssPrivKey.p, coder);
1006 bnToCssmData(openKey->q, nssPrivKey.q, coder);
1007 bnToCssmData(openKey->g, nssPrivKey.g, coder);
1008 bnToCssmData(openKey->pub_key, nssPrivKey.pub, coder);
1009 bnToCssmData(openKey->priv_key, nssPrivKey.priv, coder);
1010 }
1011 catch(...) {
1012 /* ? */
1013 return CSSMERR_CSP_MEMORY_ERROR;
1014 }
1015
1016 /* DER encode */
1017 perr = SecNssEncodeItemOdata(&nssPrivKey, NSS_DSAPrivateKeyOpensslTemplate,
1018 encodedKey);
1019 if(perr) {
1020 logAsnErr("encode(DSAPrivateKeyOpenssl)", perr);
1021 return CSSMERR_CSP_MEMORY_ERROR;
1022 }
1023 return CSSM_OK;
1024 }
1025
1026 CSSM_RETURN DSAPublicKeyDecode(
1027 DSA *openKey,
1028 CSSM_KEYBLOB_FORMAT format,
1029 void *p,
1030 size_t length)
1031 {
1032 SecNssCoder coder;
1033
1034 switch(format) {
1035 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
1036 return DSAPublicKeyDecodeFIPS186(coder, openKey, p, length);
1037 case CSSM_KEYBLOB_RAW_FORMAT_X509:
1038 return DSAPublicKeyDecodeX509(coder, openKey, p, length);
1039 default:
1040 assert(0);
1041 return CSSMERR_CSP_INTERNAL_ERROR;
1042 }
1043 }
1044
1045 CSSM_RETURN DSAPublicKeyEncode(
1046 DSA *openKey,
1047 CSSM_KEYBLOB_FORMAT format,
1048 CssmOwnedData &encodedKey)
1049 {
1050 SecNssCoder coder;
1051
1052 switch(format) {
1053 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
1054 return DSAPublicKeyEncodeFIPS186(coder, openKey, encodedKey);
1055 case CSSM_KEYBLOB_RAW_FORMAT_X509:
1056 return DSAPublicKeyEncodeX509(coder, openKey, encodedKey);
1057 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
1058 return DSAPublicKeyEncodeHashable(coder, openKey, encodedKey);
1059 default:
1060 assert(0);
1061 return CSSMERR_CSP_INTERNAL_ERROR;
1062 }
1063 }
1064
1065 CSSM_RETURN DSAPrivateKeyDecode(
1066 DSA *openKey,
1067 CSSM_KEYBLOB_FORMAT format,
1068 void *p,
1069 size_t length)
1070 {
1071 SecNssCoder coder;
1072
1073 switch(format) {
1074 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
1075 return DSAPrivateKeyDecodeFIPS186(coder, openKey, p, length);
1076 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
1077 return DSAPrivateKeyDecodeOpenssl(coder, openKey, p, length);
1078 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
1079 return DSAPrivateKeyDecodePKCS8(coder, openKey, p, length);
1080 default:
1081 assert(0);
1082 return CSSMERR_CSP_INTERNAL_ERROR;
1083 }
1084 }
1085
1086 CSSM_RETURN DSAPrivateKeyEncode(
1087 DSA *openKey,
1088 CSSM_KEYBLOB_FORMAT format,
1089 CssmOwnedData &encodedKey)
1090 {
1091 SecNssCoder coder;
1092
1093 switch(format) {
1094 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
1095 return DSAPrivateKeyEncodeFIPS186(coder, openKey, encodedKey);
1096 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
1097 return DSAPrivateKeyEncodeOpenssl(coder, openKey, encodedKey);
1098 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
1099 return DSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey);
1100 default:
1101 assert(0);
1102 return CSSMERR_CSP_INTERNAL_ERROR;
1103 }
1104 }
1105
1106 #pragma mark -
1107 #pragma mark *** DSA Signature encode/decode ***
1108
1109 CSSM_RETURN DSASigEncode(
1110 DSA_SIG *openSig,
1111 CssmOwnedData &encodedSig)
1112 {
1113 /* temp allocs from this pool */
1114 SecNssCoder coder;
1115 /* convert to NSS_DSASignature */
1116 NSS_DSASignature nssSig;
1117
1118 try {
1119 bnToCssmData(openSig->r, nssSig.r, coder);
1120 bnToCssmData(openSig->s, nssSig.s, coder);
1121 }
1122 catch(...) {
1123 /* ? */
1124 return CSSMERR_CSP_MEMORY_ERROR;
1125 }
1126
1127 PRErrorCode prtn = SecNssEncodeItemOdata(&nssSig,
1128 NSS_DSASignatureTemplate, encodedSig);
1129 if(prtn) {
1130 return CSSMERR_CSP_MEMORY_ERROR;
1131 }
1132 return CSSM_OK;
1133 }
1134
1135 CSSM_RETURN DSASigDecode(
1136 DSA_SIG *openSig,
1137 const void *p,
1138 unsigned length)
1139 {
1140 NSS_DSASignature nssSig;
1141 SecNssCoder coder;
1142
1143 memset(&nssSig, 0, sizeof(nssSig));
1144 PRErrorCode perr = coder.decode(p, length,
1145 NSS_DSASignatureTemplate, &nssSig);
1146 if(perr) {
1147 logAsnErr("decode(DSASigDecode)", perr);
1148 return CSSMERR_CSP_INVALID_SIGNATURE;
1149 }
1150
1151 try {
1152 openSig->r = cssmDataToBn(nssSig.r);
1153 openSig->s = cssmDataToBn(nssSig.s);
1154 }
1155 catch(...) {
1156 return CSSMERR_CSP_MEMORY_ERROR;
1157 }
1158 return 0;
1159 }
1160
1161 #pragma mark -
1162 #pragma mark *** DSA Algorithm Parameters encode/decode ***
1163
1164 CSSM_RETURN DSAEncodeAlgParams(
1165 NSS_DSAAlgParams &algParams,
1166 CssmOwnedData &encodedParams)
1167 {
1168 PRErrorCode prtn = SecNssEncodeItemOdata(&algParams,
1169 NSS_DSAAlgParamsTemplate, encodedParams);
1170 if(prtn) {
1171 return CSSMERR_CSP_MEMORY_ERROR;
1172 }
1173 return CSSM_OK;
1174 }
1175
1176 CSSM_RETURN DSADecodeAlgParams(
1177 NSS_DSAAlgParams &algParams,
1178 const void *p,
1179 unsigned len,
1180 SecNssCoder &coder)
1181 {
1182
1183 memset(&algParams, 0, sizeof(algParams));
1184 PRErrorCode perr = coder.decode(p, len,
1185 NSS_DSAAlgParamsTemplate, &algParams);
1186 if(perr) {
1187 logAsnErr("decode(DSAAlgParams)", perr);
1188 return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS;
1189 }
1190 return CSSM_OK;
1191 }
1192
1193 #pragma mark -
1194 #pragma mark *** Diffie-Hellman key encode/decode ***
1195
1196 CSSM_RETURN DHPrivateKeyDecodePKCS3(
1197 SecNssCoder &coder,
1198 DH *openKey,
1199 unsigned char *p,
1200 unsigned length)
1201 {
1202 NSS_DHPrivateKey nssPrivKey;
1203 PRErrorCode perr;
1204
1205 memset(&nssPrivKey, 0, sizeof(nssPrivKey));
1206 perr = coder.decode(p, length, NSS_DHPrivateKeyTemplate, &nssPrivKey);
1207 if(perr) {
1208 logAsnErr("decode(DHPrivateKey)", perr);
1209 return CSSMERR_CSP_INVALID_KEY;
1210 }
1211
1212 /* verify alg identifier */
1213 const CSSM_OID *oid = &nssPrivKey.dhOid;
1214 if(!cspCompareCssmData(oid, &CSSMOID_DH)) {
1215 sslAsn1Debug("DHPrivateKeyDecode: bad OID");
1216 return CSSMERR_CSP_ALGID_MISMATCH;
1217 }
1218
1219 NSS_DHParameter &params = nssPrivKey.params;
1220
1221 try {
1222 openKey->priv_key = cssmDataToBn(nssPrivKey.secretPart);
1223 openKey->p = cssmDataToBn(params.prime);
1224 openKey->g = cssmDataToBn(params.base);
1225 /* TBD - ignore privateValueLength for now */
1226 }
1227 catch(...) {
1228 /* FIXME - bad sig? memory? */
1229 return CSSMERR_CSP_MEMORY_ERROR;
1230 }
1231 return 0;
1232 }
1233
1234 CSSM_RETURN DHPrivateKeyEncodePKCS3(
1235 SecNssCoder &coder,
1236 DH *openKey,
1237 CssmOwnedData &encodedKey)
1238 {
1239 /* convert into a NSS_DHPrivateKey */
1240 NSS_DHPrivateKey nssPrivKey;
1241 NSS_DHParameter &params = nssPrivKey.params;
1242 memset(&nssPrivKey, 0, sizeof(nssPrivKey));
1243 nssPrivKey.dhOid = CSSMOID_DH;
1244
1245
1246 try {
1247 bnToCssmData(openKey->priv_key, nssPrivKey.secretPart, coder);
1248 bnToCssmData(openKey->p, params.prime, coder);
1249 bnToCssmData(openKey->g, params.base, coder);
1250 if(openKey->length) {
1251 /* actually currently not supported in openssl... */
1252 intToCssmData(openKey->length, params.privateValueLength, coder);
1253 }
1254 }
1255 catch(...) {
1256 return CSSMERR_CSP_MEMORY_ERROR;
1257 }
1258
1259 /* DER encode */
1260 PRErrorCode perr;
1261 perr = SecNssEncodeItemOdata(&nssPrivKey, NSS_DHPrivateKeyTemplate,
1262 encodedKey);
1263 if(perr) {
1264 logAsnErr("encode(DHPrivateKey)", perr);
1265 return CSSMERR_CSP_MEMORY_ERROR;
1266 }
1267 return CSSM_OK;
1268 }
1269
1270 /*
1271 * NSS_DHAlgorithmIdentifierX942 <--> DH
1272 * NOTE this is incomplete. It's functional on decode, but we throw
1273 * away everything except p and g. On encode, we put zeroes in
1274 * all the fields we don't deal with. Thus the encode side will NOT be
1275 * interoperable with other implementations.
1276 */
1277 static void dhToNssAlgIdX942(
1278 const DH *openKey,
1279 NSS_DHAlgorithmIdentifierX942 &algId,
1280 SecNssCoder &coder)
1281 {
1282 /*
1283 * When trying to encode a public key in X509 form, we may in
1284 * fact have nothing here - public keys created and exported in
1285 * PKCS3 have the pub_key value, and that's it.
1286 */
1287
1288 memset(&algId, 0, sizeof(algId));
1289 algId.oid = CSSMOID_ANSI_DH_PUB_NUMBER; // not mallocd
1290 NSS_DHDomainParamsX942 &params = algId.params;
1291 uint8 zero = 0;
1292 CSSM_DATA czero = {1, &zero};
1293 if(openKey->p != NULL) {
1294 bnToCssmData(openKey->p, params.p, coder);
1295 }
1296 else {
1297 coder.allocCopyItem(czero, params.p);
1298 }
1299 if(openKey->g != NULL) {
1300 bnToCssmData(openKey->g, params.g, coder);
1301 }
1302 else {
1303 coder.allocCopyItem(czero, params.g);
1304 }
1305 /* and we never have a vali0d q */
1306 coder.allocCopyItem(czero, params.q);
1307
1308 }
1309
1310 static CSSM_RETURN nssAlgIdToDhX942(
1311 NSS_DHAlgorithmIdentifierX942 &algId,
1312 DH *openKey)
1313 {
1314 if(!cspCompareCssmData(&algId.oid, &CSSMOID_ANSI_DH_PUB_NUMBER)) {
1315 sslAsn1Debug("nssAlgIdToDhX942: bad OID");
1316 return CSSMERR_CSP_INVALID_KEY;
1317 }
1318 openKey->p = cssmDataToBn(algId.params.p);
1319 openKey->g = cssmDataToBn(algId.params.g);
1320 return CSSM_OK;
1321 }
1322
1323 CSSM_RETURN DHPrivateKeyDecodePKCS8(
1324 SecNssCoder &coder,
1325 DH *openKey,
1326 unsigned char *p,
1327 unsigned length)
1328 {
1329 NSS_DHPrivateKeyPKCS8 nssPrivKey;
1330 PRErrorCode perr;
1331
1332 memset(&nssPrivKey, 0, sizeof(nssPrivKey));
1333 perr = coder.decode(p, length, NSS_DHPrivateKeyPKCS8Template,
1334 &nssPrivKey);
1335 if(perr) {
1336 logAsnErr("decode(DHPrivateKeyPKCS8)", perr);
1337 return CSSMERR_CSP_INVALID_KEY;
1338 }
1339
1340 try {
1341 CSSM_RETURN crtn = nssAlgIdToDhX942(nssPrivKey.algorithm, openKey);
1342 if(crtn) {
1343 return crtn;
1344 }
1345
1346 /* post-decode private key is a DER encoded integer */
1347 CSSM_DATA privKeyInt = {0, NULL};
1348 if(coder.decodeItem(nssPrivKey.privateKey,
1349 SEC_UnsignedIntegerTemplate,
1350 &privKeyInt)) {
1351 logAsnErr("decode(DHPrivateKeyPKCS8 privKey int)", perr);
1352 return CSSMERR_CSP_INVALID_KEY;
1353 }
1354
1355 openKey->priv_key = cssmDataToBn(privKeyInt);
1356 }
1357 catch(...) {
1358 /* FIXME - bad sig? memory? */
1359 return CSSMERR_CSP_MEMORY_ERROR;
1360 }
1361 return 0;
1362 }
1363
1364 CSSM_RETURN DHPrivateKeyEncodePKCS8(
1365 SecNssCoder &coder,
1366 DH *openKey,
1367 CssmOwnedData &encodedKey)
1368 {
1369 /* convert into a NSS_DHPrivateKeyPKCS8 */
1370 NSS_DHPrivateKeyPKCS8 nssPrivKey;
1371 memset(&nssPrivKey, 0, sizeof(nssPrivKey));
1372 uint8 vers = 0;
1373 nssPrivKey.version.Length = 1;
1374 nssPrivKey.version.Data = &vers;
1375 NSS_DHAlgorithmIdentifierX942 &alg = nssPrivKey.algorithm;
1376
1377 try {
1378
1379 dhToNssAlgIdX942(openKey, alg, coder);
1380 /* pre-encode, nssPrivKey.privateKey is the DER-encoding of
1381 * an ASN integer... */
1382 CSSM_DATA privKeyInt;
1383 bnToCssmData(openKey->priv_key, privKeyInt, coder);
1384
1385 /* DER encode the privateKey portion into arena pool memory
1386 * into nssPrivKey.privateKey */
1387 coder.encodeItem(&privKeyInt, SEC_UnsignedIntegerTemplate,
1388 nssPrivKey.privateKey);
1389 }
1390 catch(...) {
1391 return CSSMERR_CSP_MEMORY_ERROR;
1392 }
1393
1394 /* DER encode */
1395 PRErrorCode perr;
1396 perr = SecNssEncodeItemOdata(&nssPrivKey, NSS_DHPrivateKeyPKCS8Template,
1397 encodedKey);
1398 if(perr) {
1399 logAsnErr("encode(DHPrivateKey)", perr);
1400 return CSSMERR_CSP_MEMORY_ERROR;
1401 }
1402 return CSSM_OK;
1403 }
1404
1405 /*
1406 * In the PKCS3 form, the public blob is simply the literal
1407 * public key value, not DER encoded.
1408 */
1409 static CSSM_RETURN DHPublicKeyDecodePKCS3(
1410 DH *openKey,
1411 SecNssCoder &coder,
1412 unsigned char *p,
1413 unsigned length)
1414 {
1415 try {
1416 CSSM_DATA pubKey = {(uint32)length, (uint8 *)p};
1417 openKey->pub_key = cssmDataToBn(pubKey);
1418 return CSSM_OK;
1419 }
1420 catch(...) {
1421 return CSSMERR_CSP_MEMORY_ERROR;
1422 }
1423 }
1424
1425 static CSSM_RETURN DHPublicKeyEncodePKCS3(
1426 DH *openKey,
1427 SecNssCoder &coder,
1428 CssmOwnedData &encodedKey)
1429 {
1430 try {
1431 CSSM_DATA pubKey;
1432 bnToCssmData(openKey->pub_key, pubKey, coder);
1433 encodedKey.copy(CssmData::overlay(pubKey));
1434 return CSSM_OK;
1435 }
1436 catch(...) {
1437 return CSSMERR_CSP_MEMORY_ERROR;
1438 }
1439 }
1440
1441 static CSSM_RETURN DHPublicKeyDecodeX509(
1442 DH *openKey,
1443 SecNssCoder &coder,
1444 unsigned char *p,
1445 unsigned length)
1446 {
1447 NSS_DHPublicKeyX509 nssPubKey;
1448 PRErrorCode perr;
1449
1450 memset(&nssPubKey, 0, sizeof(nssPubKey));
1451 perr = coder.decode(p, length, NSS_DHPublicKeyX509Template,
1452 &nssPubKey);
1453 if(perr) {
1454 logAsnErr("decode(DHPublicKeyX509)", perr);
1455 return CSSMERR_CSP_INVALID_KEY;
1456 }
1457
1458 try {
1459 CSSM_RETURN crtn = nssAlgIdToDhX942(nssPubKey.algorithm, openKey);
1460 if(crtn) {
1461 return crtn;
1462 }
1463
1464 /*
1465 * Post-decode public key length in bits
1466 * Contents are pub_key as DER-encoded INTEGER
1467 */
1468 CSSM_DATA &pubKey = nssPubKey.publicKey;
1469 pubKey.Length = (pubKey.Length + 7) / 8;
1470 CSSM_DATA pubKeyInt = {0, NULL};
1471 if(coder.decodeItem(pubKey,
1472 SEC_UnsignedIntegerTemplate, &pubKeyInt)) {
1473 logAsnErr("decode(DHPublicKeyX509 pub key int)", perr);
1474 return CSSMERR_CSP_INVALID_KEY;
1475 }
1476 openKey->pub_key = cssmDataToBn(pubKeyInt);
1477 }
1478 catch(...) {
1479 /* FIXME - bad sig? memory? */
1480 return CSSMERR_CSP_MEMORY_ERROR;
1481 }
1482 return 0;
1483 }
1484
1485 static CSSM_RETURN DHPublicKeyEncodeX509(
1486 DH *openKey,
1487 SecNssCoder &coder,
1488 CssmOwnedData &encodedKey)
1489 {
1490 /* convert into a NSS_DHPublicKeyX509 */
1491 NSS_DHPublicKeyX509 nssPubKey;
1492 memset(&nssPubKey, 0, sizeof(nssPubKey));
1493 NSS_DHAlgorithmIdentifierX942 &alg = nssPubKey.algorithm;
1494
1495 try {
1496 dhToNssAlgIdX942(openKey, alg, coder);
1497
1498 /* encode pub_key as integer */
1499 CSSM_DATA pubKeyInt = {0, NULL};
1500 bnToCssmData(openKey->pub_key, pubKeyInt, coder);
1501 coder.encodeItem(&pubKeyInt, SEC_UnsignedIntegerTemplate,
1502 nssPubKey.publicKey);
1503 /* specify length in bits */
1504 nssPubKey.publicKey.Length *= 8;
1505 }
1506 catch(...) {
1507 return CSSMERR_CSP_MEMORY_ERROR;
1508 }
1509
1510 /* DER encode */
1511 PRErrorCode perr;
1512 perr = SecNssEncodeItemOdata(&nssPubKey, NSS_DHPublicKeyX509Template,
1513 encodedKey);
1514 if(perr) {
1515 logAsnErr("encode(DHPublicKeyX509)", perr);
1516 return CSSMERR_CSP_MEMORY_ERROR;
1517 }
1518 return CSSM_OK;
1519 }
1520
1521 CSSM_RETURN DHPrivateKeyDecode(
1522 DH *openKey,
1523 CSSM_KEYBLOB_FORMAT format,
1524 unsigned char *p,
1525 unsigned length)
1526 {
1527 SecNssCoder coder;
1528
1529 switch(format) {
1530 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
1531 return DHPrivateKeyDecodePKCS3(coder, openKey, p, length);
1532 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
1533 return DHPrivateKeyDecodePKCS8(coder, openKey, p, length);
1534 default:
1535 assert(0);
1536 return CSSMERR_CSP_INTERNAL_ERROR;
1537 }
1538 }
1539
1540 CSSM_RETURN DHPrivateKeyEncode(
1541 DH *openKey,
1542 CSSM_KEYBLOB_FORMAT format,
1543 CssmOwnedData &encodedKey)
1544 {
1545 SecNssCoder coder;
1546
1547 switch(format) {
1548 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
1549 return DHPrivateKeyEncodePKCS3(coder, openKey, encodedKey);
1550 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
1551 return DHPrivateKeyEncodePKCS8(coder, openKey, encodedKey);
1552 default:
1553 assert(0);
1554 return CSSMERR_CSP_INTERNAL_ERROR;
1555 }
1556 }
1557
1558 CSSM_RETURN DHPublicKeyDecode(
1559 DH *openKey,
1560 CSSM_KEYBLOB_FORMAT format,
1561 unsigned char *p,
1562 unsigned length)
1563 {
1564 SecNssCoder coder;
1565
1566 switch(format) {
1567 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
1568 return DHPublicKeyDecodePKCS3(openKey, coder, p, length);
1569 case CSSM_KEYBLOB_RAW_FORMAT_X509:
1570 return DHPublicKeyDecodeX509(openKey, coder, p, length);
1571 default:
1572 assert(0);
1573 return CSSMERR_CSP_INTERNAL_ERROR;
1574 }
1575 }
1576
1577 CSSM_RETURN DHPublicKeyEncode(
1578 DH *openKey,
1579 CSSM_KEYBLOB_FORMAT format,
1580 CssmOwnedData &encodedKey)
1581 {
1582 SecNssCoder coder;
1583
1584 switch(format) {
1585 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
1586 return DHPublicKeyEncodePKCS3(openKey, coder, encodedKey);
1587 case CSSM_KEYBLOB_RAW_FORMAT_X509:
1588 return DHPublicKeyEncodeX509(openKey, coder, encodedKey);
1589 default:
1590 assert(0);
1591 return CSSMERR_CSP_INTERNAL_ERROR;
1592 }
1593 }
1594
1595 /*
1596 * Encode/decode a NSS_DHParameterBlock.
1597 */
1598 CSSM_RETURN DHParamBlockDecode(
1599 const CSSM_DATA &encParam,
1600 NSS_DHParameterBlock &paramBlock,
1601 SecNssCoder &coder)
1602 {
1603 PRErrorCode perr;
1604
1605 memset(&paramBlock, 0, sizeof(paramBlock));
1606 perr = coder.decodeItem(encParam, NSS_DHParameterBlockTemplate,
1607 &paramBlock);
1608 if(perr == 0) {
1609 return CSSM_OK;
1610 }
1611
1612 /*
1613 * CDSA Extension: the CDSA Algorithm Guide says that the D-H
1614 * parameter block is supposed to be wrapped with its accompanying
1615 * OID. However Openssl does not do this; it just exports
1616 * an encoded DHParameter rather than a DHParameterBlock.
1617 * For compatibility we'll try decoding the parameters as one
1618 * of these.
1619 */
1620 memset(&paramBlock, 0, sizeof(paramBlock));
1621 perr = coder.decodeItem(encParam, NSS_DHParameterTemplate,
1622 &paramBlock.params);
1623 if(perr == 0) {
1624 return CSSM_OK;
1625 }
1626 return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS;
1627 }
1628
1629 #pragma mark -
1630 #pragma mark *** Message Digest ***
1631
1632 /*
1633 * Given a message digest and associated algorithm, cook up a PKCS1-style
1634 * DigestInfo and return its DER encoding. This is a necessary step for
1635 * RSA signature (both generating and verifying) - the output of this
1636 * routine is what gets encrypted during signing, and what is expected when
1637 * verifying (i.e., decrypting the signature).
1638 *
1639 * A good guess for the length of the output digestInfo is the size of the
1640 * key being used to sign/verify. The digest can never be larger than that.
1641 */
1642 CSSM_RETURN generateDigestInfo(
1643 const void *msgDigest,
1644 size_t digestLen,
1645 CSSM_ALGORITHMS digestAlg, // CSSM_ALGID_SHA1, etc.
1646 CssmOwnedData &encodedInfo,
1647 size_t maxEncodedSize)
1648 {
1649 if(digestAlg == CSSM_ALGID_NONE) {
1650 /* special case, no encode, just copy */
1651 encodedInfo.copy(msgDigest, digestLen);
1652 return 0;
1653 }
1654
1655 NSS_DigestInfo digestInfo;
1656 CSSM_X509_ALGORITHM_IDENTIFIER &algId = digestInfo.digestAlgorithm;
1657
1658 memset(&digestInfo, 0, sizeof(digestInfo));
1659 switch(digestAlg) {
1660 case CSSM_ALGID_MD5:
1661 algId.algorithm = CSSMOID_MD5;
1662 break;
1663 case CSSM_ALGID_MD2:
1664 algId.algorithm = CSSMOID_MD2;
1665 break;
1666 case CSSM_ALGID_SHA1:
1667 algId.algorithm = CSSMOID_SHA1;
1668 break;
1669 default:
1670 return CSSMERR_CSP_INVALID_ALGORITHM;
1671 }
1672 nullAlgParams(algId);
1673 digestInfo.digest.Data = (uint8 *)msgDigest;
1674 digestInfo.digest.Length = digestLen;
1675
1676 /* DER encode */
1677 PRErrorCode perr;
1678 perr = SecNssEncodeItemOdata(&digestInfo, NSS_DigestInfoTemplate,
1679 encodedInfo);
1680 if(perr) {
1681 logAsnErr("encode(digestInfo)", perr);
1682 return CSSMERR_CSP_MEMORY_ERROR;
1683 }
1684 return CSSM_OK;
1685 }
1686