2 * Copyright (c) 2003 Apple Computer, 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/err.h>
28 #include <openssl/bn.h>
29 #include <openssl/crypto.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>
40 #define sslAsn1Debug(args...) secdebug("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
, 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 uint32 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 uint32 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
, 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
, 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.
721 CSSM_RETURN
DSAPublicKeyDecodeFIPS186(
727 NSS_DSAPublicKeyBSAFE nssPubKey
;
731 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
732 perr
= coder
.decode(p
, length
, kSecAsn1DSAPublicKeyBSAFETemplate
,
735 logAsnErr("decode(DSAPublicKeyBSAFE)", perr
);
736 return CSSMERR_CSP_INVALID_KEY
;
739 /* BSAFE style DSA-specific alg params */
740 NSS_DSAAlgorithmIdBSAFE
&algId
= nssPubKey
.dsaAlg
;
741 crtn
= nssAlgIdToDsaBSAFE(algId
, openKey
);
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
,
754 logAsnErr("decode(NSS_DSAPublicKeyBSAFE.publicKey)", perr
);
755 return CSSMERR_CSP_INVALID_KEY
;
757 openKey
->pub_key
= cssmDataToBn(pubKeyBytes
);
759 if(openKey
->pub_key
== NULL
) {
760 return CSSMERR_CSP_INVALID_KEY
;
765 CSSM_RETURN
DSAPublicKeyEncodeFIPS186(
768 CssmOwnedData
&encodedKey
)
771 /* convert to NSS_DSAPublicKeyBSAFE */
772 NSS_DSAPublicKeyBSAFE nssPubKey
;
773 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
774 dsaToNssAlgIdBSAFE(openKey
, nssPubKey
.dsaAlg
, coder
);
777 * publicKey is the DER-encoding of a ASN INTEGER wrapped in
782 bnToCssmData(openKey
->pub_key
, pubKeyRaw
, coder
);
783 perr
= coder
.encodeItem(&pubKeyRaw
, kSecAsn1UnsignedIntegerTemplate
,
784 nssPubKey
.publicKey
);
786 logAsnErr("encodeItem(DSAPublicKeyBSAFE.publicKey)", perr
);
787 return CSSMERR_CSP_MEMORY_ERROR
;
789 nssPubKey
.publicKey
.Length
*= 8;
792 SecNssEncodeItemOdata(&nssPubKey
, kSecAsn1DSAPublicKeyBSAFETemplate
,
798 return CSSMERR_CSP_MEMORY_ERROR
;
803 * DSA private keys, FIPS186 format.
804 * Compatible with BSAFE.
806 CSSM_RETURN
DSAPrivateKeyDecodeFIPS186(
812 NSS_DSAPrivateKeyBSAFE nssPrivKeyInfo
;
815 memset(&nssPrivKeyInfo
, 0, sizeof(nssPrivKeyInfo
));
816 perr
= coder
.decode(p
, length
, kSecAsn1DSAPrivateKeyBSAFETemplate
,
819 logAsnErr("decode(DSA PrivateKeyInfo)", perr
);
820 return CSSMERR_CSP_INVALID_KEY
;
823 CSSM_RETURN crtn
= nssAlgIdToDsaBSAFE(nssPrivKeyInfo
.dsaAlg
, openKey
);
828 /* nssPrivKeyInfo.privateKey is the DER-encoding of a
829 * DSAPrivateKeyOcts... */
832 NSS_DSAPrivateKeyOcts keyOcts
;
834 perr
= coder
.decodeItem(nssPrivKeyInfo
.privateKey
,
835 kSecAsn1DSAPrivateKeyOctsTemplate
, &keyOcts
);
837 logAsnErr("decode(DSA PrivateKeyInfoOcts)", perr
);
838 return CSSMERR_CSP_INVALID_KEY
;
841 openKey
->priv_key
= cssmDataToBn(keyOcts
.privateKey
);
842 if(openKey
->priv_key
== NULL
) {
843 return CSSMERR_CSP_INVALID_KEY
;
848 return CSSMERR_CSP_INVALID_KEY
;
852 CSSM_RETURN
DSAPrivateKeyEncodeFIPS186(
855 CssmOwnedData
&encodedKey
)
858 /* First convert into a NSS_DSAPrivateKeyBSAFE */
859 NSS_DSAPrivateKeyBSAFE nssPrivKey
;
860 intToCssmData(openKey
->version
, nssPrivKey
.version
, coder
);
861 dsaToNssAlgIdBSAFE(openKey
, nssPrivKey
.dsaAlg
, coder
);
863 /* nssPrivKey.privateKey is the DER-encoding of one of these... */
864 NSS_DSAPrivateKeyOcts privKeyOcts
;
865 bnToCssmData(openKey
->priv_key
, privKeyOcts
.privateKey
, coder
);
867 /* DER encode the privateKey portion into arena pool memory
868 * into NSS_DSAPrivateKeyPKCS8.privateKey */
869 coder
.encodeItem(&privKeyOcts
, kSecAsn1DSAPrivateKeyOctsTemplate
,
870 nssPrivKey
.privateKey
);
872 /* DER encode the whole thing */
874 perr
= SecNssEncodeItemOdata(&nssPrivKey
,
875 kSecAsn1DSAPrivateKeyBSAFETemplate
, encodedKey
);
880 return CSSMERR_CSP_MEMORY_ERROR
;
885 * DSA private keys, PKCS8/SMIME format.
887 CSSM_RETURN
DSAPrivateKeyDecodePKCS8(
893 NSS_DSAPrivateKeyPKCS8 nssPrivKeyInfo
;
896 memset(&nssPrivKeyInfo
, 0, sizeof(nssPrivKeyInfo
));
897 perr
= coder
.decode(p
, length
, kSecAsn1DSAPrivateKeyPKCS8Template
,
900 logAsnErr("decode(DSA NSS_DSAPrivateKeyPKCS8)", perr
);
901 return CSSMERR_CSP_INVALID_KEY
;
904 CSSM_RETURN crtn
= nssAlgIdToDsaX509(nssPrivKeyInfo
.dsaAlg
, openKey
);
910 * Post-decode, nssPrivKeyInfo.privateKey is the DER-encoding of a
915 CSSM_DATA privKeyInt
= {0, NULL
};
917 perr
= coder
.decodeItem(nssPrivKeyInfo
.privateKey
,
918 kSecAsn1UnsignedIntegerTemplate
, &privKeyInt
);
920 logAsnErr("decode(DSA nssPrivKeyInfo.privateKey)", perr
);
921 return CSSMERR_CSP_INVALID_KEY
;
924 openKey
->priv_key
= cssmDataToBn(privKeyInt
);
925 if(openKey
->priv_key
== NULL
) {
926 return CSSMERR_CSP_INVALID_KEY
;
931 return CSSMERR_CSP_INVALID_KEY
;
935 CSSM_RETURN
DSAPrivateKeyEncodePKCS8(
938 CssmOwnedData
&encodedKey
)
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
);
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
);
955 /* DER encode the privateKey portion into arena pool memory
956 * into NSS_DSAPrivateKeyPKCS8.privateKey */
957 coder
.encodeItem(&privKeyInt
, kSecAsn1UnsignedIntegerTemplate
,
958 nssPrivKey
.privateKey
);
960 /* DER encode the whole thing */
962 perr
= SecNssEncodeItemOdata(&nssPrivKey
,
963 kSecAsn1DSAPrivateKeyPKCS8Template
, encodedKey
);
968 return CSSMERR_CSP_MEMORY_ERROR
;
973 * DSA public key, X509/openssl format.
975 static CSSM_RETURN
DSAPublicKeyDecodeX509(
981 NSS_DSAPublicKeyX509 nssPubKey
;
985 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
986 perr
= coder
.decode(p
, length
, kSecAsn1DSAPublicKeyX509Template
,
989 logAsnErr("decode(DSAPublicKeyX509)", perr
);
990 return CSSMERR_CSP_INVALID_KEY
;
993 /* X509 style DSA-specific alg params */
994 NSS_DSAAlgorithmIdX509
&algId
= nssPubKey
.dsaAlg
;
995 crtn
= nssAlgIdToDsaX509(algId
, openKey
);
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
,
1008 logAsnErr("decode(NSS_DSAPublicKeyX509.publicKey)", perr
);
1009 return CSSMERR_CSP_INVALID_KEY
;
1011 openKey
->pub_key
= cssmDataToBn(pubKeyBytes
);
1013 if(openKey
->pub_key
== NULL
) {
1014 return CSSMERR_CSP_INVALID_KEY
;
1019 static CSSM_RETURN
DSAPublicKeyEncodeX509(
1022 CssmOwnedData
&encodedKey
)
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
);
1034 * publicKey is the DER-encoding of a ASN INTEGER wrapped in
1037 CSSM_DATA pubKeyRaw
;
1039 bnToCssmData(openKey
->pub_key
, pubKeyRaw
, coder
);
1040 perr
= coder
.encodeItem(&pubKeyRaw
, kSecAsn1UnsignedIntegerTemplate
,
1041 nssPubKey
.publicKey
);
1043 logAsnErr("encodeItem(DSAPublicKeyX509.publicKey)", perr
);
1044 return CSSMERR_CSP_MEMORY_ERROR
;
1046 nssPubKey
.publicKey
.Length
*= 8;
1049 SecNssEncodeItemOdata(&nssPubKey
, kSecAsn1DSAPublicKeyX509Template
,
1055 return CSSMERR_CSP_MEMORY_ERROR
;
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.
1065 static CSSM_RETURN
DSAPublicKeyEncodeHashable(
1068 CssmOwnedData
&encodedKey
)
1072 * publicKey is the DER-encoding of an ASN integer
1075 bnToCssmData(openKey
->pub_key
, pubKey
, coder
);
1078 perr
= SecNssEncodeItemOdata(&pubKey
, kSecAsn1UnsignedIntegerTemplate
,
1081 logAsnErr("encode(DSAPubHashable)", perr
);
1082 return CSSMERR_CSP_MEMORY_ERROR
;
1088 return CSSMERR_CSP_MEMORY_ERROR
;
1093 * DSA private key, custom openssl format.
1095 static CSSM_RETURN
DSAPrivateKeyDecodeOpenssl(
1101 NSS_DSAPrivateKeyOpenssl nssPrivKey
;
1104 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1105 perr
= coder
.decode(p
, length
, kSecAsn1DSAPrivateKeyOpensslTemplate
,
1108 logAsnErr("decode(DSAPrivateKeyOpenssl)", perr
);
1109 return CSSMERR_CSP_INVALID_KEY
;
1112 /* convert nssPrivKey fields to RSA key fields */
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
);
1122 return CSSMERR_CSP_MEMORY_ERROR
;
1127 static CSSM_RETURN
DSAPrivateKeyEncodeOpenssl(
1130 CssmOwnedData
&encodedKey
)
1132 NSS_DSAPrivateKeyOpenssl nssPrivKey
;
1135 /* convert to NSS_DSAPrivateKeyOpenssl */
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
);
1146 return CSSMERR_CSP_MEMORY_ERROR
;
1150 perr
= SecNssEncodeItemOdata(&nssPrivKey
, kSecAsn1DSAPrivateKeyOpensslTemplate
,
1153 logAsnErr("encode(DSAPrivateKeyOpenssl)", perr
);
1154 return CSSMERR_CSP_MEMORY_ERROR
;
1159 CSSM_RETURN
DSAPublicKeyDecode(
1161 CSSM_KEYBLOB_FORMAT 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
);
1176 return CSSMERR_CSP_INTERNAL_ERROR
;
1180 CSSM_RETURN
DSAPublicKeyEncode(
1182 CSSM_KEYBLOB_FORMAT format
,
1183 const CssmData
&descData
,
1184 CssmOwnedData
&encodedKey
)
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
);
1199 return CSSMERR_CSP_INTERNAL_ERROR
;
1203 CSSM_RETURN
DSAPrivateKeyDecode(
1205 CSSM_KEYBLOB_FORMAT 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
);
1220 return CSSMERR_CSP_INTERNAL_ERROR
;
1224 CSSM_RETURN
DSAPrivateKeyEncode(
1226 CSSM_KEYBLOB_FORMAT format
,
1227 const CssmData
&descData
,
1228 CssmOwnedData
&encodedKey
)
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
);
1241 return CSSMERR_CSP_INTERNAL_ERROR
;
1246 #pragma mark *** DSA Signature encode/decode ***
1248 CSSM_RETURN
DSASigEncode(
1250 CssmOwnedData
&encodedSig
)
1252 /* temp allocs from this pool */
1254 /* convert to NSS_DSASignature */
1255 NSS_DSASignature nssSig
;
1258 bnToCssmData(openSig
->r
, nssSig
.r
, coder
);
1259 bnToCssmData(openSig
->s
, nssSig
.s
, coder
);
1263 return CSSMERR_CSP_MEMORY_ERROR
;
1266 PRErrorCode prtn
= SecNssEncodeItemOdata(&nssSig
,
1267 kSecAsn1DSASignatureTemplate
, encodedSig
);
1269 return CSSMERR_CSP_MEMORY_ERROR
;
1274 CSSM_RETURN
DSASigDecode(
1279 NSS_DSASignature nssSig
;
1282 memset(&nssSig
, 0, sizeof(nssSig
));
1283 PRErrorCode perr
= coder
.decode(p
, length
,
1284 kSecAsn1DSASignatureTemplate
, &nssSig
);
1286 logAsnErr("decode(DSASigDecode)", perr
);
1287 return CSSMERR_CSP_INVALID_SIGNATURE
;
1291 openSig
->r
= cssmDataToBn(nssSig
.r
);
1292 openSig
->s
= cssmDataToBn(nssSig
.s
);
1295 return CSSMERR_CSP_MEMORY_ERROR
;
1301 #pragma mark *** DSA Algorithm Parameters encode/decode ***
1303 CSSM_RETURN
DSAEncodeAlgParams(
1304 NSS_DSAAlgParams
&algParams
,
1305 CssmOwnedData
&encodedParams
)
1307 PRErrorCode prtn
= SecNssEncodeItemOdata(&algParams
,
1308 kSecAsn1DSAAlgParamsTemplate
, encodedParams
);
1310 return CSSMERR_CSP_MEMORY_ERROR
;
1315 CSSM_RETURN
DSADecodeAlgParams(
1316 NSS_DSAAlgParams
&algParams
,
1322 memset(&algParams
, 0, sizeof(algParams
));
1323 PRErrorCode perr
= coder
.decode(p
, len
,
1324 kSecAsn1DSAAlgParamsTemplate
, &algParams
);
1326 logAsnErr("decode(DSAAlgParams)", perr
);
1327 return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS
;
1333 #pragma mark *** Diffie-Hellman key encode/decode ***
1335 CSSM_RETURN
DHPrivateKeyDecodePKCS3(
1341 NSS_DHPrivateKey nssPrivKey
;
1344 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1345 perr
= coder
.decode(p
, length
, kSecAsn1DHPrivateKeyTemplate
, &nssPrivKey
);
1347 logAsnErr("decode(DHPrivateKey)", perr
);
1348 return CSSMERR_CSP_INVALID_KEY
;
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
;
1358 NSS_DHParameter
¶ms
= nssPrivKey
.params
;
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 */
1367 /* FIXME - bad sig? memory? */
1368 return CSSMERR_CSP_MEMORY_ERROR
;
1373 CSSM_RETURN
DHPrivateKeyEncodePKCS3(
1376 CssmOwnedData
&encodedKey
)
1378 /* convert into a NSS_DHPrivateKey */
1379 NSS_DHPrivateKey nssPrivKey
;
1380 NSS_DHParameter
¶ms
= nssPrivKey
.params
;
1381 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1382 nssPrivKey
.dhOid
= CSSMOID_DH
;
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
);
1395 return CSSMERR_CSP_MEMORY_ERROR
;
1400 perr
= SecNssEncodeItemOdata(&nssPrivKey
, kSecAsn1DHPrivateKeyTemplate
,
1403 logAsnErr("encode(DHPrivateKey)", perr
);
1404 return CSSMERR_CSP_MEMORY_ERROR
;
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.
1416 static void dhToNssAlgIdX942(
1418 NSS_DHAlgorithmIdentifierX942
&algId
,
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.
1427 memset(&algId
, 0, sizeof(algId
));
1428 algId
.oid
= CSSMOID_ANSI_DH_PUB_NUMBER
; // not mallocd
1429 NSS_DHDomainParamsX942
¶ms
= algId
.params
;
1431 CSSM_DATA czero
= {1, &zero
};
1432 if(openKey
->p
!= NULL
) {
1433 bnToCssmData(openKey
->p
, params
.p
, coder
);
1436 coder
.allocCopyItem(czero
, params
.p
);
1438 if(openKey
->g
!= NULL
) {
1439 bnToCssmData(openKey
->g
, params
.g
, coder
);
1442 coder
.allocCopyItem(czero
, params
.g
);
1444 /* and we never have a vali0d q */
1445 coder
.allocCopyItem(czero
, params
.q
);
1449 static CSSM_RETURN
nssAlgIdToDhX942(
1450 NSS_DHAlgorithmIdentifierX942
&algId
,
1453 if(!cspCompareCssmData(&algId
.oid
, &CSSMOID_ANSI_DH_PUB_NUMBER
)) {
1454 sslAsn1Debug("nssAlgIdToDhX942: bad OID");
1455 return CSSMERR_CSP_INVALID_KEY
;
1457 openKey
->p
= cssmDataToBn(algId
.params
.p
);
1458 openKey
->g
= cssmDataToBn(algId
.params
.g
);
1462 CSSM_RETURN
DHPrivateKeyDecodePKCS8(
1468 NSS_DHPrivateKeyPKCS8 nssPrivKey
;
1471 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1472 perr
= coder
.decode(p
, length
, kSecAsn1DHPrivateKeyPKCS8Template
,
1475 logAsnErr("decode(DHPrivateKeyPKCS8)", perr
);
1476 return CSSMERR_CSP_INVALID_KEY
;
1480 CSSM_RETURN crtn
= nssAlgIdToDhX942(nssPrivKey
.algorithm
, openKey
);
1485 /* post-decode private key is a DER encoded integer */
1486 CSSM_DATA privKeyInt
= {0, NULL
};
1487 if(coder
.decodeItem(nssPrivKey
.privateKey
,
1488 kSecAsn1UnsignedIntegerTemplate
,
1490 logAsnErr("decode(DHPrivateKeyPKCS8 privKey int)", perr
);
1491 return CSSMERR_CSP_INVALID_KEY
;
1494 openKey
->priv_key
= cssmDataToBn(privKeyInt
);
1497 /* FIXME - bad sig? memory? */
1498 return CSSMERR_CSP_MEMORY_ERROR
;
1503 CSSM_RETURN
DHPrivateKeyEncodePKCS8(
1506 CssmOwnedData
&encodedKey
)
1508 /* convert into a NSS_DHPrivateKeyPKCS8 */
1509 NSS_DHPrivateKeyPKCS8 nssPrivKey
;
1510 memset(&nssPrivKey
, 0, sizeof(nssPrivKey
));
1512 nssPrivKey
.version
.Length
= 1;
1513 nssPrivKey
.version
.Data
= &vers
;
1514 NSS_DHAlgorithmIdentifierX942
&alg
= nssPrivKey
.algorithm
;
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
);
1524 /* DER encode the privateKey portion into arena pool memory
1525 * into nssPrivKey.privateKey */
1526 coder
.encodeItem(&privKeyInt
, kSecAsn1UnsignedIntegerTemplate
,
1527 nssPrivKey
.privateKey
);
1530 return CSSMERR_CSP_MEMORY_ERROR
;
1535 perr
= SecNssEncodeItemOdata(&nssPrivKey
, kSecAsn1DHPrivateKeyPKCS8Template
,
1538 logAsnErr("encode(DHPrivateKey)", perr
);
1539 return CSSMERR_CSP_MEMORY_ERROR
;
1545 * In the PKCS3 form, the public blob is simply the literal
1546 * public key value, not DER encoded.
1548 static CSSM_RETURN
DHPublicKeyDecodePKCS3(
1555 CSSM_DATA pubKey
= {(uint32
)length
, (uint8
*)p
};
1556 openKey
->pub_key
= cssmDataToBn(pubKey
);
1560 return CSSMERR_CSP_MEMORY_ERROR
;
1564 static CSSM_RETURN
DHPublicKeyEncodePKCS3(
1567 CssmOwnedData
&encodedKey
)
1571 bnToCssmData(openKey
->pub_key
, pubKey
, coder
);
1572 encodedKey
.copy(CssmData::overlay(pubKey
));
1576 return CSSMERR_CSP_MEMORY_ERROR
;
1580 static CSSM_RETURN
DHPublicKeyDecodeX509(
1586 NSS_DHPublicKeyX509 nssPubKey
;
1589 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
1590 perr
= coder
.decode(p
, length
, kSecAsn1DHPublicKeyX509Template
,
1593 logAsnErr("decode(DHPublicKeyX509)", perr
);
1594 return CSSMERR_CSP_INVALID_KEY
;
1598 CSSM_RETURN crtn
= nssAlgIdToDhX942(nssPubKey
.algorithm
, openKey
);
1604 * Post-decode public key length in bits
1605 * Contents are pub_key as DER-encoded INTEGER
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
;
1615 openKey
->pub_key
= cssmDataToBn(pubKeyInt
);
1618 /* FIXME - bad sig? memory? */
1619 return CSSMERR_CSP_MEMORY_ERROR
;
1624 static CSSM_RETURN
DHPublicKeyEncodeX509(
1627 CssmOwnedData
&encodedKey
)
1629 /* convert into a NSS_DHPublicKeyX509 */
1630 NSS_DHPublicKeyX509 nssPubKey
;
1631 memset(&nssPubKey
, 0, sizeof(nssPubKey
));
1632 NSS_DHAlgorithmIdentifierX942
&alg
= nssPubKey
.algorithm
;
1635 dhToNssAlgIdX942(openKey
, alg
, coder
);
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;
1646 return CSSMERR_CSP_MEMORY_ERROR
;
1651 perr
= SecNssEncodeItemOdata(&nssPubKey
, kSecAsn1DHPublicKeyX509Template
,
1654 logAsnErr("encode(DHPublicKeyX509)", perr
);
1655 return CSSMERR_CSP_MEMORY_ERROR
;
1660 CSSM_RETURN
DHPrivateKeyDecode(
1662 CSSM_KEYBLOB_FORMAT 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
);
1675 return CSSMERR_CSP_INTERNAL_ERROR
;
1679 CSSM_RETURN
DHPrivateKeyEncode(
1681 CSSM_KEYBLOB_FORMAT format
,
1682 CssmOwnedData
&encodedKey
)
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
);
1693 return CSSMERR_CSP_INTERNAL_ERROR
;
1697 CSSM_RETURN
DHPublicKeyDecode(
1699 CSSM_KEYBLOB_FORMAT 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
);
1712 return CSSMERR_CSP_INTERNAL_ERROR
;
1716 CSSM_RETURN
DHPublicKeyEncode(
1718 CSSM_KEYBLOB_FORMAT format
,
1719 CssmOwnedData
&encodedKey
)
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
);
1730 return CSSMERR_CSP_INTERNAL_ERROR
;
1735 * Encode/decode a NSS_DHParameterBlock.
1737 CSSM_RETURN
DHParamBlockDecode(
1738 const CSSM_DATA
&encParam
,
1739 NSS_DHParameterBlock
¶mBlock
,
1744 memset(¶mBlock
, 0, sizeof(paramBlock
));
1745 perr
= coder
.decodeItem(encParam
, kSecAsn1DHParameterBlockTemplate
,
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
1759 memset(¶mBlock
, 0, sizeof(paramBlock
));
1760 perr
= coder
.decodeItem(encParam
, kSecAsn1DHParameterTemplate
,
1761 ¶mBlock
.params
);
1765 return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS
;
1769 #pragma mark *** Message Digest ***
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).
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.
1781 CSSM_RETURN
generateDigestInfo(
1782 const void *msgDigest
,
1784 CSSM_ALGORITHMS digestAlg
, // CSSM_ALGID_SHA1, etc.
1785 CssmOwnedData
&encodedInfo
,
1786 size_t maxEncodedSize
)
1788 if(digestAlg
== CSSM_ALGID_NONE
) {
1789 /* special case, no encode, just copy */
1790 encodedInfo
.copy(msgDigest
, digestLen
);
1794 NSS_DigestInfo digestInfo
;
1795 CSSM_X509_ALGORITHM_IDENTIFIER
&algId
= digestInfo
.digestAlgorithm
;
1797 memset(&digestInfo
, 0, sizeof(digestInfo
));
1799 case CSSM_ALGID_MD5
:
1800 algId
.algorithm
= CSSMOID_MD5
;
1802 case CSSM_ALGID_MD2
:
1803 algId
.algorithm
= CSSMOID_MD2
;
1805 case CSSM_ALGID_SHA1
:
1806 algId
.algorithm
= CSSMOID_SHA1
;
1808 case CSSM_ALGID_SHA224
:
1809 algId
.algorithm
= CSSMOID_SHA224
;
1811 case CSSM_ALGID_SHA256
:
1812 algId
.algorithm
= CSSMOID_SHA256
;
1814 case CSSM_ALGID_SHA384
:
1815 algId
.algorithm
= CSSMOID_SHA384
;
1817 case CSSM_ALGID_SHA512
:
1818 algId
.algorithm
= CSSMOID_SHA512
;
1821 return CSSMERR_CSP_INVALID_ALGORITHM
;
1823 nullAlgParams(algId
);
1824 digestInfo
.digest
.Data
= (uint8
*)msgDigest
;
1825 digestInfo
.digest
.Length
= digestLen
;
1829 perr
= SecNssEncodeItemOdata(&digestInfo
, kSecAsn1DigestInfoTemplate
,
1832 logAsnErr("encode(digestInfo)", perr
);
1833 return CSSMERR_CSP_MEMORY_ERROR
;