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