]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_apple_x509_cl/lib/clNssUtils.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_apple_x509_cl / lib / clNssUtils.cpp
diff --git a/libsecurity_apple_x509_cl/lib/clNssUtils.cpp b/libsecurity_apple_x509_cl/lib/clNssUtils.cpp
deleted file mode 100644 (file)
index a559e6a..0000000
+++ /dev/null
@@ -1,1386 +0,0 @@
-/*
- * 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);
-       }
-
-}