X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp diff --git a/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp b/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp deleted file mode 100644 index 5f3b68e6..00000000 --- a/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp +++ /dev/null @@ -1,1846 +0,0 @@ -/* - * Copyright (c) 2003,2011-2012,2014 Apple 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 "opensshCoding.h" -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#define sslAsn1Debug(args...) secdebug("sslAsn1", ##args) - -#ifndef NDEBUG -/* set to 1 to see all ASN related errors */ -#define LOG_ASN_ERRORS 0 -#else -#define LOG_ASN_ERRORS 0 -#endif - -#if LOG_ASN_ERRORS -#include -#include - -static void logAsnErr( - const char *op, - PRErrorCode perr) -{ - printf("Error on %s: %s\n", op, SECErrorString(perr)); -} -#else -#define logAsnErr(op, perr) -#endif /* LOG_ASN_ERRORS */ - -/* CSSM_DATA --> BIGNUM */ -BIGNUM *cssmDataToBn( - const CSSM_DATA &cdata) -{ - BIGNUM *bn = BN_new(); - BIGNUM *rtn; - - rtn = BN_bin2bn(cdata.Data, (int)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 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>= 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, - kSecAsn1RSAPublicKeyPKCS1Template, &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, - kSecAsn1RSAPublicKeyPKCS1Template, 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, - CSSM_SIZE length, - /* mallocd/returned encoded alg params for OAEP key */ - uint8 **algParams, - CSSM_SIZE *algParamLen) -{ - CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo; - PRErrorCode perr; - - memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo)); - perr = coder.decode(p, length, kSecAsn1SubjectPublicKeyInfoTemplate, - &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)) { - if(!cspCompareCssmData(oid, &CSSMOID_RSAWithOAEP)) { - sslAsn1Debug("RSAPublicKeyDecodeX509: bad OID"); - return CSSMERR_CSP_INVALID_KEY; - } - if(nssPubKeyInfo.algorithm.parameters.Data != NULL) { - CSSM_SIZE len = nssPubKeyInfo.algorithm.parameters.Length; - *algParams = (uint8 *)malloc(len); - memmove(*algParams, nssPubKeyInfo.algorithm.parameters.Data, len); - *algParamLen = len; - } - } - - /* 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, - /* encoded alg params for OAEP key */ - uint8 *algParams, - uint32 algParamsLen) -{ - CssmAutoData aData(Allocator::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; - - if(algParams) { - algId.parameters.Data = (uint8 *)algParams; - algId.parameters.Length = algParamsLen; - } - else { - /* NULL algorithm parameters */ - nullAlgParams(algId); - } - - /* DER encode */ - PRErrorCode perr; - perr = SecNssEncodeItemOdata(&nssPubKeyInfo, - kSecAsn1SubjectPublicKeyInfoTemplate, 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, kSecAsn1RSAPrivateKeyPKCS1Template, &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, kSecAsn1RSAPrivateKeyPKCS1Template, - 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, - CSSM_SIZE length, - /* mallocd/returned encoded alg params for OAEP key */ - uint8 **algParams, - CSSM_SIZE *algParamLen) -{ - NSS_PrivateKeyInfo nssPrivKeyInfo; - PRErrorCode perr; - - memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); - perr = coder.decode(p, length, kSecAsn1PrivateKeyInfoTemplate, &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)) { - if(!cspCompareCssmData(oid, &CSSMOID_RSAWithOAEP)) { - sslAsn1Debug("RSAPrivateKeyDecodePKCS8: bad OID"); - return CSSMERR_CSP_INVALID_KEY; - } - if(nssPrivKeyInfo.algorithm.parameters.Data != NULL) { - CSSM_SIZE len = nssPrivKeyInfo.algorithm.parameters.Length; - *algParams = (uint8 *)malloc(len); - memmove(*algParams, nssPrivKeyInfo.algorithm.parameters.Data, len); - *algParamLen = len; - } - } - - /* - * 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, - /* encoded alg params for OAEP key */ - uint8 *algParams, - uint32 algParamsLen) -{ - - /* First get PKCS1-style encoding */ - CssmAutoData aData(Allocator::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; - - if(algParams) { - algId.parameters.Data = (uint8 *)algParams; - algId.parameters.Length = algParamsLen; - } - else { - /* NULL algorithm parameters */ - nullAlgParams(algId); - } - - /* FIXME : attributes? */ - - uint8 vers = 0; - nssPrivKeyInfo.version.Data = &vers; - nssPrivKeyInfo.version.Length = 1; - - /* DER encode */ - PRErrorCode perr; - perr = SecNssEncodeItemOdata(&nssPrivKeyInfo, - kSecAsn1PrivateKeyInfoTemplate, 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, NULL, NULL); - case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: - return RSAPublicKeyDecodeOpenSSH1(openKey, p, length); - case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: - return RSAPublicKeyDecodeOpenSSH2(openKey, p, length); - default: - assert(0); - return CSSMERR_CSP_INTERNAL_ERROR; - } -} - -CSSM_RETURN RSAPublicKeyEncode( - RSA *openKey, - CSSM_KEYBLOB_FORMAT format, - const CssmData &descData, - 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, NULL, 0); - case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: - return RSAPublicKeyEncodeOpenSSH1(openKey, descData, encodedKey); - case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: - return RSAPublicKeyEncodeOpenSSH2(openKey, descData, 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, NULL, NULL); - case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: - return RSAPrivateKeyDecodeOpenSSH1(openKey, p, length); - default: - assert(0); - return CSSMERR_CSP_INTERNAL_ERROR; - } -} - -CSSM_RETURN RSAPrivateKeyEncode( - RSA *openKey, - CSSM_KEYBLOB_FORMAT format, - const CssmData &descData, - 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, NULL, 0); - case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: - return RSAPrivateKeyEncodeOpenSSH1(openKey, descData, encodedKey); - default: - assert(0); - return CSSMERR_CSP_INTERNAL_ERROR; - } -} - -CSSM_RETURN RSAOAEPPrivateKeyEncode( - RSA *openKey, - const CSSM_DATA *label, - CssmOwnedData &encodedKey) -{ - SecNssCoder coder; - CSSM_DATA encodedParams = {0, NULL}; - /* TBD encode the label into a RSAES-OAEP-params */ - - return RSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey, encodedParams.Data, (unsigned int)encodedParams.Length); -} - -CSSM_RETURN RSAOAEPPublicKeyEncode( - RSA *openKey, - const CSSM_DATA *label, - CssmOwnedData &encodedKey) -{ - SecNssCoder coder; - CSSM_DATA encodedParams = {0, NULL}; - /* TBD encode the label into a RSAES-OAEP-params */ - - return RSAPublicKeyEncodeX509(coder, openKey, encodedKey, encodedParams.Data, (unsigned int)encodedParams.Length); -} - -CSSM_RETURN RSAOAEPPublicKeyDecode( - RSA *openKey, - void *p, - size_t length, - /* mallocd and returned label */ - CSSM_DATA *label) -{ - SecNssCoder coder; - CSSM_RETURN crtn; - CSSM_DATA encodedParams = {0, NULL}; - - crtn = RSAPublicKeyDecodeX509(coder, openKey, p, length, &encodedParams.Data, - &encodedParams.Length); - if(crtn) { - return crtn; - } - - /* TBD - decode label from encoded alg params */ - label->Data = NULL; - label->Length = 0; - return CSSM_OK; -} - -CSSM_RETURN RSAOAEPPrivateKeyDecode( - RSA *openKey, - void *p, - size_t length, - /* mallocd and returned label */ - CSSM_DATA *label) -{ - SecNssCoder coder; - CSSM_RETURN crtn; - CSSM_DATA encodedParams = {0, NULL}; - - crtn = RSAPrivateKeyDecodePKCS8(coder, openKey, p, length, &encodedParams.Data, - &encodedParams.Length); - if(crtn) { - return crtn; - } - - /* TBD - decode label from encoded alg params */ - label->Data = NULL; - label->Length = 0; - return CSSM_OK; -} - -#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. - */ -static -CSSM_RETURN DSAPublicKeyDecodeFIPS186( - SecNssCoder &coder, - DSA *openKey, - void *p, - size_t length) -{ - NSS_DSAPublicKeyBSAFE nssPubKey; - PRErrorCode perr; - CSSM_RETURN crtn; - - memset(&nssPubKey, 0, sizeof(nssPubKey)); - perr = coder.decode(p, length, kSecAsn1DSAPublicKeyBSAFETemplate, - &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, - kSecAsn1UnsignedIntegerTemplate, - &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; -} - -static -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, kSecAsn1UnsignedIntegerTemplate, - nssPubKey.publicKey); - if(perr) { - logAsnErr("encodeItem(DSAPublicKeyBSAFE.publicKey)", perr); - return CSSMERR_CSP_MEMORY_ERROR; - } - nssPubKey.publicKey.Length *= 8; - - /* DER encode */ - SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DSAPublicKeyBSAFETemplate, - encodedKey); - return CSSM_OK; - } - catch(...) { - /* ? */ - return CSSMERR_CSP_MEMORY_ERROR; - } -} - -/* - * DSA private keys, FIPS186 format. - * Compatible with BSAFE. - */ -static -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, kSecAsn1DSAPrivateKeyBSAFETemplate, - &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, - kSecAsn1DSAPrivateKeyOctsTemplate, &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; - } -} - -static -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, kSecAsn1DSAPrivateKeyOctsTemplate, - nssPrivKey.privateKey); - - /* DER encode the whole thing */ - PRErrorCode perr; - perr = SecNssEncodeItemOdata(&nssPrivKey, - kSecAsn1DSAPrivateKeyBSAFETemplate, encodedKey); - return 0; - } - catch(...) { - /* ? */ - return CSSMERR_CSP_MEMORY_ERROR; - } -} - -/* - * DSA private keys, PKCS8/SMIME format. - */ -static -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, kSecAsn1DSAPrivateKeyPKCS8Template, - &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, - kSecAsn1UnsignedIntegerTemplate, &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; - } -} - -static -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, kSecAsn1UnsignedIntegerTemplate, - nssPrivKey.privateKey); - - /* DER encode the whole thing */ - PRErrorCode perr; - perr = SecNssEncodeItemOdata(&nssPrivKey, - kSecAsn1DSAPrivateKeyPKCS8Template, 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, kSecAsn1DSAPublicKeyX509Template, - &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, - kSecAsn1UnsignedIntegerTemplate, - &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, kSecAsn1UnsignedIntegerTemplate, - nssPubKey.publicKey); - if(perr) { - logAsnErr("encodeItem(DSAPublicKeyX509.publicKey)", perr); - return CSSMERR_CSP_MEMORY_ERROR; - } - nssPubKey.publicKey.Length *= 8; - - /* DER encode */ - SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DSAPublicKeyX509Template, - 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, kSecAsn1UnsignedIntegerTemplate, - 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, kSecAsn1DSAPrivateKeyOpensslTemplate, - &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, kSecAsn1DSAPrivateKeyOpensslTemplate, - 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); - case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: - return DSAPublicKeyDecodeOpenSSH2(openKey, p, length); - default: - assert(0); - return CSSMERR_CSP_INTERNAL_ERROR; - } -} - -CSSM_RETURN DSAPublicKeyEncode( - DSA *openKey, - CSSM_KEYBLOB_FORMAT format, - const CssmData &descData, - 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); - case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: - return DSAPublicKeyEncodeOpenSSH2(openKey, descData, 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, (unsigned)length); - case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: - return DSAPrivateKeyDecodeOpenssl(coder, openKey, p, length); - case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: - return DSAPrivateKeyDecodePKCS8(coder, openKey, p, (unsigned)length); - default: - assert(0); - return CSSMERR_CSP_INTERNAL_ERROR; - } -} - -CSSM_RETURN DSAPrivateKeyEncode( - DSA *openKey, - CSSM_KEYBLOB_FORMAT format, - const CssmData &descData, - 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, - kSecAsn1DSASignatureTemplate, 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, - kSecAsn1DSASignatureTemplate, &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, - kSecAsn1DSAAlgParamsTemplate, 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, - kSecAsn1DSAAlgParamsTemplate, &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 *** -static -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, kSecAsn1DHPrivateKeyTemplate, &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; -} - -static -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, kSecAsn1DHPrivateKeyTemplate, - 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; -} - -static -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, kSecAsn1DHPrivateKeyPKCS8Template, - &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, - kSecAsn1UnsignedIntegerTemplate, - &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; -} - -static -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, kSecAsn1UnsignedIntegerTemplate, - nssPrivKey.privateKey); - } - catch(...) { - return CSSMERR_CSP_MEMORY_ERROR; - } - - /* DER encode */ - PRErrorCode perr; - perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DHPrivateKeyPKCS8Template, - 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, kSecAsn1DHPublicKeyX509Template, - &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, - kSecAsn1UnsignedIntegerTemplate, &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, kSecAsn1UnsignedIntegerTemplate, - nssPubKey.publicKey); - /* specify length in bits */ - nssPubKey.publicKey.Length *= 8; - } - catch(...) { - return CSSMERR_CSP_MEMORY_ERROR; - } - - /* DER encode */ - PRErrorCode perr; - perr = SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DHPublicKeyX509Template, - 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, kSecAsn1DHParameterBlockTemplate, - ¶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, kSecAsn1DHParameterTemplate, - ¶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; - case CSSM_ALGID_SHA224: - algId.algorithm = CSSMOID_SHA224; - break; - case CSSM_ALGID_SHA256: - algId.algorithm = CSSMOID_SHA256; - break; - case CSSM_ALGID_SHA384: - algId.algorithm = CSSMOID_SHA384; - break; - case CSSM_ALGID_SHA512: - algId.algorithm = CSSMOID_SHA512; - 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, kSecAsn1DigestInfoTemplate, - encodedInfo); - if(perr) { - logAsnErr("encode(digestInfo)", perr); - return CSSMERR_CSP_MEMORY_ERROR; - } - return CSSM_OK; -} -