+++ /dev/null
-/*
- * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-/*
- * opensslAsn1.h - ANS1 encode/decode of openssl object, libssnasn1 version
- */
-#include "opensslAsn1.h"
-#include "BinaryKey.h"
-#include "AppleCSPUtils.h"
-#include "osKeyTemplates.h"
-#include <openssl/err.h>
-#include <openssl/bn.h>
-#include <openssl/crypto.h>
-
-#include <SecurityNssAsn1/SecNssCoder.h>
-#include <SecurityNssAsn1/secerr.h>
-#include <SecurityNssAsn1/keyTemplates.h>
-#include <Security/debugging.h>
-#include <Security/oidsalg.h>
-
-#include <assert.h>
-
-#define sslAsn1Debug(args...) secdebug("sslAsn1", ##args)
-
-#ifndef NDEBUG
-#include <stdio.h>
-#include <SecurityNssAsn1/secerr.h>
-
-static void logAsnErr(
- const char *op,
- PRErrorCode perr)
-{
- printf("Error on %s: %s\n", op, SECErrorString(perr));
-}
-#else
-#define logAsnErr(op, perr)
-#endif
-
-/* CSSM_DATA --> BIGNUM */
-BIGNUM *cssmDataToBn(
- const CSSM_DATA &cdata)
-{
- BIGNUM *bn = BN_new();
- BIGNUM *rtn;
-
- rtn = BN_bin2bn(cdata.Data, cdata.Length, bn);
- if(rtn == NULL) {
- BN_free(bn);
- CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
- }
- return bn;
-}
-
-/* BIGNUM --> CSSM_DATA, mallocing from a SecNssCoder's PL_ArenaPool */
-void bnToCssmData(
- const BIGNUM *bn,
- CSSM_DATA &cdata,
- SecNssCoder &coder)
-{
- assert(bn != NULL);
- unsigned numBytes = BN_num_bytes(bn);
- cdata.Data = (uint8 *)coder.malloc(numBytes);
- if(cdata.Data == NULL) {
- CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
- }
- cdata.Length = numBytes;
- BN_bn2bin(bn, cdata.Data);
-}
-
-/*
- * CSSM_DATA --> unsigned int
- */
-unsigned cssmDataToInt(
- const CSSM_DATA &cdata)
-{
- if((cdata.Length == 0) || (cdata.Data == NULL)) {
- return 0;
- }
- unsigned len = (unsigned)cdata.Length;
- if(len > sizeof(int)) {
- logAsnErr("cssmDataToInt: Length error (%u)", len);
- CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
- }
-
- unsigned rtn = 0;
- uint8 *cp = cdata.Data;
- for(unsigned i=0; i<len; i++) {
- rtn = (rtn << 8) | *cp++;
- }
- return rtn;
-}
-
-/*
- * unsigned int --> CSSM_DATA, mallocing from an SecNssCoder
- */
-void intToCssmData(
- unsigned num,
- CSSM_DATA &cdata,
- SecNssCoder &coder)
-{
- unsigned len = 0;
-
- if(num < 0x100) {
- len = 1;
- }
- else if(num < 0x10000) {
- len = 2;
- }
- else if(num < 0x1000000) {
- len = 3;
- }
- else {
- len = 4;
- }
- cdata.Data = (uint8 *)coder.malloc(len);
- cdata.Length = len;
- uint8 *cp = &cdata.Data[len - 1];
- for(unsigned i=0; i<len; i++) {
- *cp-- = num & 0xff;
- num >>= 8;
- }
-}
-
-/*
- * Set up a encoded NULL for AlgorithmIdentifier.parameters,
- * required for RSA
- */
-static void nullAlgParams(
- CSSM_X509_ALGORITHM_IDENTIFIER &algId)
-{
- static const uint8 encNull[2] = { SEC_ASN1_NULL, 0 };
- CSSM_DATA encNullData;
- encNullData.Data = (uint8 *)encNull;
- encNullData.Length = 2;
-
- algId.parameters = encNullData;
-}
-
-#pragma mark -
-#pragma mark *** RSA key encode/decode ***
-
-/*
- * DER encode/decode RSA keys in various formats.
- *
- * Public key, CSSM_KEYBLOB_RAW_FORMAT_PKCS1
- * -- compatible with BSAFE
- * -- used for CSSM_KEYBLOB_RAW_FORMAT_DIGEST on both keys
- */
-static CSSM_RETURN RSAPublicKeyDecodePKCS1(
- SecNssCoder &coder,
- RSA *openKey,
- void *p,
- size_t length)
-{
- NSS_RSAPublicKeyPKCS1 nssPubKey;
-
- memset(&nssPubKey, 0, sizeof(nssPubKey));
- PRErrorCode perr = coder.decode(p, length,
- NSS_RSAPublicKeyPKCS1Template, &nssPubKey);
- if(perr) {
- logAsnErr("decode(RSAPublicKeyPKCS1)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- try {
- openKey->n = cssmDataToBn(nssPubKey.modulus);
- openKey->e = cssmDataToBn(nssPubKey.publicExponent);
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return 0;
-}
-
-static CSSM_RETURN RSAPublicKeyEncodePKCS1(
- SecNssCoder &coder,
- RSA *openKey,
- CssmOwnedData &encodedKey)
-{
- /* convert to NSS_RSAPublicKeyPKCS1 */
- NSS_RSAPublicKeyPKCS1 nssPubKey;
-
- try {
- bnToCssmData(openKey->n, nssPubKey.modulus, coder);
- bnToCssmData(openKey->e, nssPubKey.publicExponent, coder);
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-
- PRErrorCode prtn;
- prtn = SecNssEncodeItemOdata(&nssPubKey,
- NSS_RSAPublicKeyPKCS1Template, encodedKey);
- if(prtn) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-/*
- * SubjectPublicKeyInfo, as used by openssl.
- * The subjectPublicKey component is a PKCS1-style RSAPublicKey.
- */
-static CSSM_RETURN RSAPublicKeyDecodeX509(
- SecNssCoder &coder,
- RSA *openKey,
- void *p,
- size_t length)
-{
- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo;
- PRErrorCode perr;
-
- memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo));
- perr = coder.decode(p, length, NSS_SubjectPublicKeyInfoTemplate,
- &nssPubKeyInfo);
- if(perr) {
- logAsnErr("decode(RSA SubjectPublicKeyInfo)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- /* verify alg identifier */
- const CSSM_OID *oid = &nssPubKeyInfo.algorithm.algorithm;
- if(!cspCompareCssmData(oid, &CSSMOID_RSA)) {
- sslAsn1Debug("RSAPublicKeyDecodeX509: bad OID");
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- /* decode the raw bits */
- CSSM_DATA *pubKey = &nssPubKeyInfo.subjectPublicKey;
- /* decoded length was in bits */
- pubKey->Length = (pubKey->Length + 7) / 8;
- return RSAPublicKeyDecodePKCS1(coder, openKey, pubKey->Data,
- pubKey->Length);
-}
-
-static CSSM_RETURN RSAPublicKeyEncodeX509(
- SecNssCoder &coder,
- RSA *openKey,
- CssmOwnedData &encodedKey)
-{
- CssmAutoData aData(CssmAllocator::standard());
- CSSM_RETURN crtn;
-
- /* First get an encoded PKCS1-style RSAPublicKey */
- crtn = RSAPublicKeyEncodePKCS1(coder, openKey, aData);
- if(crtn) {
- return crtn;
- }
-
- /*
- * That's the AsnBits subjectPublicKey component of a
- * SubjectPublicKeyInfo
- */
- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo;
- memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo));
- nssPubKeyInfo.subjectPublicKey.Data = (uint8 *)aData.data();
- nssPubKeyInfo.subjectPublicKey.Length = aData.length() * 8;
-
- CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPubKeyInfo.algorithm;
- algId.algorithm = CSSMOID_RSA;
-
- /* NULL algorithm paramneters, always in this case */
- nullAlgParams(algId);
-
- /* DER encode */
- PRErrorCode perr;
- perr = SecNssEncodeItemOdata(&nssPubKeyInfo,
- NSS_SubjectPublicKeyInfoTemplate, encodedKey);
-
- if(perr) {
- logAsnErr("encode(RSA SubjectPublicKeyInfo)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-/*
- * RSA private key, PKCS1 format, used by openssl.
- */
-static CSSM_RETURN RSAPrivateKeyDecodePKCS1(
- SecNssCoder &coder,
- RSA *openKey,
- void *p,
- size_t length)
-{
- NSS_RSAPrivateKeyPKCS1 nssPrivKey;
- PRErrorCode perr;
-
- memset(&nssPrivKey, 0, sizeof(nssPrivKey));
- perr = coder.decode(p, length, NSS_RSAPrivateKeyPKCS1Template, &nssPrivKey);
- if(perr) {
- logAsnErr("decode(RSAPrivateKeyPKCS)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- /* convert nssPrivKey fields to RSA key fields */
- try {
- openKey->version = cssmDataToInt(nssPrivKey.version);
- openKey->n = cssmDataToBn(nssPrivKey.modulus);
- openKey->e = cssmDataToBn(nssPrivKey.publicExponent);
- openKey->d = cssmDataToBn(nssPrivKey.privateExponent);
- openKey->p = cssmDataToBn(nssPrivKey.prime1);
- openKey->q = cssmDataToBn(nssPrivKey.prime2);
- openKey->dmp1 = cssmDataToBn(nssPrivKey.exponent1);
- openKey->dmq1 = cssmDataToBn(nssPrivKey.exponent2);
- openKey->iqmp = cssmDataToBn(nssPrivKey.coefficient);
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return 0;
-}
-
-static CSSM_RETURN RSAPrivateKeyEncodePKCS1(
- SecNssCoder &coder,
- RSA *openKey,
- CssmOwnedData &encodedKey)
-{
- NSS_RSAPrivateKeyPKCS1 nssPrivKey;
- PRErrorCode perr;
-
- /* convert to NSS_RSAPrivateKeyPKCS1 */
- try {
- intToCssmData(openKey->version, nssPrivKey.version, coder);
- bnToCssmData(openKey->n, nssPrivKey.modulus, coder);
- bnToCssmData(openKey->e, nssPrivKey.publicExponent, coder);
- bnToCssmData(openKey->d, nssPrivKey.privateExponent, coder);
- bnToCssmData(openKey->p, nssPrivKey.prime1, coder);
- bnToCssmData(openKey->q, nssPrivKey.prime2, coder);
- bnToCssmData(openKey->dmp1, nssPrivKey.exponent1, coder);
- bnToCssmData(openKey->dmq1, nssPrivKey.exponent2, coder);
- bnToCssmData(openKey->iqmp, nssPrivKey.coefficient, coder);
- }
- catch(...) {
- /* ? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-
- /* DER encode */
- perr = SecNssEncodeItemOdata(&nssPrivKey, NSS_RSAPrivateKeyPKCS1Template,
- encodedKey);
- if(perr) {
- logAsnErr("encode(RSAPrivateKeyPKCS1)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-/*
- * RSA private key, PKCS8, compatible with BSAFE.
- */
-static CSSM_RETURN RSAPrivateKeyDecodePKCS8(
- SecNssCoder &coder,
- RSA *openKey,
- void *p,
- size_t length)
-{
- NSS_PrivateKeyInfo nssPrivKeyInfo;
- PRErrorCode perr;
-
- memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
- perr = coder.decode(p, length, NSS_PrivateKeyInfoTemplate, &nssPrivKeyInfo);
- if(perr) {
- logAsnErr("decode(PrivateKeyInfo)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- /* verify alg identifier */
- const CSSM_OID *oid = &nssPrivKeyInfo.algorithm.algorithm;
- if(!cspCompareCssmData(oid, &CSSMOID_RSA)) {
- sslAsn1Debug("RSAPrivateKeyDecodePKCS8: bad OID");
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- /*
- * nssPrivKeyInfo.privateKey is an octet string which needs
- * subsequent decoding
- */
- CSSM_DATA *privKey = &nssPrivKeyInfo.privateKey;
- return RSAPrivateKeyDecodePKCS1(coder, openKey,
- privKey->Data, privKey->Length);
-}
-
-static CSSM_RETURN RSAPrivateKeyEncodePKCS8(
- SecNssCoder &coder,
- RSA *openKey,
- CssmOwnedData &encodedKey)
-{
-
- /* First get PKCS1-style encoding */
- CssmAutoData aData(CssmAllocator::standard());
- CSSM_RETURN crtn = RSAPrivateKeyEncodePKCS1(coder, openKey, aData);
- if(crtn) {
- return crtn;
- }
-
- /* that encoding is the privateKey field of a NSS_PrivateKeyInfo */
- NSS_PrivateKeyInfo nssPrivKeyInfo;
- memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
- nssPrivKeyInfo.privateKey.Data = (uint8 *)aData.data();
- nssPrivKeyInfo.privateKey.Length = aData.length();
-
- CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPrivKeyInfo.algorithm;
- algId.algorithm = CSSMOID_RSA;
-
- /* NULL algorithm paramneters, always in this case */
- nullAlgParams(algId);
-
- /* FIXME : attributes? */
-
- uint8 vers = 0;
- nssPrivKeyInfo.version.Data = &vers;
- nssPrivKeyInfo.version.Length = 1;
-
- /* DER encode */
- PRErrorCode perr;
- perr = SecNssEncodeItemOdata(&nssPrivKeyInfo,
- NSS_PrivateKeyInfoTemplate, encodedKey);
-
- if(perr) {
- logAsnErr("encode(RSA PrivateKeyInfo)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-CSSM_RETURN RSAPublicKeyDecode(
- RSA *openKey,
- CSSM_KEYBLOB_FORMAT format,
- void *p,
- size_t length)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
- return RSAPublicKeyDecodePKCS1(coder, openKey, p, length);
- case CSSM_KEYBLOB_RAW_FORMAT_X509:
- return RSAPublicKeyDecodeX509(coder, openKey, p, length);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-CSSM_RETURN RSAPublicKeyEncode(
- RSA *openKey,
- CSSM_KEYBLOB_FORMAT format,
- CssmOwnedData &encodedKey)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
- return RSAPublicKeyEncodePKCS1(coder, openKey, encodedKey);
- case CSSM_KEYBLOB_RAW_FORMAT_X509:
- return RSAPublicKeyEncodeX509(coder, openKey, encodedKey);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-CSSM_RETURN RSAPrivateKeyDecode(
- RSA *openKey,
- CSSM_KEYBLOB_FORMAT format,
- void *p,
- size_t length)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
- return RSAPrivateKeyDecodePKCS1(coder, openKey, p, length);
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
- return RSAPrivateKeyDecodePKCS8(coder, openKey, p, length);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-CSSM_RETURN RSAPrivateKeyEncode(
- RSA *openKey,
- CSSM_KEYBLOB_FORMAT format,
- CssmOwnedData &encodedKey)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS1:
- return RSAPrivateKeyEncodePKCS1(coder, openKey, encodedKey);
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
- return RSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-#pragma mark -
-#pragma mark *** DSA key encode/decode ***
-
-/***
- *** DSA
- ***/
-
-/* NSS_DSAAlgorithmIdBSAFE <--> DSA->{p,g,q} */
-static void dsaToNssAlgIdBSAFE(
- const DSA *openKey,
- NSS_DSAAlgorithmIdBSAFE &algId,
- SecNssCoder &coder)
-{
- /* non-standard, BSAFE-specific OID */
- algId.algorithm = CSSMOID_DSA; // not mallocd
- unsigned numBits = BN_num_bits(openKey->p);
- intToCssmData(numBits, algId.params.keySizeInBits, coder);
- bnToCssmData(openKey->p, algId.params.p, coder);
- bnToCssmData(openKey->q, algId.params.q, coder);
- bnToCssmData(openKey->g, algId.params.g, coder);
-}
-
-static CSSM_RETURN nssAlgIdToDsaBSAFE(
- NSS_DSAAlgorithmIdBSAFE &algId,
- DSA *openKey)
-{
- /* non-standard, BSAFE-specific OID */
- if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA)) {
- sslAsn1Debug("nssAlgIdToDsaBSAFE: bad OID");
- return CSSMERR_CSP_INVALID_KEY;
- }
- openKey->p = cssmDataToBn(algId.params.p);
- openKey->q = cssmDataToBn(algId.params.q);
- openKey->g = cssmDataToBn(algId.params.g);
- return CSSM_OK;
-}
-
-/* NSS_DSAAlgorithmIdX509 <--> DSA->{p,g,q} */
-static void dsaToNssAlgIdX509(
- const DSA *openKey,
- NSS_DSAAlgorithmIdX509 &algId,
- SecNssCoder &coder)
-{
- algId.algorithm = CSSMOID_DSA_CMS; // not mallocd
- bnToCssmData(openKey->p, algId.params->p, coder);
- bnToCssmData(openKey->q, algId.params->q, coder);
- bnToCssmData(openKey->g, algId.params->g, coder);
-}
-
-static CSSM_RETURN nssAlgIdToDsaX509(
- NSS_DSAAlgorithmIdX509 &algId,
- DSA *openKey)
-{
- if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_CMS) &&
- !cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_JDK)) {
- sslAsn1Debug("nssAlgIdToDsaX509: bad OID");
- return CSSMERR_CSP_INVALID_KEY;
- }
- /* these might be absent per CMS */
- if(algId.params == NULL) {
- return CSSM_OK;
- }
- openKey->p = cssmDataToBn(algId.params->p);
- openKey->q = cssmDataToBn(algId.params->q);
- openKey->g = cssmDataToBn(algId.params->g);
- return CSSM_OK;
-}
-
-/*
- * DSA public keys, FIPS186 format.
- * Compatible with BSAFE.
- */
-CSSM_RETURN DSAPublicKeyDecodeFIPS186(
- SecNssCoder &coder,
- DSA *openKey,
- void *p,
- unsigned length)
-{
- NSS_DSAPublicKeyBSAFE nssPubKey;
- PRErrorCode perr;
- CSSM_RETURN crtn;
-
- memset(&nssPubKey, 0, sizeof(nssPubKey));
- perr = coder.decode(p, length, NSS_DSAPublicKeyBSAFETemplate,
- &nssPubKey);
- if(perr) {
- logAsnErr("decode(DSAPublicKeyBSAFE)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- /* BSAFE style DSA-specific alg params */
- NSS_DSAAlgorithmIdBSAFE &algId = nssPubKey.dsaAlg;
- crtn = nssAlgIdToDsaBSAFE(algId, openKey);
- if(crtn) {
- return crtn;
- }
-
- /* inside of nssPubKey.publicKey is the DER-encoding of a
- * ASN Integer; decoded length was in bits */
- nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8;
- CSSM_DATA pubKeyBytes;
- perr = coder.decodeItem(nssPubKey.publicKey,
- SEC_UnsignedIntegerTemplate,
- &pubKeyBytes);
- if(perr) {
- logAsnErr("decode(NSS_DSAPublicKeyBSAFE.publicKey)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
- openKey->pub_key = cssmDataToBn(pubKeyBytes);
-
- if(openKey->pub_key == NULL) {
- return CSSMERR_CSP_INVALID_KEY;
- }
- return 0;
-}
-
-CSSM_RETURN DSAPublicKeyEncodeFIPS186(
- SecNssCoder &coder,
- DSA *openKey,
- CssmOwnedData &encodedKey)
-{
- try {
- /* convert to NSS_DSAPublicKeyBSAFE */
- NSS_DSAPublicKeyBSAFE nssPubKey;
- memset(&nssPubKey, 0, sizeof(nssPubKey));
- dsaToNssAlgIdBSAFE(openKey, nssPubKey.dsaAlg, coder);
-
- /*
- * publicKey is the DER-encoding of a ASN INTEGER wrapped in
- * an AsnBits
- */
- CSSM_DATA pubKeyRaw;
- PRErrorCode perr;
- bnToCssmData(openKey->pub_key, pubKeyRaw, coder);
- perr = coder.encodeItem(&pubKeyRaw, SEC_UnsignedIntegerTemplate,
- nssPubKey.publicKey);
- if(perr) {
- logAsnErr("encodeItem(DSAPublicKeyBSAFE.publicKey)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- nssPubKey.publicKey.Length *= 8;
-
- /* DER encode */
- SecNssEncodeItemOdata(&nssPubKey, NSS_DSAPublicKeyBSAFETemplate,
- encodedKey);
- return CSSM_OK;
- }
- catch(...) {
- /* ? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-}
-
-/*
- * DSA private keys, FIPS186 format.
- * Compatible with BSAFE.
- */
-CSSM_RETURN DSAPrivateKeyDecodeFIPS186(
- SecNssCoder &coder,
- DSA *openKey,
- void *p,
- unsigned length)
-{
- NSS_DSAPrivateKeyBSAFE nssPrivKeyInfo;
- PRErrorCode perr;
-
- memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
- perr = coder.decode(p, length, NSS_DSAPrivateKeyBSAFETemplate,
- &nssPrivKeyInfo);
- if(perr) {
- logAsnErr("decode(DSA PrivateKeyInfo)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- CSSM_RETURN crtn = nssAlgIdToDsaBSAFE(nssPrivKeyInfo.dsaAlg, openKey);
- if(crtn) {
- return crtn;
- }
-
- /* nssPrivKeyInfo.privateKey is the DER-encoding of a
- * DSAPrivateKeyOcts... */
- try {
- PRErrorCode perr;
- NSS_DSAPrivateKeyOcts keyOcts;
-
- perr = coder.decodeItem(nssPrivKeyInfo.privateKey,
- NSS_DSAPrivateKeyOctsTemplate, &keyOcts);
- if(perr) {
- logAsnErr("decode(DSA PrivateKeyInfoOcts)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- openKey->priv_key = cssmDataToBn(keyOcts.privateKey);
- if(openKey->priv_key == NULL) {
- return CSSMERR_CSP_INVALID_KEY;
- }
- return 0;
- }
- catch(...) {
- return CSSMERR_CSP_INVALID_KEY;
- }
-}
-
-CSSM_RETURN DSAPrivateKeyEncodeFIPS186(
- SecNssCoder &coder,
- DSA *openKey,
- CssmOwnedData &encodedKey)
-{
- try {
- /* First convert into a NSS_DSAPrivateKeyBSAFE */
- NSS_DSAPrivateKeyBSAFE nssPrivKey;
- intToCssmData(openKey->version, nssPrivKey.version, coder);
- dsaToNssAlgIdBSAFE(openKey, nssPrivKey.dsaAlg, coder);
-
- /* nssPrivKey.privateKey is the DER-encoding of one of these... */
- NSS_DSAPrivateKeyOcts privKeyOcts;
- bnToCssmData(openKey->priv_key, privKeyOcts.privateKey, coder);
-
- /* DER encode the privateKey portion into arena pool memory
- * into NSS_DSAPrivateKeyPKCS8.privateKey */
- coder.encodeItem(&privKeyOcts, NSS_DSAPrivateKeyOctsTemplate,
- nssPrivKey.privateKey);
-
- /* DER encode the whole thing */
- PRErrorCode perr;
- perr = SecNssEncodeItemOdata(&nssPrivKey,
- NSS_DSAPrivateKeyBSAFETemplate, encodedKey);
- return 0;
- }
- catch(...) {
- /* ? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-}
-
-/*
- * DSA private keys, PKCS8/SMIME format.
- */
-CSSM_RETURN DSAPrivateKeyDecodePKCS8(
- SecNssCoder &coder,
- DSA *openKey,
- void *p,
- unsigned length)
-{
- NSS_DSAPrivateKeyPKCS8 nssPrivKeyInfo;
- PRErrorCode perr;
-
- memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo));
- perr = coder.decode(p, length, NSS_DSAPrivateKeyPKCS8Template,
- &nssPrivKeyInfo);
- if(perr) {
- logAsnErr("decode(DSA NSS_DSAPrivateKeyPKCS8)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- CSSM_RETURN crtn = nssAlgIdToDsaX509(nssPrivKeyInfo.dsaAlg, openKey);
- if(crtn) {
- return crtn;
- }
-
- /*
- * Post-decode, nssPrivKeyInfo.privateKey is the DER-encoding of a
- * an ASN integer.
- */
- try {
- PRErrorCode perr;
- CSSM_DATA privKeyInt = {0, NULL};
-
- perr = coder.decodeItem(nssPrivKeyInfo.privateKey,
- SEC_UnsignedIntegerTemplate, &privKeyInt);
- if(perr) {
- logAsnErr("decode(DSA nssPrivKeyInfo.privateKey)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- openKey->priv_key = cssmDataToBn(privKeyInt);
- if(openKey->priv_key == NULL) {
- return CSSMERR_CSP_INVALID_KEY;
- }
- return 0;
- }
- catch(...) {
- return CSSMERR_CSP_INVALID_KEY;
- }
-}
-
-CSSM_RETURN DSAPrivateKeyEncodePKCS8(
- SecNssCoder &coder,
- DSA *openKey,
- CssmOwnedData &encodedKey)
-{
- try {
- /* First convert into a NSS_DSAPrivateKeyPKCS8 */
- NSS_DSAPrivateKeyPKCS8 nssPrivKey;
- NSS_DSAAlgParams algParams;
- memset(&nssPrivKey, 0, sizeof(nssPrivKey));
- memset(&algParams, 0, sizeof(algParams));
- nssPrivKey.dsaAlg.params = &algParams;
- intToCssmData(openKey->version, nssPrivKey.version, coder);
- dsaToNssAlgIdX509(openKey, nssPrivKey.dsaAlg, coder);
-
- /* pre-encode, nssPrivKey.privateKey is the DER-encoding of
- * an ASN integer... */
- CSSM_DATA privKeyInt;
- bnToCssmData(openKey->priv_key, privKeyInt, coder);
-
- /* DER encode the privateKey portion into arena pool memory
- * into NSS_DSAPrivateKeyPKCS8.privateKey */
- coder.encodeItem(&privKeyInt, SEC_UnsignedIntegerTemplate,
- nssPrivKey.privateKey);
-
- /* DER encode the whole thing */
- PRErrorCode perr;
- perr = SecNssEncodeItemOdata(&nssPrivKey,
- NSS_DSAPrivateKeyPKCS8Template, encodedKey);
- return 0;
- }
- catch(...) {
- /* ? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-}
-
-/*
- * DSA public key, X509/openssl format.
- */
-static CSSM_RETURN DSAPublicKeyDecodeX509(
- SecNssCoder &coder,
- DSA *openKey,
- void *p,
- size_t length)
-{
- NSS_DSAPublicKeyX509 nssPubKey;
- PRErrorCode perr;
- CSSM_RETURN crtn;
-
- memset(&nssPubKey, 0, sizeof(nssPubKey));
- perr = coder.decode(p, length, NSS_DSAPublicKeyX509Template,
- &nssPubKey);
- if(perr) {
- logAsnErr("decode(DSAPublicKeyX509)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- /* X509 style DSA-specific alg params */
- NSS_DSAAlgorithmIdX509 &algId = nssPubKey.dsaAlg;
- crtn = nssAlgIdToDsaX509(algId, openKey);
- if(crtn) {
- return crtn;
- }
-
- /* inside of nssPubKey.publicKey is the DER-encoding of a
- * ASN Integer; decoded length was in bits */
- nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8;
- CSSM_DATA pubKeyBytes = {0, NULL};
- perr = coder.decodeItem(nssPubKey.publicKey,
- SEC_UnsignedIntegerTemplate,
- &pubKeyBytes);
- if(perr) {
- logAsnErr("decode(NSS_DSAPublicKeyX509.publicKey)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
- openKey->pub_key = cssmDataToBn(pubKeyBytes);
-
- if(openKey->pub_key == NULL) {
- return CSSMERR_CSP_INVALID_KEY;
- }
- return 0;
-}
-
-static CSSM_RETURN DSAPublicKeyEncodeX509(
- SecNssCoder &coder,
- DSA *openKey,
- CssmOwnedData &encodedKey)
-{
- try {
- /* convert to NSS_DSAPublicKeyX509 */
- NSS_DSAPublicKeyX509 nssPubKey;
- NSS_DSAAlgParams algParams;
- memset(&nssPubKey, 0, sizeof(nssPubKey));
- memset(&algParams, 0, sizeof(algParams));
- nssPubKey.dsaAlg.params = &algParams;
- dsaToNssAlgIdX509(openKey, nssPubKey.dsaAlg, coder);
-
- /*
- * publicKey is the DER-encoding of a ASN INTEGER wrapped in
- * an AsnBits
- */
- CSSM_DATA pubKeyRaw;
- PRErrorCode perr;
- bnToCssmData(openKey->pub_key, pubKeyRaw, coder);
- perr = coder.encodeItem(&pubKeyRaw, SEC_UnsignedIntegerTemplate,
- nssPubKey.publicKey);
- if(perr) {
- logAsnErr("encodeItem(DSAPublicKeyX509.publicKey)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- nssPubKey.publicKey.Length *= 8;
-
- /* DER encode */
- SecNssEncodeItemOdata(&nssPubKey, NSS_DSAPublicKeyX509Template,
- encodedKey);
- return CSSM_OK;
- }
- catch(...) {
- /* ? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-}
-
-/*
- * Encode public key portion only for calculating key digest.
- * Note this works just fine on a partial DSA public key, i.e.,
- * A DSA public key's digest-capable blob is the same whether or
- * not the DSA key has its DSA parameters p, q, and g.
- */
-static CSSM_RETURN DSAPublicKeyEncodeHashable(
- SecNssCoder &coder,
- DSA *openKey,
- CssmOwnedData &encodedKey)
-{
- try {
- /*
- * publicKey is the DER-encoding of an ASN integer
- */
- CSSM_DATA pubKey;
- bnToCssmData(openKey->pub_key, pubKey, coder);
- PRErrorCode perr;
-
- perr = SecNssEncodeItemOdata(&pubKey, SEC_UnsignedIntegerTemplate,
- encodedKey);
- if(perr) {
- logAsnErr("encode(DSAPubHashable)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
- }
- catch(...) {
- /* ? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-}
-
-/*
- * DSA private key, custom openssl format.
- */
-static CSSM_RETURN DSAPrivateKeyDecodeOpenssl(
- SecNssCoder &coder,
- DSA *openKey,
- void *p,
- size_t length)
-{
- NSS_DSAPrivateKeyOpenssl nssPrivKey;
- PRErrorCode perr;
-
- memset(&nssPrivKey, 0, sizeof(nssPrivKey));
- perr = coder.decode(p, length, NSS_DSAPrivateKeyOpensslTemplate,
- &nssPrivKey);
- if(perr) {
- logAsnErr("decode(DSAPrivateKeyOpenssl)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- /* convert nssPrivKey fields to RSA key fields */
- try {
- openKey->version = cssmDataToInt(nssPrivKey.version);
- openKey->p = cssmDataToBn(nssPrivKey.p);
- openKey->q = cssmDataToBn(nssPrivKey.q);
- openKey->g = cssmDataToBn(nssPrivKey.g);
- openKey->pub_key = cssmDataToBn(nssPrivKey.pub);
- openKey->priv_key = cssmDataToBn(nssPrivKey.priv);
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return 0;
-}
-
-static CSSM_RETURN DSAPrivateKeyEncodeOpenssl(
- SecNssCoder &coder,
- DSA *openKey,
- CssmOwnedData &encodedKey)
-{
- NSS_DSAPrivateKeyOpenssl nssPrivKey;
- PRErrorCode perr;
-
- /* convert to NSS_DSAPrivateKeyOpenssl */
- try {
- intToCssmData(openKey->version, nssPrivKey.version, coder);
- bnToCssmData(openKey->p, nssPrivKey.p, coder);
- bnToCssmData(openKey->q, nssPrivKey.q, coder);
- bnToCssmData(openKey->g, nssPrivKey.g, coder);
- bnToCssmData(openKey->pub_key, nssPrivKey.pub, coder);
- bnToCssmData(openKey->priv_key, nssPrivKey.priv, coder);
- }
- catch(...) {
- /* ? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-
- /* DER encode */
- perr = SecNssEncodeItemOdata(&nssPrivKey, NSS_DSAPrivateKeyOpensslTemplate,
- encodedKey);
- if(perr) {
- logAsnErr("encode(DSAPrivateKeyOpenssl)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-CSSM_RETURN DSAPublicKeyDecode(
- DSA *openKey,
- CSSM_KEYBLOB_FORMAT format,
- void *p,
- size_t length)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
- return DSAPublicKeyDecodeFIPS186(coder, openKey, p, length);
- case CSSM_KEYBLOB_RAW_FORMAT_X509:
- return DSAPublicKeyDecodeX509(coder, openKey, p, length);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-CSSM_RETURN DSAPublicKeyEncode(
- DSA *openKey,
- CSSM_KEYBLOB_FORMAT format,
- CssmOwnedData &encodedKey)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
- return DSAPublicKeyEncodeFIPS186(coder, openKey, encodedKey);
- case CSSM_KEYBLOB_RAW_FORMAT_X509:
- return DSAPublicKeyEncodeX509(coder, openKey, encodedKey);
- case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
- return DSAPublicKeyEncodeHashable(coder, openKey, encodedKey);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-CSSM_RETURN DSAPrivateKeyDecode(
- DSA *openKey,
- CSSM_KEYBLOB_FORMAT format,
- void *p,
- size_t length)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
- return DSAPrivateKeyDecodeFIPS186(coder, openKey, p, length);
- case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
- return DSAPrivateKeyDecodeOpenssl(coder, openKey, p, length);
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
- return DSAPrivateKeyDecodePKCS8(coder, openKey, p, length);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-CSSM_RETURN DSAPrivateKeyEncode(
- DSA *openKey,
- CSSM_KEYBLOB_FORMAT format,
- CssmOwnedData &encodedKey)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_FIPS186:
- return DSAPrivateKeyEncodeFIPS186(coder, openKey, encodedKey);
- case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
- return DSAPrivateKeyEncodeOpenssl(coder, openKey, encodedKey);
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
- return DSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-#pragma mark -
-#pragma mark *** DSA Signature encode/decode ***
-
-CSSM_RETURN DSASigEncode(
- DSA_SIG *openSig,
- CssmOwnedData &encodedSig)
-{
- /* temp allocs from this pool */
- SecNssCoder coder;
- /* convert to NSS_DSASignature */
- NSS_DSASignature nssSig;
-
- try {
- bnToCssmData(openSig->r, nssSig.r, coder);
- bnToCssmData(openSig->s, nssSig.s, coder);
- }
- catch(...) {
- /* ? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-
- PRErrorCode prtn = SecNssEncodeItemOdata(&nssSig,
- NSS_DSASignatureTemplate, encodedSig);
- if(prtn) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-CSSM_RETURN DSASigDecode(
- DSA_SIG *openSig,
- const void *p,
- unsigned length)
-{
- NSS_DSASignature nssSig;
- SecNssCoder coder;
-
- memset(&nssSig, 0, sizeof(nssSig));
- PRErrorCode perr = coder.decode(p, length,
- NSS_DSASignatureTemplate, &nssSig);
- if(perr) {
- logAsnErr("decode(DSASigDecode)", perr);
- return CSSMERR_CSP_INVALID_SIGNATURE;
- }
-
- try {
- openSig->r = cssmDataToBn(nssSig.r);
- openSig->s = cssmDataToBn(nssSig.s);
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return 0;
-}
-
-#pragma mark -
-#pragma mark *** DSA Algorithm Parameters encode/decode ***
-
-CSSM_RETURN DSAEncodeAlgParams(
- NSS_DSAAlgParams &algParams,
- CssmOwnedData &encodedParams)
-{
- PRErrorCode prtn = SecNssEncodeItemOdata(&algParams,
- NSS_DSAAlgParamsTemplate, encodedParams);
- if(prtn) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-CSSM_RETURN DSADecodeAlgParams(
- NSS_DSAAlgParams &algParams,
- const void *p,
- unsigned len,
- SecNssCoder &coder)
-{
-
- memset(&algParams, 0, sizeof(algParams));
- PRErrorCode perr = coder.decode(p, len,
- NSS_DSAAlgParamsTemplate, &algParams);
- if(perr) {
- logAsnErr("decode(DSAAlgParams)", perr);
- return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS;
- }
- return CSSM_OK;
-}
-
-#pragma mark -
-#pragma mark *** Diffie-Hellman key encode/decode ***
-
-CSSM_RETURN DHPrivateKeyDecodePKCS3(
- SecNssCoder &coder,
- DH *openKey,
- unsigned char *p,
- unsigned length)
-{
- NSS_DHPrivateKey nssPrivKey;
- PRErrorCode perr;
-
- memset(&nssPrivKey, 0, sizeof(nssPrivKey));
- perr = coder.decode(p, length, NSS_DHPrivateKeyTemplate, &nssPrivKey);
- if(perr) {
- logAsnErr("decode(DHPrivateKey)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- /* verify alg identifier */
- const CSSM_OID *oid = &nssPrivKey.dhOid;
- if(!cspCompareCssmData(oid, &CSSMOID_DH)) {
- sslAsn1Debug("DHPrivateKeyDecode: bad OID");
- return CSSMERR_CSP_ALGID_MISMATCH;
- }
-
- NSS_DHParameter ¶ms = nssPrivKey.params;
-
- try {
- openKey->priv_key = cssmDataToBn(nssPrivKey.secretPart);
- openKey->p = cssmDataToBn(params.prime);
- openKey->g = cssmDataToBn(params.base);
- /* TBD - ignore privateValueLength for now */
- }
- catch(...) {
- /* FIXME - bad sig? memory? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return 0;
-}
-
-CSSM_RETURN DHPrivateKeyEncodePKCS3(
- SecNssCoder &coder,
- DH *openKey,
- CssmOwnedData &encodedKey)
-{
- /* convert into a NSS_DHPrivateKey */
- NSS_DHPrivateKey nssPrivKey;
- NSS_DHParameter ¶ms = nssPrivKey.params;
- memset(&nssPrivKey, 0, sizeof(nssPrivKey));
- nssPrivKey.dhOid = CSSMOID_DH;
-
-
- try {
- bnToCssmData(openKey->priv_key, nssPrivKey.secretPart, coder);
- bnToCssmData(openKey->p, params.prime, coder);
- bnToCssmData(openKey->g, params.base, coder);
- if(openKey->length) {
- /* actually currently not supported in openssl... */
- intToCssmData(openKey->length, params.privateValueLength, coder);
- }
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-
- /* DER encode */
- PRErrorCode perr;
- perr = SecNssEncodeItemOdata(&nssPrivKey, NSS_DHPrivateKeyTemplate,
- encodedKey);
- if(perr) {
- logAsnErr("encode(DHPrivateKey)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-/*
- * NSS_DHAlgorithmIdentifierX942 <--> DH
- * NOTE this is incomplete. It's functional on decode, but we throw
- * away everything except p and g. On encode, we put zeroes in
- * all the fields we don't deal with. Thus the encode side will NOT be
- * interoperable with other implementations.
- */
-static void dhToNssAlgIdX942(
- const DH *openKey,
- NSS_DHAlgorithmIdentifierX942 &algId,
- SecNssCoder &coder)
-{
- /*
- * When trying to encode a public key in X509 form, we may in
- * fact have nothing here - public keys created and exported in
- * PKCS3 have the pub_key value, and that's it.
- */
-
- memset(&algId, 0, sizeof(algId));
- algId.oid = CSSMOID_ANSI_DH_PUB_NUMBER; // not mallocd
- NSS_DHDomainParamsX942 ¶ms = algId.params;
- uint8 zero = 0;
- CSSM_DATA czero = {1, &zero};
- if(openKey->p != NULL) {
- bnToCssmData(openKey->p, params.p, coder);
- }
- else {
- coder.allocCopyItem(czero, params.p);
- }
- if(openKey->g != NULL) {
- bnToCssmData(openKey->g, params.g, coder);
- }
- else {
- coder.allocCopyItem(czero, params.g);
- }
- /* and we never have a vali0d q */
- coder.allocCopyItem(czero, params.q);
-
-}
-
-static CSSM_RETURN nssAlgIdToDhX942(
- NSS_DHAlgorithmIdentifierX942 &algId,
- DH *openKey)
-{
- if(!cspCompareCssmData(&algId.oid, &CSSMOID_ANSI_DH_PUB_NUMBER)) {
- sslAsn1Debug("nssAlgIdToDhX942: bad OID");
- return CSSMERR_CSP_INVALID_KEY;
- }
- openKey->p = cssmDataToBn(algId.params.p);
- openKey->g = cssmDataToBn(algId.params.g);
- return CSSM_OK;
-}
-
-CSSM_RETURN DHPrivateKeyDecodePKCS8(
- SecNssCoder &coder,
- DH *openKey,
- unsigned char *p,
- unsigned length)
-{
- NSS_DHPrivateKeyPKCS8 nssPrivKey;
- PRErrorCode perr;
-
- memset(&nssPrivKey, 0, sizeof(nssPrivKey));
- perr = coder.decode(p, length, NSS_DHPrivateKeyPKCS8Template,
- &nssPrivKey);
- if(perr) {
- logAsnErr("decode(DHPrivateKeyPKCS8)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- try {
- CSSM_RETURN crtn = nssAlgIdToDhX942(nssPrivKey.algorithm, openKey);
- if(crtn) {
- return crtn;
- }
-
- /* post-decode private key is a DER encoded integer */
- CSSM_DATA privKeyInt = {0, NULL};
- if(coder.decodeItem(nssPrivKey.privateKey,
- SEC_UnsignedIntegerTemplate,
- &privKeyInt)) {
- logAsnErr("decode(DHPrivateKeyPKCS8 privKey int)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- openKey->priv_key = cssmDataToBn(privKeyInt);
- }
- catch(...) {
- /* FIXME - bad sig? memory? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return 0;
-}
-
-CSSM_RETURN DHPrivateKeyEncodePKCS8(
- SecNssCoder &coder,
- DH *openKey,
- CssmOwnedData &encodedKey)
-{
- /* convert into a NSS_DHPrivateKeyPKCS8 */
- NSS_DHPrivateKeyPKCS8 nssPrivKey;
- memset(&nssPrivKey, 0, sizeof(nssPrivKey));
- uint8 vers = 0;
- nssPrivKey.version.Length = 1;
- nssPrivKey.version.Data = &vers;
- NSS_DHAlgorithmIdentifierX942 &alg = nssPrivKey.algorithm;
-
- try {
-
- dhToNssAlgIdX942(openKey, alg, coder);
- /* pre-encode, nssPrivKey.privateKey is the DER-encoding of
- * an ASN integer... */
- CSSM_DATA privKeyInt;
- bnToCssmData(openKey->priv_key, privKeyInt, coder);
-
- /* DER encode the privateKey portion into arena pool memory
- * into nssPrivKey.privateKey */
- coder.encodeItem(&privKeyInt, SEC_UnsignedIntegerTemplate,
- nssPrivKey.privateKey);
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-
- /* DER encode */
- PRErrorCode perr;
- perr = SecNssEncodeItemOdata(&nssPrivKey, NSS_DHPrivateKeyPKCS8Template,
- encodedKey);
- if(perr) {
- logAsnErr("encode(DHPrivateKey)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-/*
- * In the PKCS3 form, the public blob is simply the literal
- * public key value, not DER encoded.
- */
-static CSSM_RETURN DHPublicKeyDecodePKCS3(
- DH *openKey,
- SecNssCoder &coder,
- unsigned char *p,
- unsigned length)
-{
- try {
- CSSM_DATA pubKey = {(uint32)length, (uint8 *)p};
- openKey->pub_key = cssmDataToBn(pubKey);
- return CSSM_OK;
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-}
-
-static CSSM_RETURN DHPublicKeyEncodePKCS3(
- DH *openKey,
- SecNssCoder &coder,
- CssmOwnedData &encodedKey)
-{
- try {
- CSSM_DATA pubKey;
- bnToCssmData(openKey->pub_key, pubKey, coder);
- encodedKey.copy(CssmData::overlay(pubKey));
- return CSSM_OK;
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-}
-
-static CSSM_RETURN DHPublicKeyDecodeX509(
- DH *openKey,
- SecNssCoder &coder,
- unsigned char *p,
- unsigned length)
-{
- NSS_DHPublicKeyX509 nssPubKey;
- PRErrorCode perr;
-
- memset(&nssPubKey, 0, sizeof(nssPubKey));
- perr = coder.decode(p, length, NSS_DHPublicKeyX509Template,
- &nssPubKey);
- if(perr) {
- logAsnErr("decode(DHPublicKeyX509)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
-
- try {
- CSSM_RETURN crtn = nssAlgIdToDhX942(nssPubKey.algorithm, openKey);
- if(crtn) {
- return crtn;
- }
-
- /*
- * Post-decode public key length in bits
- * Contents are pub_key as DER-encoded INTEGER
- */
- CSSM_DATA &pubKey = nssPubKey.publicKey;
- pubKey.Length = (pubKey.Length + 7) / 8;
- CSSM_DATA pubKeyInt = {0, NULL};
- if(coder.decodeItem(pubKey,
- SEC_UnsignedIntegerTemplate, &pubKeyInt)) {
- logAsnErr("decode(DHPublicKeyX509 pub key int)", perr);
- return CSSMERR_CSP_INVALID_KEY;
- }
- openKey->pub_key = cssmDataToBn(pubKeyInt);
- }
- catch(...) {
- /* FIXME - bad sig? memory? */
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return 0;
-}
-
-static CSSM_RETURN DHPublicKeyEncodeX509(
- DH *openKey,
- SecNssCoder &coder,
- CssmOwnedData &encodedKey)
-{
- /* convert into a NSS_DHPublicKeyX509 */
- NSS_DHPublicKeyX509 nssPubKey;
- memset(&nssPubKey, 0, sizeof(nssPubKey));
- NSS_DHAlgorithmIdentifierX942 &alg = nssPubKey.algorithm;
-
- try {
- dhToNssAlgIdX942(openKey, alg, coder);
-
- /* encode pub_key as integer */
- CSSM_DATA pubKeyInt = {0, NULL};
- bnToCssmData(openKey->pub_key, pubKeyInt, coder);
- coder.encodeItem(&pubKeyInt, SEC_UnsignedIntegerTemplate,
- nssPubKey.publicKey);
- /* specify length in bits */
- nssPubKey.publicKey.Length *= 8;
- }
- catch(...) {
- return CSSMERR_CSP_MEMORY_ERROR;
- }
-
- /* DER encode */
- PRErrorCode perr;
- perr = SecNssEncodeItemOdata(&nssPubKey, NSS_DHPublicKeyX509Template,
- encodedKey);
- if(perr) {
- logAsnErr("encode(DHPublicKeyX509)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-
-CSSM_RETURN DHPrivateKeyDecode(
- DH *openKey,
- CSSM_KEYBLOB_FORMAT format,
- unsigned char *p,
- unsigned length)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
- return DHPrivateKeyDecodePKCS3(coder, openKey, p, length);
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
- return DHPrivateKeyDecodePKCS8(coder, openKey, p, length);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-CSSM_RETURN DHPrivateKeyEncode(
- DH *openKey,
- CSSM_KEYBLOB_FORMAT format,
- CssmOwnedData &encodedKey)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
- return DHPrivateKeyEncodePKCS3(coder, openKey, encodedKey);
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
- return DHPrivateKeyEncodePKCS8(coder, openKey, encodedKey);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-CSSM_RETURN DHPublicKeyDecode(
- DH *openKey,
- CSSM_KEYBLOB_FORMAT format,
- unsigned char *p,
- unsigned length)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
- return DHPublicKeyDecodePKCS3(openKey, coder, p, length);
- case CSSM_KEYBLOB_RAW_FORMAT_X509:
- return DHPublicKeyDecodeX509(openKey, coder, p, length);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-CSSM_RETURN DHPublicKeyEncode(
- DH *openKey,
- CSSM_KEYBLOB_FORMAT format,
- CssmOwnedData &encodedKey)
-{
- SecNssCoder coder;
-
- switch(format) {
- case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:
- return DHPublicKeyEncodePKCS3(openKey, coder, encodedKey);
- case CSSM_KEYBLOB_RAW_FORMAT_X509:
- return DHPublicKeyEncodeX509(openKey, coder, encodedKey);
- default:
- assert(0);
- return CSSMERR_CSP_INTERNAL_ERROR;
- }
-}
-
-/*
- * Encode/decode a NSS_DHParameterBlock.
- */
-CSSM_RETURN DHParamBlockDecode(
- const CSSM_DATA &encParam,
- NSS_DHParameterBlock ¶mBlock,
- SecNssCoder &coder)
-{
- PRErrorCode perr;
-
- memset(¶mBlock, 0, sizeof(paramBlock));
- perr = coder.decodeItem(encParam, NSS_DHParameterBlockTemplate,
- ¶mBlock);
- if(perr == 0) {
- return CSSM_OK;
- }
-
- /*
- * CDSA Extension: the CDSA Algorithm Guide says that the D-H
- * parameter block is supposed to be wrapped with its accompanying
- * OID. However Openssl does not do this; it just exports
- * an encoded DHParameter rather than a DHParameterBlock.
- * For compatibility we'll try decoding the parameters as one
- * of these.
- */
- memset(¶mBlock, 0, sizeof(paramBlock));
- perr = coder.decodeItem(encParam, NSS_DHParameterTemplate,
- ¶mBlock.params);
- if(perr == 0) {
- return CSSM_OK;
- }
- return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS;
-}
-
-#pragma mark -
-#pragma mark *** Message Digest ***
-
-/*
- * Given a message digest and associated algorithm, cook up a PKCS1-style
- * DigestInfo and return its DER encoding. This is a necessary step for
- * RSA signature (both generating and verifying) - the output of this
- * routine is what gets encrypted during signing, and what is expected when
- * verifying (i.e., decrypting the signature).
- *
- * A good guess for the length of the output digestInfo is the size of the
- * key being used to sign/verify. The digest can never be larger than that.
- */
-CSSM_RETURN generateDigestInfo(
- const void *msgDigest,
- size_t digestLen,
- CSSM_ALGORITHMS digestAlg, // CSSM_ALGID_SHA1, etc.
- CssmOwnedData &encodedInfo,
- size_t maxEncodedSize)
-{
- if(digestAlg == CSSM_ALGID_NONE) {
- /* special case, no encode, just copy */
- encodedInfo.copy(msgDigest, digestLen);
- return 0;
- }
-
- NSS_DigestInfo digestInfo;
- CSSM_X509_ALGORITHM_IDENTIFIER &algId = digestInfo.digestAlgorithm;
-
- memset(&digestInfo, 0, sizeof(digestInfo));
- switch(digestAlg) {
- case CSSM_ALGID_MD5:
- algId.algorithm = CSSMOID_MD5;
- break;
- case CSSM_ALGID_MD2:
- algId.algorithm = CSSMOID_MD2;
- break;
- case CSSM_ALGID_SHA1:
- algId.algorithm = CSSMOID_SHA1;
- break;
- default:
- return CSSMERR_CSP_INVALID_ALGORITHM;
- }
- nullAlgParams(algId);
- digestInfo.digest.Data = (uint8 *)msgDigest;
- digestInfo.digest.Length = digestLen;
-
- /* DER encode */
- PRErrorCode perr;
- perr = SecNssEncodeItemOdata(&digestInfo, NSS_DigestInfoTemplate,
- encodedInfo);
- if(perr) {
- logAsnErr("encode(digestInfo)", perr);
- return CSSMERR_CSP_MEMORY_ERROR;
- }
- return CSSM_OK;
-}
-