+++ /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.
- */
-
-/*
- * clNssUtils.cpp - support for libnssasn1-based ASN1 encode/decode
- */
-
-#include "clNssUtils.h"
-#include "clNameUtils.h"
-#include "CSPAttacher.h"
-#include <security_asn1/secasn1.h>
-#include <security_asn1/SecNssCoder.h>
-#include <security_asn1/nssUtils.h>
-#include <Security/keyTemplates.h>
-#include <Security/certExtensionTemplates.h>
-#include <Security/oidsalg.h>
-#include <Security/oidsattr.h>
-#include <Security/cssmapple.h>
-#include <string.h>
-
-#pragma mark ----- ArenaAllocator -----
-
-/*
- * Avoid inlining this for debuggability
- */
-void *ArenaAllocator::malloc(size_t len) throw(std::bad_alloc)
-{
- try {
- return mCoder.malloc(len);
- }
- catch (...) {
- throw std::bad_alloc();
- }
-}
-
-/* intentionally not implemented, should never be called */
-void ArenaAllocator::free(void *p) throw()
-{
- throw std::bad_alloc();
-}
-
-void *ArenaAllocator::realloc(void *p, size_t len) throw(std::bad_alloc)
-{
- throw std::bad_alloc();
-}
-
-#pragma mark ----- Malloc/Copy/Compare CSSM_DATA -----
-
-/*
- * Misc. alloc/copy with arbitrary Allocator
- */
-/* malloc d.Data, set d.Length */
-void clAllocData(
- Allocator &alloc,
- CSSM_DATA &dst,
- size_t len)
-{
- if(len == 0) {
- dst.Data = NULL;
- }
- else {
- dst.Data = (uint8 *)alloc.malloc(len);
- }
- dst.Length = len;
-}
-
-/* malloc and copy */
-void clAllocCopyData(
- Allocator &alloc,
- const CSSM_DATA &src,
- CSSM_DATA &dst)
-{
- clAllocData(alloc, dst, src.Length);
- if(dst.Length != 0) {
- memmove(dst.Data, src.Data, src.Length);
- }
-}
-
-/*
- * Compare two CSSM_DATAs (or two CSSM_OIDs), return true if identical.
- */
-bool clCompareCssmData(
- const CSSM_DATA *data1,
- const CSSM_DATA *data2)
-{
- if((data1 == NULL) || (data1->Data == NULL) ||
- (data2 == NULL) || (data2->Data == NULL) ||
- (data1->Length != data2->Length)) {
- return false;
- }
- if(data1->Length != data2->Length) {
- return false;
- }
- if(memcmp(data1->Data, data2->Data, data1->Length) == 0) {
- return true;
- }
- else {
- return false;
- }
-}
-
-#pragma mark ----- CSSM_DATA <--> uint32 -----
-
-uint32 clDataToInt(
- const CSSM_DATA &cdata,
- CSSM_RETURN toThrow) /* = CSSMERR_CL_INVALID_CERT_POINTER */
-{
- if((cdata.Length == 0) || (cdata.Data == NULL)) {
- return 0;
- }
- size_t len = cdata.Length;
- if(len > sizeof(uint32)) {
- if(toThrow == 0) {
- /* tolerate this */
- len = sizeof(uint32);
- }
- else {
- CssmError::throwMe(toThrow);
- }
- }
-
- uint32 rtn = 0;
- uint8 *cp = cdata.Data;
- for(size_t i=0; i<len; i++) {
- rtn = (rtn << 8) | *cp++;
- }
- return rtn;
-}
-
-void clIntToData(
- uint32 num,
- CSSM_DATA &cdata,
- Allocator &alloc)
-{
- uint32 len = 0;
-
- if(num < 0x100) {
- len = 1;
- }
- else if(num < 0x10000) {
- len = 2;
- }
- else if(num < 0x1000000) {
- len = 3;
- }
- else {
- len = 4;
- }
- clAllocData(alloc, cdata, len);
- uint8 *cp = &cdata.Data[len - 1];
- for(unsigned i=0; i<len; i++) {
- *cp-- = num & 0xff;
- num >>= 8;
- }
-}
-
-#pragma mark ----- CSSM_BOOL <--> CSSM_DATA -----
-/*
- * A Bool is encoded as one byte of either 0 or 0xff
- * Default of NSS boolean not present is false
- */
-CSSM_BOOL clNssBoolToCssm(
- const CSSM_DATA &nssBool)
-{
- if((nssBool.Data != NULL) && (nssBool.Data[0] == 0xff)) {
- return CSSM_TRUE;
- }
- else {
- return CSSM_FALSE;
- }
-}
-
-void clCssmBoolToNss(
- CSSM_BOOL cBool,
- CSSM_DATA &nssBool,
- Allocator &alloc)
-{
- uint32 num = cBool ? 0xff : 0;
- clIntToData(num, nssBool, alloc);
-}
-
-#pragma mark ----- Bit String manipulation -----
-
-/*
- * Adjust the length of a CSSM_DATA representing a pre-encoded
- * bit string. On entry the length field is the number of bytes
- * of data; en exit, the number if bits. Trailing zero bits
- * are counted as unused (which is how KeyUsage and NetscapeCertType
- * extensions are encoded).
- */
-void clCssmBitStringToNss(
- CSSM_DATA &b)
-{
- size_t numBits = b.Length * 8;
-
- /* start at end of bit array, scanning backwards looking
- * for the first set bit */
- bool foundSet = false;
- for(ptrdiff_t dex=b.Length-1; dex>=0; dex--) {
- unsigned bitMask = 0x01;
- uint8 byte = b.Data[dex];
- for(unsigned bdex=0; bdex<8; bdex++) {
- if(byte & bitMask) {
- foundSet = true;
- break;
- }
- else {
- bitMask <<= 1;
- numBits--;
- }
- }
- if(foundSet) {
- break;
- }
- }
- /* !foundSet --> numBits = 0 */
- assert(((numBits > 0) & foundSet) || ((numBits == 0) && !foundSet));
- b.Length = numBits;
-}
-
-/*
- * On entry, Length is bit count; on exit, a byte count.
- * The job here is to ensure that bits marked as "unused" in the
- * BER encoding are cleared. Encoding rules say they are undefined in
- * the actual encoding.
- */
-void clNssBitStringToCssm(
- CSSM_DATA &b)
-{
- CSSM_SIZE byteCount = (b.Length + 7) / 8;
- unsigned partialBits = b.Length & 0x7;
- b.Length = byteCount;
- if(partialBits == 0) {
- return;
- }
-
- /* mask off unused bits */
- unsigned unusedBits = 8 - partialBits;
- uint8 *bp = b.Data + b.Length - 1;
- /* mask = (2 ** unusedBits) - 1 */
- unsigned mask = (1 << unusedBits) - 1;
- *bp &= ~mask;
-}
-
-#pragma mark ----- NSS array manipulation -----
-/*
- * How many items in a NULL-terminated array of pointers?
- */
-unsigned clNssArraySize(
- const void **array)
-{
- unsigned count = 0;
- if (array) {
- while (*array++) {
- count++;
- }
- }
- return count;
-}
-
-/* malloc a NULL-ed array of pointers of size num+1 */
-void **clNssNullArray(
- uint32 num,
- SecNssCoder &coder)
-{
- unsigned len = (num + 1) * sizeof(void *);
- void **p = (void **)coder.malloc(len);
- memset(p, 0, len);
- return p;
-}
-
-/*
- * GIven a CSSM_DATA containing a decoded BIT_STRING,
- * convert to a KeyUsage.
- */
-CE_KeyUsage clBitStringToKeyUsage(
- const CSSM_DATA &cdata)
-{
- size_t toCopy = (cdata.Length + 7) / 8;
- if(toCopy > 2) {
- /* I hope I never see this... */
- clErrorLog("clBitStringToKeyUsage: KeyUsage larger than 2 bytes!");
- toCopy = 2;
- }
- unsigned char bits[2] = {0, 0};
- memmove(bits, cdata.Data, toCopy);
- CE_KeyUsage usage = (((unsigned)bits[0]) << 8) | bits[1];
- return usage;
-}
-
-CSSM_ALGORITHMS CL_oidToAlg(
- const CSSM_OID &oid)
-{
- CSSM_ALGORITHMS alg;
- bool found = cssmOidToAlg(&oid, &alg);
- if(!found) {
- clErrorLog("CL_oidToAlg: unknown alg\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
- return alg;
-}
-
-#pragma mark ----- copy CSSM_X509_ALGORITHM_IDENTIFIER -----
-
-/*
- * Copy CSSM_X509_ALGORITHM_IDENTIFIER, same format (NSS and CSSM).
- */
-void CL_copyAlgId(
- const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId,
- CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId,
- Allocator &alloc)
-{
- clAllocCopyData(alloc, srcAlgId.algorithm, dstAlgId.algorithm);
- clAllocCopyData(alloc, srcAlgId.parameters, dstAlgId.parameters);
-}
-
-void CL_freeCssmAlgId(
- CSSM_X509_ALGORITHM_IDENTIFIER *cdsaObj, // optional
- Allocator &alloc)
-{
- if(cdsaObj == NULL) {
- return;
- }
- alloc.free(cdsaObj->algorithm.Data);
- alloc.free(cdsaObj->parameters.Data);
- memset(cdsaObj, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER));
-}
-
-
-#pragma mark ----- CSSM_X509_TIME <--> NSS format -----
-
-/*
- * Map the tag associated with a choice of DirectoryString elements to
- * a template array for encoding/decoding that string type.
- * Contrary to RFC2459, we allow the IA5String type, which is actually
- * used in the real world (cf. the email address in Thawte's serverbasic
- * cert).
- */
-
-/* The template chooser does the work here */
-
-bool CL_nssTimeToCssm(
- const NSS_TaggedItem &nssTime,
- CSSM_X509_TIME &cssmObj,
- Allocator &alloc)
-{
- cssmObj.timeType = nssTime.tag;
- clAllocCopyData(alloc, nssTime.item, cssmObj.time);
- return true;
-}
-
-/*
- * CSSM time to NSS time.
- */
-void CL_cssmTimeToNss(
- const CSSM_X509_TIME &cssmTime,
- NSS_TaggedItem &nssTime,
- SecNssCoder &coder)
-{
- nssTime.tag = cssmTime.timeType;
- coder.allocCopyItem(cssmTime.time, nssTime.item);
-}
-
-void CL_freeCssmTime(
- CSSM_X509_TIME *cssmTime,
- Allocator &alloc)
-{
- if(cssmTime == NULL) {
- return;
- }
- if(cssmTime->time.Data) {
- alloc.free(cssmTime->time.Data);
- }
- memset(cssmTime, 0, sizeof(CSSM_X509_TIME));
-}
-
-
-#pragma mark ----- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO <--> CSSM_KEY -----
-
-/*
- * Copy a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO.
- *
- * Same format (NSS and CSSM), EXCEPT:
- *
- * Objects which have just been NSS decoded or are about to be
- * NSS encoded have the subjectPublicKey.Length field in BITS
- * since this field is wrapped in a BIT STRING upon encoding.
- *
- * Caller tells us which format (bits or bytes)
- * to use for each of {src, dst}.
- */
-void CL_copySubjPubKeyInfo(
- const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &srcInfo,
- bool srcInBits,
- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstInfo,
- bool dstInBits,
- Allocator &alloc)
-{
- CL_copyAlgId(srcInfo.algorithm, dstInfo.algorithm, alloc);
-
- CSSM_DATA srcKey = srcInfo.subjectPublicKey;
- if(srcInBits) {
- srcKey.Length = (srcKey.Length + 7) / 8;
- }
- clAllocCopyData(alloc, srcKey, dstInfo.subjectPublicKey);
- if(dstInBits) {
- dstInfo.subjectPublicKey.Length *= 8;
- }
-}
-
-/*
- * Obtain a CSSM_KEY from a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO,
- * inferring as much as we can from required fields
- * (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO) and extensions (for
- * KeyUse, obtained from the optional DecodedCert).
- */
-CSSM_KEY_PTR CL_extractCSSMKeyNSS(
- const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &keyInfo,
- Allocator &alloc,
- const DecodedCert *decodedCert) // optional
-{
- CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR) alloc.malloc(sizeof(CSSM_KEY));
- memset(cssmKey, 0, sizeof(CSSM_KEY));
- CSSM_KEYHEADER &hdr = cssmKey->KeyHeader;
- CssmRemoteData keyData(alloc, cssmKey->KeyData);
-
- hdr.HeaderVersion = CSSM_KEYHEADER_VERSION;
- /* CspId blank */
- hdr.BlobType = CSSM_KEYBLOB_RAW;
- hdr.AlgorithmId = CL_oidToAlg(keyInfo.algorithm.algorithm);
- hdr.KeyAttr = CSSM_KEYATTR_MODIFIABLE | CSSM_KEYATTR_EXTRACTABLE;
-
- /*
- * Format inferred from AlgorithmId. I have never seen these defined
- * anywhere, e.g., what's the format of an RSA public key in a cert?
- * X509 certainly doesn't say. However. the following two cases are
- * known to be correct.
- */
- switch(hdr.AlgorithmId) {
- case CSSM_ALGID_RSA:
- hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
- break;
- case CSSM_ALGID_DSA:
- case CSSM_ALGID_ECDSA:
- case CSSM_ALGID_DH:
- case CSSM_ALGMODE_PKCS1_EME_OAEP:
- hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_X509;
- break;
- case CSSM_ALGID_FEE:
- /* CSSM_KEYBLOB_RAW_FORMAT_NONE --> DER encoded */
- hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
- break;
- default:
- /* punt */
- hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
- }
- hdr.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
-
- /* KeyUsage inferred from extensions */
- if(decodedCert) {
- hdr.KeyUsage = decodedCert->inferKeyUsage();
- }
- else {
- hdr.KeyUsage = CSSM_KEYUSE_ANY;
- }
-
- /* start/end date unknown, leave zero */
- hdr.WrapAlgorithmId = CSSM_ALGID_NONE;
- hdr.WrapMode = CSSM_ALGMODE_NONE;
-
- switch(hdr.AlgorithmId) {
- case CSSM_ALGID_DSA:
- case CSSM_ALGID_ECDSA:
- case CSSM_ALGID_DH:
- case CSSM_ALGMODE_PKCS1_EME_OAEP:
- {
- /*
- * Just encode the whole subject public key info blob.
- * NOTE we're assuming that the keyInfo.subjectPublicKey
- * field is in the NSS_native BITSTRING format, i.e.,
- * its Length field is in bits and we don't have to adjust.
- */
- PRErrorCode prtn = SecNssEncodeItemOdata(&keyInfo,
- kSecAsn1SubjectPublicKeyInfoTemplate, keyData);
- if(prtn) {
- clErrorLog("extractCSSMKey: error on reencode\n");
- CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
- }
- break;
- }
- default:
- /*
- * RSA, FEE for now.
- * keyInfo.subjectPublicKey (in BITS) ==> KeyData
- */
- keyData.copy(keyInfo.subjectPublicKey.Data,
- (keyInfo.subjectPublicKey.Length + 7) / 8);
- }
-
- /*
- * LogicalKeySizeInBits - ask the CSP
- */
- CSSM_CSP_HANDLE cspHand = getGlobalCspHand(true);
- CSSM_KEY_SIZE keySize;
- CSSM_RETURN crtn;
- crtn = CSSM_QueryKeySizeInBits(cspHand, CSSM_INVALID_HANDLE, cssmKey,
- &keySize);
- switch(crtn) {
- default:
- CssmError::throwMe(crtn);
- case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE:
- /*
- * This is how the CSP indicates a "partial" public key,
- * with a valid public key value but no alg-specific
- * parameters (currently, DSA only).
- */
- hdr.KeyAttr |= CSSM_KEYATTR_PARTIAL;
- /* and drop thru */
- case CSSM_OK:
- cssmKey->KeyHeader.LogicalKeySizeInBits =
- keySize.LogicalKeySizeInBits;
- break;
- }
-
- keyData.release();
- return cssmKey;
-}
-
-/*
- * Set up a encoded NULL for CSSM_X509_ALGORITHM_IDENTIFIER.parameters.
- */
-void CL_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;
-}
-
-/*
- * Convert a CSSM_KEY to a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO. The
- * CSSM key must be in raw format and with a specific blob format.
- * -- RSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_PKCS1
- * -- DSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509
- * -- ECDSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509
- */
-void CL_CSSMKeyToSubjPubKeyInfoNSS(
- const CSSM_KEY &cssmKey,
- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &nssKeyInfo,
- SecNssCoder &coder)
-{
- const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
- if(hdr.BlobType != CSSM_KEYBLOB_RAW) {
- clErrorLog("CL SetField: must specify RAW key blob\n");
- CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
- }
- memset(&nssKeyInfo, 0, sizeof(nssKeyInfo));
-
- /* algorithm and format dependent from here... */
- switch(hdr.AlgorithmId) {
- case CSSM_ALGID_RSA:
- if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
- clErrorLog("CL SetField: RSA key must be in PKCS1 format\n");
- CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
- }
- /* and fall thru */
- default:
- {
- /* Key header's algorithm --> OID */
- const CSSM_OID *oid = cssmAlgToOid(hdr.AlgorithmId);
- if(oid == NULL) {
- clErrorLog("CL SetField: Unknown key algorithm\n");
- CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
- }
- CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssKeyInfo.algorithm;
- coder.allocCopyItem(*oid, algId.algorithm);
-
- /* NULL algorithm parameters, always in this case */
- CL_nullAlgParams(algId);
-
- /* Copy key bits, destination is a BIT STRING */
- coder.allocCopyItem(cssmKey.KeyData, nssKeyInfo.subjectPublicKey);
- nssKeyInfo.subjectPublicKey.Length *= 8;
- break;
- }
- case CSSM_ALGID_DSA:
- case CSSM_ALGID_ECDSA:
- if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_X509) {
- clErrorLog("CL SetField: DSA/ECDSA key must be in X509 format\n");
- CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
- }
-
- /*
- * All we do is decode the whole key blob into the
- * SubjectPublicKeyInfo.
- */
- if(coder.decodeItem(cssmKey.KeyData,
- kSecAsn1SubjectPublicKeyInfoTemplate,
- &nssKeyInfo)) {
- clErrorLog("CL SetField: Error decoding DSA public key\n");
- CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
- }
- break;
- }
-}
-
-void CL_freeCSSMKey(
- CSSM_KEY_PTR cssmKey,
- Allocator &alloc,
- bool freeTop)
-{
- if(cssmKey == NULL) {
- return;
- }
- alloc.free(cssmKey->KeyData.Data);
- memset(cssmKey, 0, sizeof(CSSM_KEY));
- if(freeTop) {
- alloc.free(cssmKey);
- }
-}
-
-#pragma mark ----- CE_AuthorityKeyID <--> NSS_AuthorityKeyId -----
-
-void CL_cssmAuthorityKeyIdToNss(
- const CE_AuthorityKeyID &cdsaObj,
- NSS_AuthorityKeyId &nssObj,
- SecNssCoder &coder)
-{
- memset(&nssObj, 0, sizeof(nssObj));
- if(cdsaObj.keyIdentifierPresent) {
- nssObj.keyIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA));
- coder.allocCopyItem(cdsaObj.keyIdentifier, *nssObj.keyIdentifier);
- }
- if(cdsaObj.generalNamesPresent ) {
- /* GeneralNames, the hard one */
- CL_cssmGeneralNamesToNss(*cdsaObj.generalNames,
- nssObj.genNames, coder);
- }
- if(cdsaObj.serialNumberPresent) {
- coder.allocCopyItem(cdsaObj.serialNumber,nssObj.serialNumber);
- }
-}
-
-void CL_nssAuthorityKeyIdToCssm(
- const NSS_AuthorityKeyId &nssObj,
- CE_AuthorityKeyID &cdsaObj,
- SecNssCoder &coder, // for temp decoding
- Allocator &alloc)
-{
- if(nssObj.keyIdentifier != NULL) {
- cdsaObj.keyIdentifierPresent = CSSM_TRUE;
- clAllocCopyData(alloc, *nssObj.keyIdentifier, cdsaObj.keyIdentifier);
- }
- if(nssObj.genNames.names != NULL) {
- /* GeneralNames, the hard one */
- cdsaObj.generalNamesPresent = CSSM_TRUE;
- cdsaObj.generalNames =
- (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralNames));
- CL_nssGeneralNamesToCssm(nssObj.genNames,
- *cdsaObj.generalNames,
- coder,
- alloc);
- }
- if(nssObj.serialNumber.Data != NULL) {
- cdsaObj.serialNumberPresent = CSSM_TRUE;
- clAllocCopyData(alloc, nssObj.serialNumber, cdsaObj.serialNumber);
- }
-}
-
-#pragma mark ----- CE_AuthorityInfoAccess <--> NSS_AuthorityInfoAccess -----
-
-void CL_cssmInfoAccessToNss(
- const CE_AuthorityInfoAccess &cdsaObj,
- NSS_AuthorityInfoAccess &nssObj,
- SecNssCoder &coder)
-{
- memset(&nssObj, 0, sizeof(nssObj));
- uint32 numDescs = cdsaObj.numAccessDescriptions;
- nssObj.accessDescriptions = (NSS_AccessDescription **)clNssNullArray(numDescs, coder);
-
- for(unsigned dex=0; dex<numDescs; dex++) {
- nssObj.accessDescriptions[dex] = coder.mallocn<NSS_AccessDescription>();
- CE_AccessDescription *src = &cdsaObj.accessDescriptions[dex];
- NSS_AccessDescription *dst = nssObj.accessDescriptions[dex];
- coder.allocCopyItem(src->accessMethod, dst->accessMethod);
-
- /* Convert general name, then encode it into destination */
- NSS_GeneralName nssGenName;
- CL_cssmGeneralNameToNss(src->accessLocation, nssGenName, coder);
- PRErrorCode prtn = coder.encodeItem(&nssGenName, kSecAsn1GeneralNameTemplate,
- dst->encodedAccessLocation);
- if(prtn) {
- clErrorLog("CL_cssmInfoAccessToNss: encode error\n");
- CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
- }
- }
-}
-
-void CL_infoAccessToCssm(
- const NSS_AuthorityInfoAccess &nssObj,
- CE_AuthorityInfoAccess &cdsaObj,
- SecNssCoder &coder, // for temp decoding
- Allocator &alloc)
-{
- memset(&cdsaObj, 0, sizeof(cdsaObj));
- unsigned numDescs = clNssArraySize((const void **)nssObj.accessDescriptions);
- if(numDescs == 0) {
- return;
- }
- cdsaObj.accessDescriptions = (CE_AccessDescription *)alloc.malloc(
- numDescs * sizeof(CE_AccessDescription));
- cdsaObj.numAccessDescriptions = numDescs;
- for(unsigned dex=0; dex<numDescs; dex++) {
- CE_AccessDescription *dst = &cdsaObj.accessDescriptions[dex];
- NSS_AccessDescription *src = nssObj.accessDescriptions[dex];
- clAllocCopyData(alloc, src->accessMethod, dst->accessMethod);
-
- /* decode the general name */
- NSS_GeneralName nssGenName;
- memset(&nssGenName, 0, sizeof(nssGenName));
- PRErrorCode prtn = coder.decodeItem(src->encodedAccessLocation,
- kSecAsn1GeneralNameTemplate, &nssGenName);
- if(prtn) {
- clErrorLog("***Error decoding NSS_AuthorityInfoAccess.accessLocation\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
-
- /* then convert the result to CSSM */
- CL_nssGeneralNameToCssm(nssGenName, dst->accessLocation, coder, alloc);
- }
-}
-
-void CL_freeInfoAccess(
- CE_AuthorityInfoAccess &cssmInfo,
- Allocator &alloc)
-{
- uint32 numDescs = cssmInfo.numAccessDescriptions;
- for(unsigned dex=0; dex<numDescs; dex++) {
- CE_AccessDescription *dst = &cssmInfo.accessDescriptions[dex];
- alloc.free(dst->accessMethod.Data);
- CL_freeCssmGeneralName(dst->accessLocation, alloc);
- }
- alloc.free(cssmInfo.accessDescriptions);
-}
-
-
-#pragma mark ----- CE_QC_Statements <--> NSS_QC_Statements -----
-
-void CL_cssmQualCertStatementsToNss(
- const CE_QC_Statements &cdsaObj,
- NSS_QC_Statements &nssObj,
- SecNssCoder &coder)
-{
- memset(&nssObj, 0, sizeof(nssObj));
- uint32 numQcs = cdsaObj.numQCStatements;
- nssObj.qcStatements =
- (NSS_QC_Statement **)clNssNullArray(numQcs, coder);
- for(uint32 dex=0; dex<numQcs; dex++) {
- nssObj.qcStatements[dex] = (NSS_QC_Statement *)
- coder.malloc(sizeof(NSS_QC_Statement));
- NSS_QC_Statement *dst = nssObj.qcStatements[dex];
- CE_QC_Statement *src = &cdsaObj.qcStatements[dex];
- memset(dst, 0, sizeof(*dst));
- coder.allocCopyItem(src->statementId, dst->statementId);
- if(src->semanticsInfo) {
- if(src->otherInfo) {
- /* this is either/or, not both */
- CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
- }
-
- /* encode this CE_SemanticsInformation */
- CE_SemanticsInformation *srcSI = src->semanticsInfo;
- NSS_SemanticsInformation dstSI;
- memset(&dstSI, 0, sizeof(dstSI));
- if(srcSI->semanticsIdentifier) {
- dstSI.semanticsIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA));
- coder.allocCopyItem(*srcSI->semanticsIdentifier,
- *dstSI.semanticsIdentifier);
- }
- if(srcSI->nameRegistrationAuthorities) {
- dstSI.nameRegistrationAuthorities =
- (NSS_GeneralNames *)coder.malloc(sizeof(NSS_GeneralNames));
- CL_cssmGeneralNamesToNss(*srcSI->nameRegistrationAuthorities,
- *dstSI.nameRegistrationAuthorities, coder);
- }
- PRErrorCode prtn = coder.encodeItem(&dstSI, kSecAsn1SemanticsInformationTemplate,
- dst->info);
- if(prtn) {
- clErrorLog("CL_cssmQualCertStatementsToNss: encode error\n");
- CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
- }
-
- }
- if(src->otherInfo) {
- /* drop in as ASN_ANY */
- coder.allocCopyItem(*src->otherInfo, dst->info);
- }
- }
-}
-
-void CL_qualCertStatementsToCssm(
- const NSS_QC_Statements &nssObj,
- CE_QC_Statements &cdsaObj,
- SecNssCoder &coder, // for temp decoding
- Allocator &alloc)
-{
- memset(&cdsaObj, 0, sizeof(cdsaObj));
- unsigned numQcs = clNssArraySize((const void **)nssObj.qcStatements);
- if(numQcs == 0) {
- return;
- }
- cdsaObj.qcStatements = (CE_QC_Statement *)alloc.malloc(
- numQcs * sizeof(CE_AccessDescription));
- cdsaObj.numQCStatements = numQcs;
- for(unsigned dex=0; dex<numQcs; dex++) {
- CE_QC_Statement *dst = &cdsaObj.qcStatements[dex];
- NSS_QC_Statement *src = nssObj.qcStatements[dex];
-
- memset(dst, 0, sizeof(*dst));
- clAllocCopyData(alloc, src->statementId, dst->statementId);
-
- /*
- * Whether the optional info is a SemanticsInformation or is uninterpreted
- * DER data depends on statementId.
- */
- if(src->info.Data) {
- if(clCompareCssmData(&src->statementId, &CSSMOID_OID_QCS_SYNTAX_V2)) {
- NSS_SemanticsInformation srcSI;
- memset(&srcSI, 0, sizeof(srcSI));
-
- /* decode info as a NSS_SemanticsInformation */
- PRErrorCode prtn = coder.decodeItem(src->info,
- kSecAsn1SemanticsInformationTemplate, &srcSI);
- if(prtn) {
- clErrorLog("***Error decoding CE_SemanticsInformation\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
-
- /* NSS_SemanticsInformation --> CE_SemanticsInformation */
- dst->semanticsInfo =
- (CE_SemanticsInformation *)alloc.malloc(sizeof(CE_SemanticsInformation));
- CE_SemanticsInformation *dstSI = dst->semanticsInfo;
- memset(dstSI, 0, sizeof(*dstSI));
- if(srcSI.semanticsIdentifier) {
- dstSI->semanticsIdentifier = (CSSM_OID *)alloc.malloc(sizeof(CSSM_OID));
- clAllocCopyData(alloc, *srcSI.semanticsIdentifier, *dstSI->semanticsIdentifier);
- }
- if(srcSI.nameRegistrationAuthorities) {
- dstSI->nameRegistrationAuthorities =
- (CE_NameRegistrationAuthorities *)alloc.malloc(
- sizeof(CE_NameRegistrationAuthorities));
- CL_nssGeneralNamesToCssm(*srcSI.nameRegistrationAuthorities,
- *dstSI->nameRegistrationAuthorities,
- coder,
- alloc);
- }
- }
- else {
- dst->otherInfo = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA));
- clAllocCopyData(alloc, src->info, *dst->otherInfo);
- }
- }
- }
-}
-
-void CL_freeQualCertStatements(
- CE_QC_Statements &cssmQCs,
- Allocator &alloc)
-{
- uint32 numQCs = cssmQCs.numQCStatements;
- for(unsigned dex=0; dex<numQCs; dex++) {
- CE_QC_Statement *dst = &cssmQCs.qcStatements[dex];
- alloc.free(dst->statementId.Data);
- if(dst->semanticsInfo) {
- CE_SemanticsInformation *si = dst->semanticsInfo;
- if(si->semanticsIdentifier) {
- alloc.free(si->semanticsIdentifier->Data);
- alloc.free(si->semanticsIdentifier);
- }
- if(si->nameRegistrationAuthorities) {
- CL_freeCssmGeneralNames(si->nameRegistrationAuthorities, alloc);
- alloc.free(si->nameRegistrationAuthorities);
- }
- alloc.free(si);
- }
- if(dst->otherInfo) {
- alloc.free(dst->otherInfo->Data);
- alloc.free(dst->otherInfo);
- }
- }
- alloc.free(cssmQCs.qcStatements);
-}
-
-#pragma mark ----- decode/encode CE_DistributionPointName -----
-
-/* This is always a DER-encoded blob at the NSS level */
-void CL_decodeDistributionPointName(
- const CSSM_DATA &nssBlob,
- CE_DistributionPointName &cssmDpn,
- SecNssCoder &coder,
- Allocator &alloc)
-{
- memset(&cssmDpn, 0, sizeof(CE_DistributionPointName));
- if(nssBlob.Length == 0) {
- clErrorLog("***CL_decodeDistributionPointName: bad PointName\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
- unsigned char tag = nssBlob.Data[0] & SEC_ASN1_TAGNUM_MASK;
- switch(tag) {
- case NSS_DIST_POINT_FULL_NAME_TAG:
- {
- /* decode to temp coder memory */
- NSS_GeneralNames gnames;
- gnames.names = NULL;
- if(coder.decodeItem(nssBlob, kSecAsn1DistPointFullNameTemplate,
- &gnames)) {
- clErrorLog("***Error decoding DistPointFullName\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
-
- cssmDpn.nameType = CE_CDNT_FullName;
- cssmDpn.dpn.fullName = (CE_GeneralNames *)alloc.malloc(
- sizeof(CE_GeneralNames));
-
- /* copy out to caller */
- CL_nssGeneralNamesToCssm(gnames,
- *cssmDpn.dpn.fullName, coder, alloc);
- break;
- }
- case NSS_DIST_POINT_RDN_TAG:
- {
- /* decode to temp coder memory */
- NSS_RDN rdn;
- memset(&rdn, 0, sizeof(rdn));
- if(coder.decodeItem(nssBlob, kSecAsn1DistPointRDNTemplate,
- &rdn)) {
- clErrorLog("***Error decoding DistPointRDN\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
-
- cssmDpn.nameType = CE_CDNT_NameRelativeToCrlIssuer;
- cssmDpn.dpn.rdn = (CSSM_X509_RDN_PTR)alloc.malloc(
- sizeof(CSSM_X509_RDN));
-
- /* copy out to caller */
- CL_nssRdnToCssm(rdn, *cssmDpn.dpn.rdn, alloc, coder);
- break;
- }
- default:
- clErrorLog("***Bad CE_DistributionPointName tag\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
-}
-
-void CL_encodeDistributionPointName(
- CE_DistributionPointName &cpoint,
- CSSM_DATA &npoint,
- SecNssCoder &coder)
-{
- const SecAsn1Template *templ = NULL;
- NSS_GeneralNames gnames;
- NSS_RDN rdn;
- void *encodeSrc = NULL;
-
- /*
- * Our job is to convert one of two incoming aggregate types
- * into NSS format, then encode the result into npoint.
- */
- switch(cpoint.nameType) {
- case CE_CDNT_FullName:
- CL_cssmGeneralNamesToNss(*cpoint.dpn.fullName,
- gnames, coder);
- encodeSrc = &gnames;
- templ = kSecAsn1DistPointFullNameTemplate;
- break;
-
- case CE_CDNT_NameRelativeToCrlIssuer:
- CL_cssmRdnToNss(*cpoint.dpn.rdn, rdn, coder);
- encodeSrc = &rdn;
- templ = kSecAsn1DistPointRDNTemplate;
- break;
- default:
- clErrorLog("CL_encodeDistributionPointName: bad nameType\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
- }
- if(coder.encodeItem(encodeSrc, templ, npoint)) {
- clErrorLog("CL_encodeDistributionPointName: encode error\n");
- CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
- }
-}
-
-
-#pragma mark --- CE_CRLDistPointsSyntax <--> NSS_CRLDistributionPoints ---
-
-void CL_cssmDistPointsToNss(
- const CE_CRLDistPointsSyntax &cdsaObj,
- NSS_CRLDistributionPoints &nssObj,
- SecNssCoder &coder)
-{
- memset(&nssObj, 0, sizeof(nssObj));
- unsigned numPoints = cdsaObj.numDistPoints;
- if(numPoints == 0) {
- return;
- }
- nssObj.distPoints =
- (NSS_DistributionPoint **)clNssNullArray(numPoints, coder);
- for(unsigned dex=0; dex<numPoints; dex++) {
- nssObj.distPoints[dex] = (NSS_DistributionPoint *)
- coder.malloc(sizeof(NSS_DistributionPoint));
- NSS_DistributionPoint *npoint = nssObj.distPoints[dex];
- memset(npoint, 0, sizeof(NSS_DistributionPoint));
- CE_CRLDistributionPoint *cpoint = &cdsaObj.distPoints[dex];
-
- /* all fields are optional */
- if(cpoint->distPointName) {
- /* encode and drop into ASN_ANY slot */
- npoint->distPointName = (CSSM_DATA *)
- coder.malloc(sizeof(CSSM_DATA));
- CL_encodeDistributionPointName(*cpoint->distPointName,
- *npoint->distPointName, coder);
-
- }
-
- if(cpoint->reasonsPresent) {
- /* bit string, presumed max length 8 bits */
- coder.allocItem(npoint->reasons, 1);
- npoint->reasons.Data[0] = cpoint->reasons;
- /* adjust for bit string length */
- npoint->reasons.Length = 8;
- }
-
- if(cpoint->crlIssuer) {
- CL_cssmGeneralNamesToNss(*cpoint->crlIssuer,
- npoint->crlIssuer, coder);
- }
- }
-}
-
-void CL_nssDistPointsToCssm(
- const NSS_CRLDistributionPoints &nssObj,
- CE_CRLDistPointsSyntax &cdsaObj,
- SecNssCoder &coder, // for temp decoding
- Allocator &alloc)
-{
- memset(&cdsaObj, 0, sizeof(cdsaObj));
- unsigned numPoints = clNssArraySize((const void **)nssObj.distPoints);
- if(numPoints == 0) {
- return;
- }
-
- unsigned len = sizeof(CE_CRLDistributionPoint) * numPoints;
- cdsaObj.distPoints = (CE_CRLDistributionPoint *)alloc.malloc(len);
- memset(cdsaObj.distPoints, 0, len);
- cdsaObj.numDistPoints = numPoints;
-
- for(unsigned dex=0; dex<numPoints; dex++) {
- CE_CRLDistributionPoint &cpoint = cdsaObj.distPoints[dex];
- NSS_DistributionPoint &npoint = *(nssObj.distPoints[dex]);
-
- /* All three fields are optional */
- if(npoint.distPointName != NULL) {
- /* Drop in a CE_DistributionPointName */
- CE_DistributionPointName *cname =
- (CE_DistributionPointName *)alloc.malloc(
- sizeof(CE_DistributionPointName));
- memset(cname, 0, sizeof(*cname));
- cpoint.distPointName = cname;
-
- /*
- * This one is currently still encoded; we have to peek
- * at its tag and decode accordingly.
- */
- CL_decodeDistributionPointName(*npoint.distPointName,
- *cname, coder, alloc);
- }
-
- if(npoint.reasons.Data != NULL) {
- /* careful, it's a bit string */
- if(npoint.reasons.Length > 8) {
- clErrorLog("***CL_nssDistPointsToCssm: Malformed reasons\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
- cpoint.reasonsPresent = CSSM_TRUE;
- if(npoint.reasons.Length != 0) {
- cpoint.reasons = npoint.reasons.Data[0];
- }
- }
-
- if(npoint.crlIssuer.names != NULL) {
- /* Cook up a new CE_GeneralNames */
- cpoint.crlIssuer =
- (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralNames));
- CL_nssGeneralNamesToCssm(npoint.crlIssuer, *cpoint.crlIssuer,
- coder, alloc);
- }
- }
-}
-
-#pragma mark ----- IssuingDistributionPoint -----
-
-void CL_nssIssuingDistPointToCssm(
- NSS_IssuingDistributionPoint *nssIdp,
- CE_IssuingDistributionPoint *cssmIdp,
- SecNssCoder &coder,
- Allocator &alloc)
-{
- /* All fields optional */
- memset(cssmIdp, 0, sizeof(*cssmIdp));
- if(nssIdp->distPointName) {
- CE_DistributionPointName *cssmDp = (CE_DistributionPointName *)
- alloc.malloc(sizeof(CE_DistributionPointName));
-
- /*
- * This one is currently still encoded; we have to peek
- * at its tag and decode accordingly.
- */
- CL_decodeDistributionPointName(*nssIdp->distPointName,
- *cssmDp, coder, alloc);
- cssmIdp->distPointName = cssmDp;
- }
- if(nssIdp->onlyUserCerts) {
- cssmIdp->onlyUserCertsPresent = CSSM_TRUE;
- cssmIdp->onlyUserCerts = clNssBoolToCssm(*nssIdp->onlyUserCerts);
- }
- if(nssIdp->onlyCACerts) {
- cssmIdp->onlyCACertsPresent = CSSM_TRUE;
- cssmIdp->onlyCACerts = clNssBoolToCssm(*nssIdp->onlyCACerts);
- }
- if(nssIdp->onlySomeReasons) {
- cssmIdp->onlySomeReasonsPresent = CSSM_TRUE;
- if(nssIdp->onlySomeReasons->Length > 0) {
- cssmIdp->onlySomeReasons = *nssIdp->onlySomeReasons->Data;
- }
- else {
- cssmIdp->onlySomeReasons = 0;
- }
- }
- if(nssIdp->indirectCRL) {
- cssmIdp->indirectCrlPresent = CSSM_TRUE;
- cssmIdp->indirectCrl = clNssBoolToCssm(*nssIdp->indirectCRL);
- }
-}
-
-#pragma mark --- CE_NameConstraints <--> NSS_NameConstraints ---
-
-void CL_cssmNameConstraintsToNss(
- const CE_NameConstraints &cdsaObj,
- NSS_NameConstraints &nssObj,
- SecNssCoder &coder)
-{
- //%%%FIXME tba
-}
-
-void CL_nssNameConstraintsToCssm(
- const NSS_NameConstraints &nssObj,
- CE_NameConstraints &cdsaObj,
- SecNssCoder &coder, // for temp decoding
- Allocator &alloc)
-{
- //%%%FIXME tba
-}
-
-void CL_freeCssmNameConstraints(
- CE_NameConstraints *cssmNcs,
- Allocator &alloc)
-{
- if(cssmNcs == NULL) {
- return;
- }
-//%%%FIXME need to add a CL_freeCssmGeneralSubtrees function to clNameUtils{.h,.cpp}
-#if 0
- switch(cssmDpn->nameType) {
- case CE_CDNT_FullName:
- CL_freeCssmGeneralNames(cssmDpn->dpn.fullName, alloc);
- alloc.free(cssmDpn->dpn.fullName);
- break;
- case CE_CDNT_NameRelativeToCrlIssuer:
- CL_freeX509Rdn(cssmDpn->dpn.rdn, alloc);
- alloc.free(cssmDpn->dpn.rdn);
- break;
- }
-#endif
- memset(cssmNcs, 0, sizeof(*cssmNcs));
-}
-
-#pragma mark --- CE_PolicyMappings <--> NSS_PolicyMappings ---
-
-void CL_cssmPolicyMappingsToNss(
- const CE_PolicyMappings &cdsaObj,
- NSS_PolicyMappings &nssObj,
- SecNssCoder &coder)
-{
- //%%%FIXME tba
-}
-
-void CL_nssPolicyMappingsToCssm(
- const NSS_PolicyMappings &nssObj,
- CE_PolicyMappings &cdsaObj,
- SecNssCoder &coder, // for temp decoding
- Allocator &alloc)
-{
- //%%%FIXME tba
-}
-
-void CL_freeCssmPolicyMappings(
- CE_PolicyMappings *cssmPms,
- Allocator &alloc)
-{
- if(cssmPms == NULL) {
- return;
- }
- //%%%FIXME tba
-
- memset(cssmPms, 0, sizeof(*cssmPms));
-}
-
-#pragma mark --- CE_PolicyConstraints <--> NSS_PolicyConstraints ---
-
-void CL_cssmPolicyConstraintsToNss(
- const CE_PolicyConstraints *cdsaObj,
- NSS_PolicyConstraints *nssObj,
- SecNssCoder &coder)
-{
- //%%%FIXME tba
-}
-
-void CL_nssPolicyConstraintsToCssm(
- const NSS_PolicyConstraints *nssObj,
- CE_PolicyConstraints *cdsaObj,
- SecNssCoder &coder, // for temp decoding
- Allocator &alloc)
-{
- memset(cdsaObj, 0, sizeof(*cdsaObj));
- if(nssObj->requireExplicitPolicy.Data) {
- cdsaObj->requireExplicitPolicyPresent = CSSM_TRUE;
- cdsaObj->inhibitPolicyMapping = clDataToInt(
- nssObj->requireExplicitPolicy, 0);
- }
- if(nssObj->inhibitPolicyMapping.Data) {
- cdsaObj->inhibitPolicyMappingPresent = CSSM_TRUE;
- cdsaObj->inhibitPolicyMapping = clDataToInt(
- nssObj->inhibitPolicyMapping, 0);
- }
-}
-
-void CL_freeCssmPolicyConstraints(
- CE_PolicyConstraints *cssmPcs,
- Allocator &alloc)
-{
- if(cssmPcs == NULL) {
- return;
- }
-
- memset(cssmPcs, 0, sizeof(*cssmPcs));
-}
-
-
-#pragma mark ----- ECDSA_SigAlgParams support -----
-
-/*
- * Some implementations use a two-OID mechanism to specify ECDSA signature
- * algorithm with a digest of other than SHA1. This is really not necessary;
- * we use the single-OID method (e.g. CSSMOID_ECDSA_WithSHA512) when
- * encoding, but we have to accomodate externally generated items with
- * the two-OID method. This routine decodes the digest OID and infers a
- * CSSM_ALGORITHMS from it.
- * Throws CSSMERR_CL_UNKNOWN_FORMAT on any error.
- */
-CSSM_ALGORITHMS CL_nssDecodeECDSASigAlgParams(
- const CSSM_DATA &encParams,
- SecNssCoder &coder)
-{
- CSSM_X509_ALGORITHM_IDENTIFIER algParams;
- memset(&algParams, 0, sizeof(algParams));
- PRErrorCode prtn = coder.decodeItem(encParams, kSecAsn1AlgorithmIDTemplate, &algParams);
- if(prtn) {
- clErrorLog("CL_nssDecodeECDSASigAlgParams: error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
-
- /* get the digest algorithm, convert to ECDSA w/digest OID */
- CSSM_ALGORITHMS digestAlg = CL_oidToAlg(algParams.algorithm);
- switch(digestAlg) {
- case CSSM_ALGID_SHA1:
- return CSSM_ALGID_SHA1WithECDSA;
- case CSSM_ALGID_SHA224:
- return CSSM_ALGID_SHA224WithECDSA;
- case CSSM_ALGID_SHA256:
- return CSSM_ALGID_SHA256WithECDSA;
- case CSSM_ALGID_SHA384:
- return CSSM_ALGID_SHA384WithECDSA;
- case CSSM_ALGID_SHA512:
- return CSSM_ALGID_SHA512WithECDSA;
- default:
- clErrorLog("CL_nssDecodeECDSASigAlgParams: unknown digest algorithm\n");
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
-}
-
-#pragma mark ----- Top-level Cert/CRL encode and decode -----
-
-/*
- * To ensure a secure means of signing and verifying TBSCert blobs, we
- * provide these functions to encode and decode just the top-level
- * elements of a certificate. Unfortunately there is no guarantee
- * that when you decode and re-encode a TBSCert blob, you get the
- * same thing you started with (although with DER rules, as opposed
- * to BER rules, you should). Thus when signing, we sign the TBSCert
- * and encode the signed cert here without ever decoding the TBSCert (or,
- * at least, without using the decoded version to get the encoded TBS blob).
- */
-
-void CL_certCrlDecodeComponents(
- const CssmData &signedItem, // DER-encoded cert or CRL
- CssmOwnedData &tbsBlob, // still DER-encoded
- CssmOwnedData &algId, // ditto
- CssmOwnedData &rawSig) // raw bits (not an encoded AsnBits)
-{
- /* BER-decode into temp memory */
- NSS_SignedCertOrCRL nssObj;
- SecNssCoder coder;
- PRErrorCode prtn;
-
- memset(&nssObj, 0, sizeof(nssObj));
- prtn = coder.decode(signedItem.data(), signedItem.length(),
- kSecAsn1SignedCertOrCRLTemplate, &nssObj);
- if(prtn) {
- CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
- }
-
- /* tbsBlob and algId are raw ASN_ANY including tags, which we pass
- * back to caller intact */
- tbsBlob.copy(nssObj.tbsBlob.Data, nssObj.tbsBlob.Length);
- algId.copy(nssObj.signatureAlgorithm.Data,
- nssObj.signatureAlgorithm.Length);
-
- /* signature is a bit string which we do in fact decode */
- rawSig.copy(nssObj.signature.Data,
- (nssObj.signature.Length + 7) / 8);
-}
-
-
-/*
- * Given pre-DER-encoded blobs, do the final encode step for a signed cert.
- */
-void
-CL_certEncodeComponents(
- const CssmData &TBSCert, // DER-encoded
- const CssmData &algId, // ditto
- const CssmData &rawSig, // raw bits, not encoded
- CssmOwnedData &signedCert) // DER-encoded
-{
- NSS_SignedCertOrCRL nssObj;
- nssObj.tbsBlob.Data = TBSCert.Data;
- nssObj.tbsBlob.Length = TBSCert.Length;
- nssObj.signatureAlgorithm.Data = algId.Data;
- nssObj.signatureAlgorithm.Length = algId.Length;
- nssObj.signature.Data = rawSig.Data;
- nssObj.signature.Length = rawSig.Length * 8; // BIT STRING
-
- PRErrorCode prtn;
-
- prtn = SecNssEncodeItemOdata(&nssObj,
- kSecAsn1SignedCertOrCRLTemplate,signedCert);
- if(prtn) {
- CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
- }
-
-}