2 * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved.
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
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.
20 * opensslAsn1.h - ANS1 encode/decode of openssl object, libssnasn1 version
22 #include "opensslAsn1.h"
23 #include "BinaryKey.h"
24 #include "AppleCSPUtils.h"
25 #include "opensshCoding.h"
26 #include <Security/osKeyTemplates.h>
27 #include <openssl/opensslerr.h>
28 #include <openssl/bn_legacy.h>
29 #include <openssl/crypto_legacy.h>
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>
38 #include <security_utilities/simulatecrash_assert.h>
40 #define sslAsn1Debug(args...) secinfo("sslAsn1", ##args)
43 /* set to 1 to see all ASN related errors */
44 #define LOG_ASN_ERRORS 0
46 #define LOG_ASN_ERRORS 0
51 #include <security_asn1/secerr.h>
53 static void logAsnErr(
57 printf("Error on %s: %s\n", op
, SECErrorString(perr
));
60 #define logAsnErr(op, perr)
61 #endif /* LOG_ASN_ERRORS */
63 /* CSSM_DATA --> BIGNUM */
65 const CSSM_DATA
&cdata
)
67 BIGNUM
*bn
= BN_new();
70 rtn
= BN_bin2bn(cdata
.Data
, (int)cdata
.Length
, bn
);
73 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
78 /* BIGNUM --> CSSM_DATA, mallocing from a SecNssCoder's PL_ArenaPool */
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
);
90 cdata
.Length
= numBytes
;
91 BN_bn2bin(bn
, cdata
.Data
);
95 * CSSM_DATA --> unsigned int
97 unsigned cssmDataToInt(
98 const CSSM_DATA
&cdata
)
100 if((cdata
.Length
== 0) || (cdata
.Data
== NULL
)) {
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
);
110 uint8
*cp
= cdata
.Data
;
111 for(unsigned i
=0; i
<len
; i
++) {
112 rtn
= (rtn
<< 8) | *cp
++;
118 * unsigned int --> CSSM_DATA, mallocing from an SecNssCoder
130 else if(num
< 0x10000) {
133 else if(num
< 0x1000000) {
139 cdata
.Data
= (uint8
*)coder
.malloc(len
);
141 uint8
*cp
= &cdata
.Data
[len
- 1];
142 for(unsigned i
=0; i
<len
; i
++) {
149 * Set up a encoded NULL for AlgorithmIdentifier.parameters,
152 static void nullAlgParams(
153 CSSM_X509_ALGORITHM_IDENTIFIER
&algId
)
155 static const uint8 encNull
[2] = { SEC_ASN1_NULL
, 0 };
156 CSSM_DATA encNullData
;
157 encNullData
.Data
= (uint8
*)encNull
;
158 encNullData
.Length
= 2;
160 algId
.parameters
= encNullData
;
164 #pragma mark *** RSA key encode/decode ***
167 * DER encode/decode RSA keys in various formats.
169 * Public key, CSSM_KEYBLOB_RAW_FORMAT_PKCS1
170 * -- compatible with BSAFE
171 * -- used for CSSM_KEYBLOB_RAW_FORMAT_DIGEST on both keys
173 static CSSM_RETURN
RSAPublicKeyDecodePKCS1(
179 NSS_RSAPublicKeyPKCS1 nssPubKey
;
181 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
182 PRErrorCode perr
= coder
.decode(p
, length
,
183 kSecAsn1RSAPublicKeyPKCS1Template
, &nssPubKey
);
185 logAsnErr("decode(RSAPublicKeyPKCS1)", perr
);
186 return CSSMERR_CSP_INVALID_KEY
;
190 openKey
->n
= cssmDataToBn(nssPubKey
.modulus
);
191 openKey
->e
= cssmDataToBn(nssPubKey
.publicExponent
);
194 return CSSMERR_CSP_MEMORY_ERROR
;
199 static CSSM_RETURN
RSAPublicKeyEncodePKCS1(
202 CssmOwnedData
&encodedKey
)
204 /* convert to NSS_RSAPublicKeyPKCS1 */
205 NSS_RSAPublicKeyPKCS1 nssPubKey
;
208 bnToCssmData(openKey
->n
, nssPubKey
.modulus
, coder
);
209 bnToCssmData(openKey
->e
, nssPubKey
.publicExponent
, coder
);
212 return CSSMERR_CSP_MEMORY_ERROR
;
216 prtn
= SecNssEncodeItemOdata(&nssPubKey
,
217 kSecAsn1RSAPublicKeyPKCS1Template
, encodedKey
);
219 return CSSMERR_CSP_MEMORY_ERROR
;
225 * SubjectPublicKeyInfo, as used by openssl.
226 * The subjectPublicKey component is a PKCS1-style RSAPublicKey.
228 static CSSM_RETURN
RSAPublicKeyDecodeX509(
233 /* mallocd/returned encoded alg params for OAEP key */
235 CSSM_SIZE
*algParamLen
)
237 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo
;
240 memset(&nssPubKeyInfo
, 0, sizeof(nssPubKeyInfo
));
241 perr
= coder
.decode(p
, length
, kSecAsn1SubjectPublicKeyInfoTemplate
,
244 logAsnErr("decode(RSA SubjectPublicKeyInfo)", perr
);
245 return CSSMERR_CSP_INVALID_KEY
;
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
;
255 if(nssPubKeyInfo
.algorithm
.parameters
.Data
!= NULL
) {
256 CSSM_SIZE len
= nssPubKeyInfo
.algorithm
.parameters
.Length
;
257 *algParams
= (uint8
*)malloc(len
);
258 memmove(*algParams
, nssPubKeyInfo
.algorithm
.parameters
.Data
, len
);
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
,
271 static CSSM_RETURN
RSAPublicKeyEncodeX509(
274 CssmOwnedData
&encodedKey
,
275 /* encoded alg params for OAEP key */
279 CssmAutoData
aData(Allocator::standard());
282 /* First get an encoded PKCS1-style RSAPublicKey */
283 crtn
= RSAPublicKeyEncodePKCS1(coder
, openKey
, aData
);
289 * That's the AsnBits subjectPublicKey component of a
290 * SubjectPublicKeyInfo
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;
297 CSSM_X509_ALGORITHM_IDENTIFIER
&algId
= nssPubKeyInfo
.algorithm
;
298 algId
.algorithm
= CSSMOID_RSA
;
301 algId
.parameters
.Data
= (uint8
*)algParams
;
302 algId
.parameters
.Length
= algParamsLen
;
305 /* NULL algorithm parameters */
306 nullAlgParams(algId
);
311 perr
= SecNssEncodeItemOdata(&nssPubKeyInfo
,
312 kSecAsn1SubjectPublicKeyInfoTemplate
, encodedKey
);
315 logAsnErr("encode(RSA SubjectPublicKeyInfo)", perr
);
316 return CSSMERR_CSP_MEMORY_ERROR
;
322 * RSA private key, PKCS1 format, used by openssl.
324 static CSSM_RETURN
RSAPrivateKeyDecodePKCS1(
330 NSS_RSAPrivateKeyPKCS1 nssPrivKey
;
333 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
334 perr
= coder
.decode(p
, length
, kSecAsn1RSAPrivateKeyPKCS1Template
, &nssPrivKey
);
336 logAsnErr("decode(RSAPrivateKeyPKCS)", perr
);
337 return CSSMERR_CSP_INVALID_KEY
;
340 /* convert nssPrivKey fields to RSA key fields */
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
);
353 return CSSMERR_CSP_MEMORY_ERROR
;
358 static CSSM_RETURN
RSAPrivateKeyEncodePKCS1(
361 CssmOwnedData
&encodedKey
)
363 NSS_RSAPrivateKeyPKCS1 nssPrivKey
;
366 /* convert to NSS_RSAPrivateKeyPKCS1 */
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
);
380 return CSSMERR_CSP_MEMORY_ERROR
;
384 perr
= SecNssEncodeItemOdata(&nssPrivKey
, kSecAsn1RSAPrivateKeyPKCS1Template
,
387 logAsnErr("encode(RSAPrivateKeyPKCS1)", perr
);
388 return CSSMERR_CSP_MEMORY_ERROR
;
394 * RSA private key, PKCS8, compatible with BSAFE.
396 static CSSM_RETURN
RSAPrivateKeyDecodePKCS8(
401 /* mallocd/returned encoded alg params for OAEP key */
403 CSSM_SIZE
*algParamLen
)
405 NSS_PrivateKeyInfo nssPrivKeyInfo
;
408 memset(&nssPrivKeyInfo
, 0, sizeof(nssPrivKeyInfo
));
409 perr
= coder
.decode(p
, length
, kSecAsn1PrivateKeyInfoTemplate
, &nssPrivKeyInfo
);
411 logAsnErr("decode(PrivateKeyInfo)", perr
);
412 return CSSMERR_CSP_INVALID_KEY
;
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
;
422 if(nssPrivKeyInfo
.algorithm
.parameters
.Data
!= NULL
) {
423 CSSM_SIZE len
= nssPrivKeyInfo
.algorithm
.parameters
.Length
;
424 *algParams
= (uint8
*)malloc(len
);
425 memmove(*algParams
, nssPrivKeyInfo
.algorithm
.parameters
.Data
, len
);
431 * nssPrivKeyInfo.privateKey is an octet string which needs
432 * subsequent decoding
434 CSSM_DATA
*privKey
= &nssPrivKeyInfo
.privateKey
;
435 return RSAPrivateKeyDecodePKCS1(coder
, openKey
,
436 privKey
->Data
, privKey
->Length
);
439 static CSSM_RETURN
RSAPrivateKeyEncodePKCS8(
442 CssmOwnedData
&encodedKey
,
443 /* encoded alg params for OAEP key */
448 /* First get PKCS1-style encoding */
449 CssmAutoData
aData(Allocator::standard());
450 CSSM_RETURN crtn
= RSAPrivateKeyEncodePKCS1(coder
, openKey
, aData
);
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();
461 CSSM_X509_ALGORITHM_IDENTIFIER
&algId
= nssPrivKeyInfo
.algorithm
;
462 algId
.algorithm
= CSSMOID_RSA
;
465 algId
.parameters
.Data
= (uint8
*)algParams
;
466 algId
.parameters
.Length
= algParamsLen
;
469 /* NULL algorithm parameters */
470 nullAlgParams(algId
);
473 /* FIXME : attributes? */
476 nssPrivKeyInfo
.version
.Data
= &vers
;
477 nssPrivKeyInfo
.version
.Length
= 1;
481 perr
= SecNssEncodeItemOdata(&nssPrivKeyInfo
,
482 kSecAsn1PrivateKeyInfoTemplate
, encodedKey
);
485 logAsnErr("encode(RSA PrivateKeyInfo)", perr
);
486 return CSSMERR_CSP_MEMORY_ERROR
;
491 CSSM_RETURN
RSAPublicKeyDecode(
493 CSSM_KEYBLOB_FORMAT 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
);
510 return CSSMERR_CSP_INTERNAL_ERROR
;
514 CSSM_RETURN
RSAPublicKeyEncode(
516 CSSM_KEYBLOB_FORMAT format
,
517 const CssmData
&descData
,
518 CssmOwnedData
&encodedKey
)
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
);
533 return CSSMERR_CSP_INTERNAL_ERROR
;
537 CSSM_RETURN
RSAPrivateKeyDecode(
539 CSSM_KEYBLOB_FORMAT 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
);
554 return CSSMERR_CSP_INTERNAL_ERROR
;
558 CSSM_RETURN
RSAPrivateKeyEncode(
560 CSSM_KEYBLOB_FORMAT format
,
561 const CssmData
&descData
,
562 CssmOwnedData
&encodedKey
)
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
);
575 return CSSMERR_CSP_INTERNAL_ERROR
;
579 CSSM_RETURN
RSAOAEPPrivateKeyEncode(
581 const CSSM_DATA
*label
,
582 CssmOwnedData
&encodedKey
)
585 CSSM_DATA encodedParams
= {0, NULL
};
586 /* TBD encode the label into a RSAES-OAEP-params */
588 return RSAPrivateKeyEncodePKCS8(coder
, openKey
, encodedKey
, encodedParams
.Data
, (unsigned int)encodedParams
.Length
);
591 CSSM_RETURN
RSAOAEPPublicKeyEncode(
593 const CSSM_DATA
*label
,
594 CssmOwnedData
&encodedKey
)
597 CSSM_DATA encodedParams
= {0, NULL
};
598 /* TBD encode the label into a RSAES-OAEP-params */
600 return RSAPublicKeyEncodeX509(coder
, openKey
, encodedKey
, encodedParams
.Data
, (unsigned int)encodedParams
.Length
);
603 CSSM_RETURN
RSAOAEPPublicKeyDecode(
607 /* mallocd and returned label */
612 CSSM_DATA encodedParams
= {0, NULL
};
614 crtn
= RSAPublicKeyDecodeX509(coder
, openKey
, p
, length
, &encodedParams
.Data
,
615 &encodedParams
.Length
);
620 /* TBD - decode label from encoded alg params */
626 CSSM_RETURN
RSAOAEPPrivateKeyDecode(
630 /* mallocd and returned label */
635 CSSM_DATA encodedParams
= {0, NULL
};
637 crtn
= RSAPrivateKeyDecodePKCS8(coder
, openKey
, p
, length
, &encodedParams
.Data
,
638 &encodedParams
.Length
);
643 /* TBD - decode label from encoded alg params */
650 #pragma mark *** DSA key encode/decode ***
656 /* NSS_DSAAlgorithmIdBSAFE <--> DSA->{p,g,q} */
657 static void dsaToNssAlgIdBSAFE(
659 NSS_DSAAlgorithmIdBSAFE
&algId
,
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
);
671 static CSSM_RETURN
nssAlgIdToDsaBSAFE(
672 NSS_DSAAlgorithmIdBSAFE
&algId
,
675 /* non-standard, BSAFE-specific OID */
676 if(!cspCompareCssmData(&algId
.algorithm
, &CSSMOID_DSA
)) {
677 sslAsn1Debug("nssAlgIdToDsaBSAFE: bad OID");
678 return CSSMERR_CSP_INVALID_KEY
;
680 openKey
->p
= cssmDataToBn(algId
.params
.p
);
681 openKey
->q
= cssmDataToBn(algId
.params
.q
);
682 openKey
->g
= cssmDataToBn(algId
.params
.g
);
686 /* NSS_DSAAlgorithmIdX509 <--> DSA->{p,g,q} */
687 static void dsaToNssAlgIdX509(
689 NSS_DSAAlgorithmIdX509
&algId
,
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
);
698 static CSSM_RETURN
nssAlgIdToDsaX509(
699 NSS_DSAAlgorithmIdX509
&algId
,
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
;
707 /* these might be absent per CMS */
708 if(algId
.params
== NULL
) {
711 openKey
->p
= cssmDataToBn(algId
.params
->p
);
712 openKey
->q
= cssmDataToBn(algId
.params
->q
);
713 openKey
->g
= cssmDataToBn(algId
.params
->g
);
718 * DSA public keys, FIPS186 format.
719 * Compatible with BSAFE.
722 CSSM_RETURN
DSAPublicKeyDecodeFIPS186(
728 NSS_DSAPublicKeyBSAFE nssPubKey
;
732 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
733 perr
= coder
.decode(p
, length
, kSecAsn1DSAPublicKeyBSAFETemplate
,
736 logAsnErr("decode(DSAPublicKeyBSAFE)", perr
);
737 return CSSMERR_CSP_INVALID_KEY
;
740 /* BSAFE style DSA-specific alg params */
741 NSS_DSAAlgorithmIdBSAFE
&algId
= nssPubKey
.dsaAlg
;
742 crtn
= nssAlgIdToDsaBSAFE(algId
, openKey
);
747 /* inside of nssPubKey.publicKey is the DER-encoding of a
748 * ASN Integer; decoded length was in bits */
749 nssPubKey
.publicKey
.Length
= (nssPubKey
.publicKey
.Length
+ 7) / 8;
750 CSSM_DATA pubKeyBytes
;
751 perr
= coder
.decodeItem(nssPubKey
.publicKey
,
752 kSecAsn1UnsignedIntegerTemplate
,
755 logAsnErr("decode(NSS_DSAPublicKeyBSAFE.publicKey)", perr
);
756 return CSSMERR_CSP_INVALID_KEY
;
758 openKey
->pub_key
= cssmDataToBn(pubKeyBytes
);
760 if(openKey
->pub_key
== NULL
) {
761 return CSSMERR_CSP_INVALID_KEY
;
767 CSSM_RETURN
DSAPublicKeyEncodeFIPS186(
770 CssmOwnedData
&encodedKey
)
773 /* convert to NSS_DSAPublicKeyBSAFE */
774 NSS_DSAPublicKeyBSAFE nssPubKey
;
775 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
776 dsaToNssAlgIdBSAFE(openKey
, nssPubKey
.dsaAlg
, coder
);
779 * publicKey is the DER-encoding of a ASN INTEGER wrapped in
784 bnToCssmData(openKey
->pub_key
, pubKeyRaw
, coder
);
785 perr
= coder
.encodeItem(&pubKeyRaw
, kSecAsn1UnsignedIntegerTemplate
,
786 nssPubKey
.publicKey
);
788 logAsnErr("encodeItem(DSAPublicKeyBSAFE.publicKey)", perr
);
789 return CSSMERR_CSP_MEMORY_ERROR
;
791 nssPubKey
.publicKey
.Length
*= 8;
794 SecNssEncodeItemOdata(&nssPubKey
, kSecAsn1DSAPublicKeyBSAFETemplate
,
800 return CSSMERR_CSP_MEMORY_ERROR
;
805 * DSA private keys, FIPS186 format.
806 * Compatible with BSAFE.
809 CSSM_RETURN
DSAPrivateKeyDecodeFIPS186(
815 NSS_DSAPrivateKeyBSAFE nssPrivKeyInfo
;
818 memset(&nssPrivKeyInfo
, 0, sizeof(nssPrivKeyInfo
));
819 perr
= coder
.decode(p
, length
, kSecAsn1DSAPrivateKeyBSAFETemplate
,
822 logAsnErr("decode(DSA PrivateKeyInfo)", perr
);
823 return CSSMERR_CSP_INVALID_KEY
;
826 CSSM_RETURN crtn
= nssAlgIdToDsaBSAFE(nssPrivKeyInfo
.dsaAlg
, openKey
);
831 /* nssPrivKeyInfo.privateKey is the DER-encoding of a
832 * DSAPrivateKeyOcts... */
835 NSS_DSAPrivateKeyOcts keyOcts
;
837 perr
= coder
.decodeItem(nssPrivKeyInfo
.privateKey
,
838 kSecAsn1DSAPrivateKeyOctsTemplate
, &keyOcts
);
840 logAsnErr("decode(DSA PrivateKeyInfoOcts)", perr
);
841 return CSSMERR_CSP_INVALID_KEY
;
844 openKey
->priv_key
= cssmDataToBn(keyOcts
.privateKey
);
845 if(openKey
->priv_key
== NULL
) {
846 return CSSMERR_CSP_INVALID_KEY
;
851 return CSSMERR_CSP_INVALID_KEY
;
856 CSSM_RETURN
DSAPrivateKeyEncodeFIPS186(
859 CssmOwnedData
&encodedKey
)
862 /* First convert into a NSS_DSAPrivateKeyBSAFE */
863 NSS_DSAPrivateKeyBSAFE nssPrivKey
;
864 intToCssmData(openKey
->version
, nssPrivKey
.version
, coder
);
865 dsaToNssAlgIdBSAFE(openKey
, nssPrivKey
.dsaAlg
, coder
);
867 /* nssPrivKey.privateKey is the DER-encoding of one of these... */
868 NSS_DSAPrivateKeyOcts privKeyOcts
;
869 bnToCssmData(openKey
->priv_key
, privKeyOcts
.privateKey
, coder
);
871 /* DER encode the privateKey portion into arena pool memory
872 * into NSS_DSAPrivateKeyPKCS8.privateKey */
873 coder
.encodeItem(&privKeyOcts
, kSecAsn1DSAPrivateKeyOctsTemplate
,
874 nssPrivKey
.privateKey
);
876 /* DER encode the whole thing */
878 perr
= SecNssEncodeItemOdata(&nssPrivKey
,
879 kSecAsn1DSAPrivateKeyBSAFETemplate
, encodedKey
);
884 return CSSMERR_CSP_MEMORY_ERROR
;
889 * DSA private keys, PKCS8/SMIME format.
892 CSSM_RETURN
DSAPrivateKeyDecodePKCS8(
898 NSS_DSAPrivateKeyPKCS8 nssPrivKeyInfo
;
901 memset(&nssPrivKeyInfo
, 0, sizeof(nssPrivKeyInfo
));
902 perr
= coder
.decode(p
, length
, kSecAsn1DSAPrivateKeyPKCS8Template
,
905 logAsnErr("decode(DSA NSS_DSAPrivateKeyPKCS8)", perr
);
906 return CSSMERR_CSP_INVALID_KEY
;
909 CSSM_RETURN crtn
= nssAlgIdToDsaX509(nssPrivKeyInfo
.dsaAlg
, openKey
);
915 * Post-decode, nssPrivKeyInfo.privateKey is the DER-encoding of a
920 CSSM_DATA privKeyInt
= {0, NULL
};
922 perr
= coder
.decodeItem(nssPrivKeyInfo
.privateKey
,
923 kSecAsn1UnsignedIntegerTemplate
, &privKeyInt
);
925 logAsnErr("decode(DSA nssPrivKeyInfo.privateKey)", perr
);
926 return CSSMERR_CSP_INVALID_KEY
;
929 openKey
->priv_key
= cssmDataToBn(privKeyInt
);
930 if(openKey
->priv_key
== NULL
) {
931 return CSSMERR_CSP_INVALID_KEY
;
936 return CSSMERR_CSP_INVALID_KEY
;
941 CSSM_RETURN
DSAPrivateKeyEncodePKCS8(
944 CssmOwnedData
&encodedKey
)
947 /* First convert into a NSS_DSAPrivateKeyPKCS8 */
948 NSS_DSAPrivateKeyPKCS8 nssPrivKey
;
949 NSS_DSAAlgParams algParams
;
950 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
951 memset(&algParams
, 0, sizeof(algParams
));
952 nssPrivKey
.dsaAlg
.params
= &algParams
;
953 intToCssmData(openKey
->version
, nssPrivKey
.version
, coder
);
954 dsaToNssAlgIdX509(openKey
, nssPrivKey
.dsaAlg
, coder
);
956 /* pre-encode, nssPrivKey.privateKey is the DER-encoding of
957 * an ASN integer... */
958 CSSM_DATA privKeyInt
;
959 bnToCssmData(openKey
->priv_key
, privKeyInt
, coder
);
961 /* DER encode the privateKey portion into arena pool memory
962 * into NSS_DSAPrivateKeyPKCS8.privateKey */
963 coder
.encodeItem(&privKeyInt
, kSecAsn1UnsignedIntegerTemplate
,
964 nssPrivKey
.privateKey
);
966 /* DER encode the whole thing */
968 perr
= SecNssEncodeItemOdata(&nssPrivKey
,
969 kSecAsn1DSAPrivateKeyPKCS8Template
, encodedKey
);
974 return CSSMERR_CSP_MEMORY_ERROR
;
979 * DSA public key, X509/openssl format.
981 static CSSM_RETURN
DSAPublicKeyDecodeX509(
987 NSS_DSAPublicKeyX509 nssPubKey
;
991 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
992 perr
= coder
.decode(p
, length
, kSecAsn1DSAPublicKeyX509Template
,
995 logAsnErr("decode(DSAPublicKeyX509)", perr
);
996 return CSSMERR_CSP_INVALID_KEY
;
999 /* X509 style DSA-specific alg params */
1000 NSS_DSAAlgorithmIdX509
&algId
= nssPubKey
.dsaAlg
;
1001 crtn
= nssAlgIdToDsaX509(algId
, openKey
);
1006 /* inside of nssPubKey.publicKey is the DER-encoding of a
1007 * ASN Integer; decoded length was in bits */
1008 nssPubKey
.publicKey
.Length
= (nssPubKey
.publicKey
.Length
+ 7) / 8;
1009 CSSM_DATA pubKeyBytes
= {0, NULL
};
1010 perr
= coder
.decodeItem(nssPubKey
.publicKey
,
1011 kSecAsn1UnsignedIntegerTemplate
,
1014 logAsnErr("decode(NSS_DSAPublicKeyX509.publicKey)", perr
);
1015 return CSSMERR_CSP_INVALID_KEY
;
1017 openKey
->pub_key
= cssmDataToBn(pubKeyBytes
);
1019 if(openKey
->pub_key
== NULL
) {
1020 return CSSMERR_CSP_INVALID_KEY
;
1025 static CSSM_RETURN
DSAPublicKeyEncodeX509(
1028 CssmOwnedData
&encodedKey
)
1031 /* convert to NSS_DSAPublicKeyX509 */
1032 NSS_DSAPublicKeyX509 nssPubKey
;
1033 NSS_DSAAlgParams algParams
;
1034 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
1035 memset(&algParams
, 0, sizeof(algParams
));
1036 nssPubKey
.dsaAlg
.params
= &algParams
;
1037 dsaToNssAlgIdX509(openKey
, nssPubKey
.dsaAlg
, coder
);
1040 * publicKey is the DER-encoding of a ASN INTEGER wrapped in
1043 CSSM_DATA pubKeyRaw
;
1045 bnToCssmData(openKey
->pub_key
, pubKeyRaw
, coder
);
1046 perr
= coder
.encodeItem(&pubKeyRaw
, kSecAsn1UnsignedIntegerTemplate
,
1047 nssPubKey
.publicKey
);
1049 logAsnErr("encodeItem(DSAPublicKeyX509.publicKey)", perr
);
1050 return CSSMERR_CSP_MEMORY_ERROR
;
1052 nssPubKey
.publicKey
.Length
*= 8;
1055 SecNssEncodeItemOdata(&nssPubKey
, kSecAsn1DSAPublicKeyX509Template
,
1061 return CSSMERR_CSP_MEMORY_ERROR
;
1066 * Encode public key portion only for calculating key digest.
1067 * Note this works just fine on a partial DSA public key, i.e.,
1068 * A DSA public key's digest-capable blob is the same whether or
1069 * not the DSA key has its DSA parameters p, q, and g.
1071 static CSSM_RETURN
DSAPublicKeyEncodeHashable(
1074 CssmOwnedData
&encodedKey
)
1078 * publicKey is the DER-encoding of an ASN integer
1081 bnToCssmData(openKey
->pub_key
, pubKey
, coder
);
1084 perr
= SecNssEncodeItemOdata(&pubKey
, kSecAsn1UnsignedIntegerTemplate
,
1087 logAsnErr("encode(DSAPubHashable)", perr
);
1088 return CSSMERR_CSP_MEMORY_ERROR
;
1094 return CSSMERR_CSP_MEMORY_ERROR
;
1099 * DSA private key, custom openssl format.
1101 static CSSM_RETURN
DSAPrivateKeyDecodeOpenssl(
1107 NSS_DSAPrivateKeyOpenssl nssPrivKey
;
1110 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1111 perr
= coder
.decode(p
, length
, kSecAsn1DSAPrivateKeyOpensslTemplate
,
1114 logAsnErr("decode(DSAPrivateKeyOpenssl)", perr
);
1115 return CSSMERR_CSP_INVALID_KEY
;
1118 /* convert nssPrivKey fields to RSA key fields */
1120 openKey
->version
= cssmDataToInt(nssPrivKey
.version
);
1121 openKey
->p
= cssmDataToBn(nssPrivKey
.p
);
1122 openKey
->q
= cssmDataToBn(nssPrivKey
.q
);
1123 openKey
->g
= cssmDataToBn(nssPrivKey
.g
);
1124 openKey
->pub_key
= cssmDataToBn(nssPrivKey
.pub
);
1125 openKey
->priv_key
= cssmDataToBn(nssPrivKey
.priv
);
1128 return CSSMERR_CSP_MEMORY_ERROR
;
1133 static CSSM_RETURN
DSAPrivateKeyEncodeOpenssl(
1136 CssmOwnedData
&encodedKey
)
1138 NSS_DSAPrivateKeyOpenssl nssPrivKey
;
1141 /* convert to NSS_DSAPrivateKeyOpenssl */
1143 intToCssmData(openKey
->version
, nssPrivKey
.version
, coder
);
1144 bnToCssmData(openKey
->p
, nssPrivKey
.p
, coder
);
1145 bnToCssmData(openKey
->q
, nssPrivKey
.q
, coder
);
1146 bnToCssmData(openKey
->g
, nssPrivKey
.g
, coder
);
1147 bnToCssmData(openKey
->pub_key
, nssPrivKey
.pub
, coder
);
1148 bnToCssmData(openKey
->priv_key
, nssPrivKey
.priv
, coder
);
1152 return CSSMERR_CSP_MEMORY_ERROR
;
1156 perr
= SecNssEncodeItemOdata(&nssPrivKey
, kSecAsn1DSAPrivateKeyOpensslTemplate
,
1159 logAsnErr("encode(DSAPrivateKeyOpenssl)", perr
);
1160 return CSSMERR_CSP_MEMORY_ERROR
;
1165 CSSM_RETURN
DSAPublicKeyDecode(
1167 CSSM_KEYBLOB_FORMAT format
,
1174 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186
:
1175 return DSAPublicKeyDecodeFIPS186(coder
, openKey
, p
, length
);
1176 case CSSM_KEYBLOB_RAW_FORMAT_X509
:
1177 return DSAPublicKeyDecodeX509(coder
, openKey
, p
, length
);
1178 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2
:
1179 return DSAPublicKeyDecodeOpenSSH2(openKey
, p
, length
);
1182 return CSSMERR_CSP_INTERNAL_ERROR
;
1186 CSSM_RETURN
DSAPublicKeyEncode(
1188 CSSM_KEYBLOB_FORMAT format
,
1189 const CssmData
&descData
,
1190 CssmOwnedData
&encodedKey
)
1195 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186
:
1196 return DSAPublicKeyEncodeFIPS186(coder
, openKey
, encodedKey
);
1197 case CSSM_KEYBLOB_RAW_FORMAT_X509
:
1198 return DSAPublicKeyEncodeX509(coder
, openKey
, encodedKey
);
1199 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST
:
1200 return DSAPublicKeyEncodeHashable(coder
, openKey
, encodedKey
);
1201 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2
:
1202 return DSAPublicKeyEncodeOpenSSH2(openKey
, descData
, encodedKey
);
1205 return CSSMERR_CSP_INTERNAL_ERROR
;
1209 CSSM_RETURN
DSAPrivateKeyDecode(
1211 CSSM_KEYBLOB_FORMAT format
,
1218 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186
:
1219 return DSAPrivateKeyDecodeFIPS186(coder
, openKey
, p
, (unsigned)length
);
1220 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
:
1221 return DSAPrivateKeyDecodeOpenssl(coder
, openKey
, p
, length
);
1222 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8
:
1223 return DSAPrivateKeyDecodePKCS8(coder
, openKey
, p
, (unsigned)length
);
1226 return CSSMERR_CSP_INTERNAL_ERROR
;
1230 CSSM_RETURN
DSAPrivateKeyEncode(
1232 CSSM_KEYBLOB_FORMAT format
,
1233 const CssmData
&descData
,
1234 CssmOwnedData
&encodedKey
)
1239 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186
:
1240 return DSAPrivateKeyEncodeFIPS186(coder
, openKey
, encodedKey
);
1241 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
:
1242 return DSAPrivateKeyEncodeOpenssl(coder
, openKey
, encodedKey
);
1243 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8
:
1244 return DSAPrivateKeyEncodePKCS8(coder
, openKey
, encodedKey
);
1247 return CSSMERR_CSP_INTERNAL_ERROR
;
1252 #pragma mark *** DSA Signature encode/decode ***
1254 CSSM_RETURN
DSASigEncode(
1256 CssmOwnedData
&encodedSig
)
1258 /* temp allocs from this pool */
1260 /* convert to NSS_DSASignature */
1261 NSS_DSASignature nssSig
;
1264 bnToCssmData(openSig
->r
, nssSig
.r
, coder
);
1265 bnToCssmData(openSig
->s
, nssSig
.s
, coder
);
1269 return CSSMERR_CSP_MEMORY_ERROR
;
1272 PRErrorCode prtn
= SecNssEncodeItemOdata(&nssSig
,
1273 kSecAsn1DSASignatureTemplate
, encodedSig
);
1275 return CSSMERR_CSP_MEMORY_ERROR
;
1280 CSSM_RETURN
DSASigDecode(
1285 NSS_DSASignature nssSig
;
1288 memset(&nssSig
, 0, sizeof(nssSig
));
1289 PRErrorCode perr
= coder
.decode(p
, length
,
1290 kSecAsn1DSASignatureTemplate
, &nssSig
);
1292 logAsnErr("decode(DSASigDecode)", perr
);
1293 return CSSMERR_CSP_INVALID_SIGNATURE
;
1297 openSig
->r
= cssmDataToBn(nssSig
.r
);
1298 openSig
->s
= cssmDataToBn(nssSig
.s
);
1301 return CSSMERR_CSP_MEMORY_ERROR
;
1307 #pragma mark *** DSA Algorithm Parameters encode/decode ***
1309 CSSM_RETURN
DSAEncodeAlgParams(
1310 NSS_DSAAlgParams
&algParams
,
1311 CssmOwnedData
&encodedParams
)
1313 PRErrorCode prtn
= SecNssEncodeItemOdata(&algParams
,
1314 kSecAsn1DSAAlgParamsTemplate
, encodedParams
);
1316 return CSSMERR_CSP_MEMORY_ERROR
;
1321 CSSM_RETURN
DSADecodeAlgParams(
1322 NSS_DSAAlgParams
&algParams
,
1328 memset(&algParams
, 0, sizeof(algParams
));
1329 PRErrorCode perr
= coder
.decode(p
, len
,
1330 kSecAsn1DSAAlgParamsTemplate
, &algParams
);
1332 logAsnErr("decode(DSAAlgParams)", perr
);
1333 return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS
;
1339 #pragma mark *** Diffie-Hellman key encode/decode ***
1341 CSSM_RETURN
DHPrivateKeyDecodePKCS3(
1347 NSS_DHPrivateKey nssPrivKey
;
1350 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1351 perr
= coder
.decode(p
, length
, kSecAsn1DHPrivateKeyTemplate
, &nssPrivKey
);
1353 logAsnErr("decode(DHPrivateKey)", perr
);
1354 return CSSMERR_CSP_INVALID_KEY
;
1357 /* verify alg identifier */
1358 const CSSM_OID
*oid
= &nssPrivKey
.dhOid
;
1359 if(!cspCompareCssmData(oid
, &CSSMOID_DH
)) {
1360 sslAsn1Debug("DHPrivateKeyDecode: bad OID");
1361 return CSSMERR_CSP_ALGID_MISMATCH
;
1364 NSS_DHParameter
¶ms
= nssPrivKey
.params
;
1367 openKey
->priv_key
= cssmDataToBn(nssPrivKey
.secretPart
);
1368 openKey
->p
= cssmDataToBn(params
.prime
);
1369 openKey
->g
= cssmDataToBn(params
.base
);
1370 /* TBD - ignore privateValueLength for now */
1373 /* FIXME - bad sig? memory? */
1374 return CSSMERR_CSP_MEMORY_ERROR
;
1380 CSSM_RETURN
DHPrivateKeyEncodePKCS3(
1383 CssmOwnedData
&encodedKey
)
1385 /* convert into a NSS_DHPrivateKey */
1386 NSS_DHPrivateKey nssPrivKey
;
1387 NSS_DHParameter
¶ms
= nssPrivKey
.params
;
1388 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1389 nssPrivKey
.dhOid
= CSSMOID_DH
;
1393 bnToCssmData(openKey
->priv_key
, nssPrivKey
.secretPart
, coder
);
1394 bnToCssmData(openKey
->p
, params
.prime
, coder
);
1395 bnToCssmData(openKey
->g
, params
.base
, coder
);
1396 if(openKey
->length
) {
1397 /* actually currently not supported in openssl... */
1398 intToCssmData(openKey
->length
, params
.privateValueLength
, coder
);
1402 return CSSMERR_CSP_MEMORY_ERROR
;
1407 perr
= SecNssEncodeItemOdata(&nssPrivKey
, kSecAsn1DHPrivateKeyTemplate
,
1410 logAsnErr("encode(DHPrivateKey)", perr
);
1411 return CSSMERR_CSP_MEMORY_ERROR
;
1417 * NSS_DHAlgorithmIdentifierX942 <--> DH
1418 * NOTE this is incomplete. It's functional on decode, but we throw
1419 * away everything except p and g. On encode, we put zeroes in
1420 * all the fields we don't deal with. Thus the encode side will NOT be
1421 * interoperable with other implementations.
1423 static void dhToNssAlgIdX942(
1425 NSS_DHAlgorithmIdentifierX942
&algId
,
1429 * When trying to encode a public key in X509 form, we may in
1430 * fact have nothing here - public keys created and exported in
1431 * PKCS3 have the pub_key value, and that's it.
1434 memset(&algId
, 0, sizeof(algId
));
1435 algId
.oid
= CSSMOID_ANSI_DH_PUB_NUMBER
; // not mallocd
1436 NSS_DHDomainParamsX942
¶ms
= algId
.params
;
1438 CSSM_DATA czero
= {1, &zero
};
1439 if(openKey
->p
!= NULL
) {
1440 bnToCssmData(openKey
->p
, params
.p
, coder
);
1443 coder
.allocCopyItem(czero
, params
.p
);
1445 if(openKey
->g
!= NULL
) {
1446 bnToCssmData(openKey
->g
, params
.g
, coder
);
1449 coder
.allocCopyItem(czero
, params
.g
);
1451 /* and we never have a vali0d q */
1452 coder
.allocCopyItem(czero
, params
.q
);
1456 static CSSM_RETURN
nssAlgIdToDhX942(
1457 NSS_DHAlgorithmIdentifierX942
&algId
,
1460 if(!cspCompareCssmData(&algId
.oid
, &CSSMOID_ANSI_DH_PUB_NUMBER
)) {
1461 sslAsn1Debug("nssAlgIdToDhX942: bad OID");
1462 return CSSMERR_CSP_INVALID_KEY
;
1464 openKey
->p
= cssmDataToBn(algId
.params
.p
);
1465 openKey
->g
= cssmDataToBn(algId
.params
.g
);
1470 CSSM_RETURN
DHPrivateKeyDecodePKCS8(
1476 NSS_DHPrivateKeyPKCS8 nssPrivKey
;
1479 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1480 perr
= coder
.decode(p
, length
, kSecAsn1DHPrivateKeyPKCS8Template
,
1483 logAsnErr("decode(DHPrivateKeyPKCS8)", perr
);
1484 return CSSMERR_CSP_INVALID_KEY
;
1488 CSSM_RETURN crtn
= nssAlgIdToDhX942(nssPrivKey
.algorithm
, openKey
);
1493 /* post-decode private key is a DER encoded integer */
1494 CSSM_DATA privKeyInt
= {0, NULL
};
1495 if(coder
.decodeItem(nssPrivKey
.privateKey
,
1496 kSecAsn1UnsignedIntegerTemplate
,
1498 logAsnErr("decode(DHPrivateKeyPKCS8 privKey int)", perr
);
1499 return CSSMERR_CSP_INVALID_KEY
;
1502 openKey
->priv_key
= cssmDataToBn(privKeyInt
);
1505 /* FIXME - bad sig? memory? */
1506 return CSSMERR_CSP_MEMORY_ERROR
;
1512 CSSM_RETURN
DHPrivateKeyEncodePKCS8(
1515 CssmOwnedData
&encodedKey
)
1517 /* convert into a NSS_DHPrivateKeyPKCS8 */
1518 NSS_DHPrivateKeyPKCS8 nssPrivKey
;
1519 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1521 nssPrivKey
.version
.Length
= 1;
1522 nssPrivKey
.version
.Data
= &vers
;
1523 NSS_DHAlgorithmIdentifierX942
&alg
= nssPrivKey
.algorithm
;
1527 dhToNssAlgIdX942(openKey
, alg
, coder
);
1528 /* pre-encode, nssPrivKey.privateKey is the DER-encoding of
1529 * an ASN integer... */
1530 CSSM_DATA privKeyInt
;
1531 bnToCssmData(openKey
->priv_key
, privKeyInt
, coder
);
1533 /* DER encode the privateKey portion into arena pool memory
1534 * into nssPrivKey.privateKey */
1535 coder
.encodeItem(&privKeyInt
, kSecAsn1UnsignedIntegerTemplate
,
1536 nssPrivKey
.privateKey
);
1539 return CSSMERR_CSP_MEMORY_ERROR
;
1544 perr
= SecNssEncodeItemOdata(&nssPrivKey
, kSecAsn1DHPrivateKeyPKCS8Template
,
1547 logAsnErr("encode(DHPrivateKey)", perr
);
1548 return CSSMERR_CSP_MEMORY_ERROR
;
1554 * In the PKCS3 form, the public blob is simply the literal
1555 * public key value, not DER encoded.
1557 static CSSM_RETURN
DHPublicKeyDecodePKCS3(
1564 CSSM_DATA pubKey
= {(uint32
)length
, (uint8
*)p
};
1565 openKey
->pub_key
= cssmDataToBn(pubKey
);
1569 return CSSMERR_CSP_MEMORY_ERROR
;
1573 static CSSM_RETURN
DHPublicKeyEncodePKCS3(
1576 CssmOwnedData
&encodedKey
)
1580 bnToCssmData(openKey
->pub_key
, pubKey
, coder
);
1581 encodedKey
.copy(CssmData::overlay(pubKey
));
1585 return CSSMERR_CSP_MEMORY_ERROR
;
1589 static CSSM_RETURN
DHPublicKeyDecodeX509(
1595 NSS_DHPublicKeyX509 nssPubKey
;
1598 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
1599 perr
= coder
.decode(p
, length
, kSecAsn1DHPublicKeyX509Template
,
1602 logAsnErr("decode(DHPublicKeyX509)", perr
);
1603 return CSSMERR_CSP_INVALID_KEY
;
1607 CSSM_RETURN crtn
= nssAlgIdToDhX942(nssPubKey
.algorithm
, openKey
);
1613 * Post-decode public key length in bits
1614 * Contents are pub_key as DER-encoded INTEGER
1616 CSSM_DATA
&pubKey
= nssPubKey
.publicKey
;
1617 pubKey
.Length
= (pubKey
.Length
+ 7) / 8;
1618 CSSM_DATA pubKeyInt
= {0, NULL
};
1619 if(coder
.decodeItem(pubKey
,
1620 kSecAsn1UnsignedIntegerTemplate
, &pubKeyInt
)) {
1621 logAsnErr("decode(DHPublicKeyX509 pub key int)", perr
);
1622 return CSSMERR_CSP_INVALID_KEY
;
1624 openKey
->pub_key
= cssmDataToBn(pubKeyInt
);
1627 /* FIXME - bad sig? memory? */
1628 return CSSMERR_CSP_MEMORY_ERROR
;
1633 static CSSM_RETURN
DHPublicKeyEncodeX509(
1636 CssmOwnedData
&encodedKey
)
1638 /* convert into a NSS_DHPublicKeyX509 */
1639 NSS_DHPublicKeyX509 nssPubKey
;
1640 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
1641 NSS_DHAlgorithmIdentifierX942
&alg
= nssPubKey
.algorithm
;
1644 dhToNssAlgIdX942(openKey
, alg
, coder
);
1646 /* encode pub_key as integer */
1647 CSSM_DATA pubKeyInt
= {0, NULL
};
1648 bnToCssmData(openKey
->pub_key
, pubKeyInt
, coder
);
1649 coder
.encodeItem(&pubKeyInt
, kSecAsn1UnsignedIntegerTemplate
,
1650 nssPubKey
.publicKey
);
1651 /* specify length in bits */
1652 nssPubKey
.publicKey
.Length
*= 8;
1655 return CSSMERR_CSP_MEMORY_ERROR
;
1660 perr
= SecNssEncodeItemOdata(&nssPubKey
, kSecAsn1DHPublicKeyX509Template
,
1663 logAsnErr("encode(DHPublicKeyX509)", perr
);
1664 return CSSMERR_CSP_MEMORY_ERROR
;
1669 CSSM_RETURN
DHPrivateKeyDecode(
1671 CSSM_KEYBLOB_FORMAT format
,
1678 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3
:
1679 return DHPrivateKeyDecodePKCS3(coder
, openKey
, p
, length
);
1680 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8
:
1681 return DHPrivateKeyDecodePKCS8(coder
, openKey
, p
, length
);
1684 return CSSMERR_CSP_INTERNAL_ERROR
;
1688 CSSM_RETURN
DHPrivateKeyEncode(
1690 CSSM_KEYBLOB_FORMAT format
,
1691 CssmOwnedData
&encodedKey
)
1696 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3
:
1697 return DHPrivateKeyEncodePKCS3(coder
, openKey
, encodedKey
);
1698 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8
:
1699 return DHPrivateKeyEncodePKCS8(coder
, openKey
, encodedKey
);
1702 return CSSMERR_CSP_INTERNAL_ERROR
;
1706 CSSM_RETURN
DHPublicKeyDecode(
1708 CSSM_KEYBLOB_FORMAT format
,
1715 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3
:
1716 return DHPublicKeyDecodePKCS3(openKey
, coder
, p
, length
);
1717 case CSSM_KEYBLOB_RAW_FORMAT_X509
:
1718 return DHPublicKeyDecodeX509(openKey
, coder
, p
, length
);
1721 return CSSMERR_CSP_INTERNAL_ERROR
;
1725 CSSM_RETURN
DHPublicKeyEncode(
1727 CSSM_KEYBLOB_FORMAT format
,
1728 CssmOwnedData
&encodedKey
)
1733 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3
:
1734 return DHPublicKeyEncodePKCS3(openKey
, coder
, encodedKey
);
1735 case CSSM_KEYBLOB_RAW_FORMAT_X509
:
1736 return DHPublicKeyEncodeX509(openKey
, coder
, encodedKey
);
1739 return CSSMERR_CSP_INTERNAL_ERROR
;
1744 * Encode/decode a NSS_DHParameterBlock.
1746 CSSM_RETURN
DHParamBlockDecode(
1747 const CSSM_DATA
&encParam
,
1748 NSS_DHParameterBlock
¶mBlock
,
1753 memset(¶mBlock
, 0, sizeof(paramBlock
));
1754 perr
= coder
.decodeItem(encParam
, kSecAsn1DHParameterBlockTemplate
,
1761 * CDSA Extension: the CDSA Algorithm Guide says that the D-H
1762 * parameter block is supposed to be wrapped with its accompanying
1763 * OID. However Openssl does not do this; it just exports
1764 * an encoded DHParameter rather than a DHParameterBlock.
1765 * For compatibility we'll try decoding the parameters as one
1768 memset(¶mBlock
, 0, sizeof(paramBlock
));
1769 perr
= coder
.decodeItem(encParam
, kSecAsn1DHParameterTemplate
,
1770 ¶mBlock
.params
);
1774 return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS
;
1778 #pragma mark *** Message Digest ***
1781 * Given a message digest and associated algorithm, cook up a PKCS1-style
1782 * DigestInfo and return its DER encoding. This is a necessary step for
1783 * RSA signature (both generating and verifying) - the output of this
1784 * routine is what gets encrypted during signing, and what is expected when
1785 * verifying (i.e., decrypting the signature).
1787 * A good guess for the length of the output digestInfo is the size of the
1788 * key being used to sign/verify. The digest can never be larger than that.
1790 CSSM_RETURN
generateDigestInfo(
1791 const void *msgDigest
,
1793 CSSM_ALGORITHMS digestAlg
, // CSSM_ALGID_SHA1, etc.
1794 CssmOwnedData
&encodedInfo
,
1795 size_t maxEncodedSize
)
1797 if(digestAlg
== CSSM_ALGID_NONE
) {
1798 /* special case, no encode, just copy */
1799 encodedInfo
.copy(msgDigest
, digestLen
);
1803 NSS_DigestInfo digestInfo
;
1804 CSSM_X509_ALGORITHM_IDENTIFIER
&algId
= digestInfo
.digestAlgorithm
;
1806 memset(&digestInfo
, 0, sizeof(digestInfo
));
1808 case CSSM_ALGID_MD5
:
1809 algId
.algorithm
= CSSMOID_MD5
;
1811 case CSSM_ALGID_MD2
:
1812 algId
.algorithm
= CSSMOID_MD2
;
1814 case CSSM_ALGID_SHA1
:
1815 algId
.algorithm
= CSSMOID_SHA1
;
1817 case CSSM_ALGID_SHA224
:
1818 algId
.algorithm
= CSSMOID_SHA224
;
1820 case CSSM_ALGID_SHA256
:
1821 algId
.algorithm
= CSSMOID_SHA256
;
1823 case CSSM_ALGID_SHA384
:
1824 algId
.algorithm
= CSSMOID_SHA384
;
1826 case CSSM_ALGID_SHA512
:
1827 algId
.algorithm
= CSSMOID_SHA512
;
1830 return CSSMERR_CSP_INVALID_ALGORITHM
;
1832 nullAlgParams(algId
);
1833 digestInfo
.digest
.Data
= (uint8
*)msgDigest
;
1834 digestInfo
.digest
.Length
= digestLen
;
1838 perr
= SecNssEncodeItemOdata(&digestInfo
, kSecAsn1DigestInfoTemplate
,
1841 logAsnErr("encode(digestInfo)", perr
);
1842 return CSSMERR_CSP_MEMORY_ERROR
;