]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_apple_x509_cl / lib / CLCertExtensions.cpp
diff --git a/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp b/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp
new file mode 100644 (file)
index 0000000..aa198e0
--- /dev/null
@@ -0,0 +1,1265 @@
+/*
+ * Copyright (c) 2000-2012 Apple Inc. All Rights Reserved.
+ * 
+ * The contents of this file constitute Original Code as defined in and are
+ * subject to the Apple Public Source License Version 1.2 (the 'License').
+ * You may not use this file except in compliance with the License. Please obtain
+ * a copy of the License at http://www.apple.com/publicsource and read it before
+ * using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
+ * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
+ * specific language governing rights and limitations under the License.
+ */
+
+
+/*
+ * CLCertExtensions.cpp - extensions support. A major component of DecodedCert.
+ *
+ */
+#include "DecodedCert.h"
+#include "cldebugging.h"
+#include "CLCertExtensions.h"
+#include "CLFieldsCommon.h"
+#include "clNssUtils.h"
+#include "clNameUtils.h"
+#include <security_utilities/utilities.h>
+#include <Security/oidscert.h>
+#include <Security/oidsattr.h>
+#include <Security/cssmerr.h>
+#include <Security/x509defs.h>
+#include <Security/certextensions.h>
+#include <security_utilities/globalizer.h>
+#include <Security/certExtensionTemplates.h>
+#include <Security/SecAsn1Templates.h>
+
+/***
+ *** get/set/free functions called out from CertFields.cpp
+ ***/
+
+/***
+ *** KeyUsage 
+ *** CDSA format       CE_KeyUsage
+ *** NSS format        CSSM_DATA, length 2
+ *** OID                       CSSMOID_KeyUsage
+ ***/
+void setFieldKeyUsage(         
+       DecodedItem     &cert, 
+       const CssmData &fieldValue) 
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, 
+               false);
+       CE_KeyUsage *cdsaObj = (CE_KeyUsage *)cssmExt->value.parsedValue;
+       
+       /* Alloc an NSS-style key usage in cert.coder's memory */
+       SecNssCoder &coder = cert.coder();
+       CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
+       coder.allocItem(*nssObj, 2);
+       
+       /* cdsaObj --> nssObj */
+       nssObj->Data[0] = (*cdsaObj) >> 8;
+       nssObj->Data[1] = *cdsaObj;
+       
+       /* Adjust length for BIT STRING encoding */
+       clCssmBitStringToNss(*nssObj);
+       
+       /* add to mExtensions */
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1KeyUsageTemplate); 
+}
+
+
+bool getFieldKeyUsage(
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       CSSM_DATA *nssObj;
+       CE_KeyUsage *cdsaObj;
+       bool brtn;
+       
+       brtn = cert.GetExtenTop<CSSM_DATA, CE_KeyUsage>(
+               index,
+               numFields,
+               fieldValue.allocator,
+               CSSMOID_KeyUsage,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       
+       /* make a copy - can't modify length in place */
+       CSSM_DATA bitString = *nssObj;
+       clNssBitStringToCssm(bitString);
+       size_t toCopy = bitString.Length;
+       if(toCopy > 2) {
+               /* I hope I never see this... */
+               clErrorLog("getFieldKeyUsage: KeyUsage larger than 2 bytes!");
+               toCopy = 2;
+       }
+       unsigned char bits[2] = {0, 0};
+       memmove(bits, bitString.Data, toCopy);
+       *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
+       
+       /* pass back to caller */
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+/***
+ *** Basic Constraints 
+ *** CDSA format:      CE_BasicConstraints
+ *** NSS format        CE_BasicConstraints
+ *** OID                       CSSMOID_BasicConstraints
+ ***/
+void setFieldBasicConstraints(         
+       DecodedItem     &cert, 
+       const CssmData &fieldValue) 
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = 
+               verifySetFreeExtension(fieldValue, false);
+       CE_BasicConstraints *cdsaObj = 
+               (CE_BasicConstraints *)cssmExt->value.parsedValue;
+       
+       /* Alloc an NSS-style BasicConstraints in cert.coder's memory */
+       SecNssCoder &coder = cert.coder();
+       NSS_BasicConstraints *nssObj = 
+               (NSS_BasicConstraints *)coder.malloc(sizeof(NSS_BasicConstraints));
+       memset(nssObj, 0, sizeof(*nssObj));
+       
+       /* cdsaObj --> nssObj */
+       ArenaAllocator arenaAlloc(coder);
+       clCssmBoolToNss(cdsaObj->cA, nssObj->cA, arenaAlloc);
+       if(cdsaObj->pathLenConstraintPresent) {
+               clIntToData(cdsaObj->pathLenConstraint, 
+                       nssObj->pathLenConstraint, arenaAlloc);
+       }
+
+       /* add to mExtensions */
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1BasicConstraintsTemplate); 
+}
+
+
+bool getFieldBasicConstraints(
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_BasicConstraints *nssObj;
+       CE_BasicConstraints *cdsaObj;
+       bool brtn;
+       
+       brtn = cert.GetExtenTop<NSS_BasicConstraints, CE_BasicConstraints>(
+               index,
+               numFields,
+               fieldValue.allocator,
+               CSSMOID_BasicConstraints,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+
+       if(nssObj->cA.Data == NULL) {
+               /* default */
+               cdsaObj->cA = CSSM_FALSE;
+       }
+       else {
+               cdsaObj->cA = clNssBoolToCssm(nssObj->cA);
+       }
+       if(nssObj->pathLenConstraint.Data == NULL) {
+               /* optional */
+               cdsaObj->pathLenConstraintPresent = CSSM_FALSE;
+               cdsaObj->pathLenConstraint = 0;
+       }
+       else {
+               cdsaObj->pathLenConstraintPresent = CSSM_TRUE;
+               cdsaObj->pathLenConstraint = clDataToInt(nssObj->pathLenConstraint);
+       }
+       
+       /* pass back to caller */
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+/***
+ *** Extended Key Usage
+ *** CDSA format:      CE_ExtendedKeyUsage
+ *** NSS format:       NSS_ExtKeyUsage
+ *** OID                       CSSMOID_ExtendedKeyUsage
+ ***/
+void setFieldExtKeyUsage(              
+       DecodedItem     &cert, 
+       const CssmData &fieldValue) 
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, 
+               false);
+       CE_ExtendedKeyUsage *cdsaObj = 
+               (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
+       
+       SecNssCoder &coder = cert.coder();
+       NSS_ExtKeyUsage *nssObj = 
+               (NSS_ExtKeyUsage *)coder.malloc(sizeof(NSS_ExtKeyUsage));
+       memset(nssObj, 0, sizeof(*nssObj));
+       if(cdsaObj->numPurposes != 0) {
+               nssObj->purposes = 
+                       (CSSM_OID **)clNssNullArray(cdsaObj->numPurposes, coder);
+       }
+       
+       /* cdsaObj --> nssObj, one 'purpose' (OID) at a time */
+       for(unsigned dex=0; dex<cdsaObj->numPurposes; dex++) {
+               nssObj->purposes[dex] = (CSSM_OID *)coder.malloc(sizeof(CSSM_OID));
+               coder.allocCopyItem(cdsaObj->purposes[dex],
+                       *nssObj->purposes[dex]);
+       }
+
+       /* add to mExtensions */
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1ExtKeyUsageTemplate); 
+}
+
+bool getFieldExtKeyUsage(
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_ExtKeyUsage *nssObj;
+       CE_ExtendedKeyUsage *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+       
+       brtn = cert.GetExtenTop<NSS_ExtKeyUsage, CE_ExtendedKeyUsage>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_ExtendedKeyUsage,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       
+       /* nssObj --> cdsaObj, one purpose at a time */ 
+       unsigned numPurposes = clNssArraySize((const void **)nssObj->purposes);
+       cdsaObj->numPurposes = numPurposes;
+       if(numPurposes) {
+               unsigned len = numPurposes * sizeof(CSSM_OID);
+               cdsaObj->purposes = (CSSM_OID_PTR)alloc.malloc(len);
+               memset(cdsaObj->purposes, 0, len);
+       }
+       for(unsigned dex=0; dex<numPurposes; dex++) {
+               clAllocCopyData(alloc, *nssObj->purposes[dex], cdsaObj->purposes[dex]);
+       }
+
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldExtKeyUsage(
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_ExtendedKeyUsage *cdsaObj = 
+               (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
+       unsigned oidDex;
+       for(oidDex=0; oidDex<cdsaObj->numPurposes; oidDex++) {
+               alloc.free(cdsaObj->purposes[oidDex].Data);
+       }
+       alloc.free(cdsaObj->purposes);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+}
+
+/***
+ *** Subject Key Identifier
+ *** CDSA format:      CE_SubjectKeyID, which is just a CSSM_DATA
+ *** OID                       CSSMOID_SubjectKeyIdentifier
+ ***/
+void setFieldSubjectKeyId(             
+       DecodedItem     &cert, 
+       const CssmData &fieldValue) 
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, 
+               false);
+       CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue;
+       SecNssCoder &coder = cert.coder();
+       CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
+       coder.allocCopyItem(*cdsaObj, *nssObj);
+       
+       /* add to mExtensions */
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1SubjectKeyIdTemplate); 
+}
+
+bool getFieldSubjectKeyId(
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       CSSM_DATA *nssObj;
+       CE_SubjectKeyID *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+       
+       brtn = cert.GetExtenTop<CSSM_DATA, CE_SubjectKeyID>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_SubjectKeyIdentifier,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       
+       /* if this fails, we're out of sync with nssExtenInfo[] in 
+        * CLFieldsCommon.cpp */
+       assert(nssObj != NULL); 
+       clAllocCopyData(alloc, *nssObj, *cdsaObj);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldSubjectKeyId (
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue;
+       alloc.free(cdsaObj->Data);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+}
+
+/***
+ *** Authority Key Identifier
+ *** CDSA format:      CE_AuthorityKeyID
+ *** NSS format:       NSS_AuthorityKeyId
+ *** OID                       CSSMOID_AuthorityKeyIdentifier
+ ***/
+void setFieldAuthorityKeyId(           
+       DecodedItem     &cert, 
+       const CssmData &fieldValue) 
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, 
+               false);
+       CE_AuthorityKeyID *cdsaObj = 
+               (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
+       
+       /* Alloc an NSS-style AuthorityKeyId in cert.coder's memory */
+       SecNssCoder &coder = cert.coder();
+       NSS_AuthorityKeyId *nssObj = 
+               (NSS_AuthorityKeyId *)coder.malloc(sizeof(NSS_AuthorityKeyId));
+       memset(nssObj, 0, sizeof(*nssObj));
+       
+       /* convert caller's CDSA-style CE_AuthorityKeyID to NSS */
+       CL_cssmAuthorityKeyIdToNss(*cdsaObj, *nssObj, coder);
+       
+       /* add to mExtensions */
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1AuthorityKeyIdTemplate); 
+}
+
+bool getFieldAuthorityKeyId(
+       DecodedItem                     &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_AuthorityKeyId *nssObj;
+       CE_AuthorityKeyID *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+       
+       brtn = cert.GetExtenTop<NSS_AuthorityKeyId, CE_AuthorityKeyID>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_AuthorityKeyIdentifier,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       assert(nssObj != NULL);
+       
+       /* nssObj --> cdsaObj */
+       CL_nssAuthorityKeyIdToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
+       
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldAuthorityKeyId (
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
+       CL_freeAuthorityKeyId(*cdsaObj, alloc);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+}
+
+/***
+ *** Subject/Issuer alternate name
+ *** CDSA Format:      CE_GeneralNames
+ *** NSS format:       NSS_GeneralNames
+ *** OID:                      CSSMOID_SubjectAltName, CSSMOID_IssuerAltName
+ ***/
+void setFieldSubjIssuerAltName(                
+       DecodedItem     &cert, 
+       const CssmData &fieldValue) 
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = 
+               verifySetFreeExtension(fieldValue, false);
+       CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
+
+       /* Alloc an NSS-style GeneralNames in cert.coder's memory */
+       SecNssCoder &coder = cert.coder();
+       NSS_GeneralNames *nssObj = 
+               (NSS_GeneralNames *)coder.malloc(sizeof(NSS_GeneralNames));
+       memset(nssObj, 0, sizeof(*nssObj));
+       
+       /* cdsaObj --> nssObj */
+       CL_cssmGeneralNamesToNss(*cdsaObj, *nssObj, coder);
+       
+       /* add to mExtensions */
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1GeneralNamesTemplate); 
+}
+
+bool getFieldSubjAltName(
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_GeneralNames *nssObj;
+       CE_GeneralNames *cdsaObj; 
+       bool brtn;
+       
+       brtn = cert.GetExtenTop<NSS_GeneralNames, CE_GeneralNames>(
+               index,
+               numFields,
+               fieldValue.allocator,
+               CSSMOID_SubjectAltName,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj,     
+               cert.coder(), fieldValue.allocator);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+bool getFieldIssuerAltName(
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_GeneralNames *nssObj;
+       CE_GeneralNames *cdsaObj; 
+       bool brtn;
+       
+       brtn = cert.GetExtenTop<NSS_GeneralNames, CE_GeneralNames>(
+               index,
+               numFields,
+               fieldValue.allocator,
+               CSSMOID_IssuerAltName,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj,     
+               cert.coder(), fieldValue.allocator);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldSubjIssuerAltName (
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
+       CL_freeCssmGeneralNames(cdsaObj, alloc);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+}
+
+/***
+ *** Certificate Policies
+ *** CDSA Format:      CE_CertPolicies
+ *** NSS format :      NSS_CertPolicies
+ *** OID:                      CSSMOID_CertificatePolicies
+ ***/
+#define MAX_IA5_NAME_SIZE      1024
+
+void setFieldCertPolicies(             
+       DecodedItem     &cert, 
+       const CssmData &fieldValue) 
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = 
+               verifySetFreeExtension(fieldValue, false);
+       SecNssCoder &coder = cert.coder();
+       NSS_CertPolicies *nssObj = 
+               (NSS_CertPolicies *)coder.malloc(sizeof(NSS_CertPolicies));
+       memset(nssObj, 0, sizeof(NSS_CertPolicies));
+       CE_CertPolicies *cdsaObj = 
+               (CE_CertPolicies *)cssmExt->value.parsedValue;
+       
+       if(cdsaObj->numPolicies) {
+               nssObj->policies = 
+                       (NSS_PolicyInformation **)clNssNullArray(
+                               cdsaObj->numPolicies, coder);
+       }
+       for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
+               CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
+               NSS_PolicyInformation *nPolInfo = (NSS_PolicyInformation *)
+                       coder.malloc(sizeof(NSS_PolicyInformation));
+               memset(nPolInfo, 0, sizeof(*nPolInfo));
+               nssObj->policies[polDex] = nPolInfo;
+               
+               coder.allocCopyItem(cPolInfo->certPolicyId, nPolInfo->certPolicyId);
+
+               unsigned numQual = cPolInfo->numPolicyQualifiers;
+               if(numQual != 0) {
+                       nPolInfo->policyQualifiers = 
+                               (NSS_PolicyQualifierInfo **)clNssNullArray(numQual,
+                                       coder);
+               }
+               for(unsigned qualDex=0; qualDex<numQual; qualDex++) {
+                       CE_PolicyQualifierInfo *cQualInfo = 
+                               &cPolInfo->policyQualifiers[qualDex];
+                       NSS_PolicyQualifierInfo *nQualInfo = 
+                               (NSS_PolicyQualifierInfo *)coder.malloc(
+                                       sizeof(NSS_PolicyQualifierInfo));
+                       memset(nQualInfo, 0, sizeof(NSS_PolicyQualifierInfo));
+                       nPolInfo->policyQualifiers[qualDex] = nQualInfo;
+                       
+                       /* 
+                        * OK we're at the lowest level. 
+                        * policyQualifierId == id_qt_cps: qualifier is 
+                        * an IA5 string, incoming data is its contents. 
+                        * Else incoming data is an encoded blob we pass on directly.
+                        */
+                       coder.allocCopyItem(cQualInfo->policyQualifierId,
+                               nQualInfo->policyQualifierId);
+                               
+                       if(clCompareCssmData(&cQualInfo->policyQualifierId, 
+                                       &CSSMOID_QT_CPS)) {
+                               if(coder.encodeItem(&cQualInfo->qualifier,
+                                               kSecAsn1IA5StringTemplate,
+                                               nQualInfo->qualifier)) {
+                                       clErrorLog("setFieldCertPOlicies: IA5 encode error\n");
+                                       CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
+                               }
+                       }
+                       else {
+                               /* uninterpreted, copy over directly */
+                               coder.allocCopyItem(cQualInfo->qualifier,
+                                       nQualInfo->qualifier);
+                       }
+               }       /* for each qualifier */
+       }       /* for each policy */
+       
+       /* add to mExtensions */
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1CertPoliciesTemplate); 
+}
+
+bool getFieldCertPolicies( 
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_CertPolicies *nssObj;
+       CE_CertPolicies *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+       brtn = cert.GetExtenTop<NSS_CertPolicies, CE_CertPolicies>(
+               index,
+               numFields,
+               fieldValue.allocator,
+               CSSMOID_CertificatePolicies,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       assert(nssObj != NULL);
+       
+       memset(cdsaObj, 0, sizeof(*cdsaObj));
+       cdsaObj->numPolicies = 
+               clNssArraySize((const void **)nssObj->policies);
+       unsigned sz = cdsaObj->numPolicies * sizeof(CE_PolicyInformation);
+       if(sz) {
+               cdsaObj->policies = (CE_PolicyInformation *)alloc.malloc(sz);
+               memset(cdsaObj->policies, 0, sz);
+       }
+
+       for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
+               CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
+               NSS_PolicyInformation *nPolInfo = nssObj->policies[polDex];
+               clAllocCopyData(alloc, nPolInfo->certPolicyId,
+                       cPolInfo->certPolicyId);
+               if(nPolInfo->policyQualifiers == NULL) {
+                       continue;
+               }
+               
+               cPolInfo->numPolicyQualifiers = 
+                       clNssArraySize((const void **)nPolInfo->policyQualifiers);
+               sz = cPolInfo->numPolicyQualifiers * 
+                        sizeof(CE_PolicyQualifierInfo);
+               cPolInfo->policyQualifiers = (CE_PolicyQualifierInfo *)
+                       alloc.malloc(sz);
+               memset(cPolInfo->policyQualifiers, 0, sz);
+               
+               for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; 
+                               qualDex++) {
+                       NSS_PolicyQualifierInfo *nQualInfo = 
+                               nPolInfo->policyQualifiers[qualDex];
+                       CE_PolicyQualifierInfo *cQualInfo = 
+                               &cPolInfo->policyQualifiers[qualDex];
+                       
+                       /* 
+                        * leaf. 
+                        * policyQualifierId == CSSMOID_QT_CPS : 
+                        *              IA5String - decode and return contents.
+                        * Else return whole thing. 
+                        */
+                       clAllocCopyData(alloc, nQualInfo->policyQualifierId,
+                               cQualInfo->policyQualifierId);
+                       CSSM_DATA toCopy = nQualInfo->qualifier;
+                       if(clCompareCssmData(&nQualInfo->policyQualifierId, 
+                                               &CSSMOID_QT_CPS)) {
+                               /* decode as IA5String to temp memory */
+                               toCopy.Data = NULL;
+                               toCopy.Length = 0;
+                               if(cert.coder().decodeItem(nQualInfo->qualifier,
+                                               kSecAsn1IA5StringTemplate,
+                                               &toCopy)) {
+                                       clErrorLog("***getCertPolicies: bad IA5String!\n");
+                                       CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
+                               }
+                       }
+                       /* else copy out nQualInfo->qualifier */
+                       clAllocCopyData(alloc, toCopy, cQualInfo->qualifier);
+               }       /* for each qualifier */
+       }               /* for each policy info */
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldCertPolicies (
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue;
+       for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
+               CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
+               alloc.free(cPolInfo->certPolicyId.Data);
+               for(unsigned qualDex=0; 
+                            qualDex<cPolInfo->numPolicyQualifiers; 
+                                        qualDex++) {
+                       CE_PolicyQualifierInfo *cQualInfo = 
+                               &cPolInfo->policyQualifiers[qualDex];
+                       alloc.free(cQualInfo->policyQualifierId.Data);
+                       alloc.free(cQualInfo->qualifier.Data);
+               }
+               alloc.free(cPolInfo->policyQualifiers);
+       }
+       alloc.free(cdsaObj->policies);
+       freeFieldExtenCommon(cssmExt, alloc);   // frees extnId, parsedValue,
+                                                                                       //    BERvalue
+}
+
+/***
+ *** Netscape cert type
+ *** CDSA Format:      CE_NetscapeCertType (a uint16)
+ *** NSS format        CSSM_DATA, length 2
+ *** OID:                      CSSMOID_NetscapeCertType
+ ***/
+void setFieldNetscapeCertType(         
+       DecodedItem     &cert, 
+       const CssmData &fieldValue) 
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, 
+               false);
+       CE_NetscapeCertType *cdsaObj = 
+               (CE_NetscapeCertType *)cssmExt->value.parsedValue;
+       
+       /* Alloc an NSS-style key usage in cert.coder's memory */
+       SecNssCoder &coder = cert.coder();
+       CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
+       coder.allocItem(*nssObj, 2);
+       
+       /* cdsaObj --> nssObj */
+       nssObj->Data[0] = (*cdsaObj) >> 8;
+       nssObj->Data[1] = *cdsaObj;
+       
+       /* Adjust length for BIT STRING encoding */
+       clCssmBitStringToNss(*nssObj);
+       
+       /* add to mExtensions */
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1NetscapeCertTypeTemplate); 
+}
+
+bool getFieldNetscapeCertType(
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       CSSM_DATA *nssObj;
+       CE_NetscapeCertType *cdsaObj;
+       bool brtn;
+       
+       brtn = cert.GetExtenTop<CSSM_DATA, CE_NetscapeCertType>(
+               index,
+               numFields,
+               fieldValue.allocator,
+               CSSMOID_NetscapeCertType,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       
+       /* make a copy - can't modify length in place */
+       CSSM_DATA bitString = *nssObj;
+       clNssBitStringToCssm(bitString);
+       size_t toCopy = bitString.Length;
+       if(toCopy > 2) {
+               /* I hope I never see this... */
+               clErrorLog("getFieldKeyUsage: CertType larger than 2 bytes!");
+               toCopy = 2;
+       }
+       unsigned char bits[2] = {0, 0};
+       memmove(bits, bitString.Data, toCopy);
+       *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
+       
+       /* pass back to caller */
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+/***
+ *** CRL Distribution points
+ *** CDSA Format:      CE_CRLDistPointsSyntax
+ *** NSS format:       NSS_CRLDistributionPoints
+ *** OID:                      CSSMOID_CrlDistributionPoints
+ ***/
+void setFieldCrlDistPoints(            
+       DecodedItem     &cert, 
+       const CssmData &fieldValue)  
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = 
+               verifySetFreeExtension(fieldValue, false);
+       CE_CRLDistPointsSyntax *cdsaObj = 
+               (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue;
+       SecNssCoder &coder = cert.coder();
+       NSS_CRLDistributionPoints *nssObj = 
+               (NSS_CRLDistributionPoints *)coder.malloc(
+                               sizeof(NSS_CRLDistributionPoints));
+               
+       CL_cssmDistPointsToNss(*cdsaObj, *nssObj, coder);
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1CRLDistributionPointsTemplate); 
+}
+
+bool getFieldCrlDistPoints( 
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_CRLDistributionPoints *nssObj;
+       CE_CRLDistPointsSyntax *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+
+       brtn = cert.GetExtenTop<NSS_CRLDistributionPoints, 
+                       CE_CRLDistPointsSyntax>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_CrlDistributionPoints,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       assert(nssObj != NULL);
+       CL_nssDistPointsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldCrlDistPoints (
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_CRLDistPointsSyntax *cdsaObj = 
+               (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue;
+       CL_freeCssmDistPoints(cdsaObj, alloc);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+}
+
+/***
+ *** {Subject,Authority}InfoAccess
+ ***
+ *** CDSA Format:      CE_AuthorityInfoAccess
+ *** NSS format:       NSS_AuthorityInfoAccess
+ *** OID:                      CSSMOID_AuthorityInfoAccess, CSSMOID_SubjectInfoAccess
+ ***/
+void setFieldAuthInfoAccess(           
+       DecodedItem     &cert, 
+       const CssmData &fieldValue)  
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = 
+               verifySetFreeExtension(fieldValue, false);
+       CE_AuthorityInfoAccess *cdsaObj = 
+               (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue;
+       SecNssCoder &coder = cert.coder();
+       NSS_AuthorityInfoAccess *nssObj = 
+               (NSS_AuthorityInfoAccess *)coder.malloc(
+                               sizeof(NSS_AuthorityInfoAccess));
+               
+       CL_cssmInfoAccessToNss(*cdsaObj, *nssObj, coder);
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1AuthorityInfoAccessTemplate); 
+}
+
+bool getFieldAuthInfoAccess( 
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_AuthorityInfoAccess *nssObj;
+       CE_AuthorityInfoAccess *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+
+       brtn = cert.GetExtenTop<NSS_AuthorityInfoAccess, 
+                       CE_AuthorityInfoAccess>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_AuthorityInfoAccess,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       assert(nssObj != NULL);
+       CL_infoAccessToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+bool getFieldSubjInfoAccess( 
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_AuthorityInfoAccess *nssObj;
+       CE_AuthorityInfoAccess *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+
+       brtn = cert.GetExtenTop<NSS_AuthorityInfoAccess, 
+                       CE_AuthorityInfoAccess>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_SubjectInfoAccess,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       assert(nssObj != NULL);
+       CL_infoAccessToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldInfoAccess (
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_AuthorityInfoAccess *cdsaObj = 
+               (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue;
+       CL_freeInfoAccess(*cdsaObj, alloc);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+
+}
+
+/***
+ *** Qualfied Cert Statements
+ ***
+ *** CDSA Format:      CE_QC_Statements
+ *** NSS format:       NSS_QC_Statements
+ *** OID:                      CSSMOID_QC_Statements
+ ***/
+void setFieldQualCertStatements(               
+       DecodedItem     &cert, 
+       const CssmData &fieldValue)  
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = 
+               verifySetFreeExtension(fieldValue, false);
+       CE_QC_Statements *cdsaObj = 
+               (CE_QC_Statements *)cssmExt->value.parsedValue;
+       SecNssCoder &coder = cert.coder();
+       NSS_QC_Statements *nssObj = 
+               (NSS_QC_Statements *)coder.malloc(
+                               sizeof(NSS_QC_Statements));
+               
+       CL_cssmQualCertStatementsToNss(*cdsaObj, *nssObj, coder);
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1QC_StatementsTemplate); 
+}
+
+bool getFieldQualCertStatements( 
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_QC_Statements *nssObj;
+       CE_QC_Statements *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+
+       brtn = cert.GetExtenTop<NSS_QC_Statements, 
+                       CE_QC_Statements>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_QC_Statements,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       assert(nssObj != NULL);
+       CL_qualCertStatementsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldQualCertStatements( 
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_QC_Statements *cdsaObj = 
+               (CE_QC_Statements *)cssmExt->value.parsedValue;
+       CL_freeQualCertStatements(*cdsaObj, alloc);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+}
+
+/***
+ *** Name Constraints
+ *** CDSA Format:      CE_NameConstraints
+ *** NSS format:       NSS_NameConstraints
+ *** OID:                      CSSMOID_NameConstraints
+ ***/
+void setFieldNameConstraints(          
+       DecodedItem     &cert, 
+       const CssmData &fieldValue)  
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = 
+               verifySetFreeExtension(fieldValue, false);
+       CE_NameConstraints *cdsaObj = 
+               (CE_NameConstraints *)cssmExt->value.parsedValue;
+       SecNssCoder &coder = cert.coder();
+       NSS_NameConstraints *nssObj = 
+               (NSS_NameConstraints *)coder.malloc(
+                               sizeof(NSS_NameConstraints));
+       CL_cssmNameConstraintsToNss(*cdsaObj, *nssObj, coder);
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1NameConstraintsTemplate); 
+}
+
+bool getFieldNameConstraints( 
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_NameConstraints *nssObj;
+       CE_NameConstraints *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+
+       brtn = cert.GetExtenTop<NSS_NameConstraints, 
+                       CE_NameConstraints>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_NameConstraints,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       assert(nssObj != NULL);
+       CL_nssNameConstraintsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldNameConstraints (
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_NameConstraints *cdsaObj = 
+               (CE_NameConstraints *)cssmExt->value.parsedValue;
+       CL_freeCssmNameConstraints(cdsaObj, alloc);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+}
+
+/***
+ *** Policy Mappings
+ *** CDSA Format:      CE_PolicyMappings
+ *** NSS format:       NSS_PolicyMappings
+ *** OID:                      CSSMOID_PolicyMappings
+ ***/
+void setFieldPolicyMappings(           
+       DecodedItem     &cert, 
+       const CssmData &fieldValue)  
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = 
+               verifySetFreeExtension(fieldValue, false);
+       CE_PolicyMappings *cdsaObj = 
+               (CE_PolicyMappings *)cssmExt->value.parsedValue;
+       SecNssCoder &coder = cert.coder();
+       NSS_PolicyMappings *nssObj = 
+               (NSS_PolicyMappings *)coder.malloc(
+                               sizeof(NSS_PolicyMappings));
+       CL_cssmPolicyMappingsToNss(*cdsaObj, *nssObj, coder);
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1PolicyMappingsTemplate); 
+}
+
+bool getFieldPolicyMappings( 
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_PolicyMappings *nssObj;
+       CE_PolicyMappings *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+
+       brtn = cert.GetExtenTop<NSS_PolicyMappings, 
+                       CE_PolicyMappings>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_PolicyMappings,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       assert(nssObj != NULL);
+       CL_nssPolicyMappingsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldPolicyMappings (
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_PolicyMappings *cdsaObj = 
+               (CE_PolicyMappings *)cssmExt->value.parsedValue;
+       CL_freeCssmPolicyMappings(cdsaObj, alloc);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+}
+
+/***
+ *** Policy Constraints
+ *** CDSA Format:      CE_PolicyConstraints
+ *** NSS format:       NSS_PolicyConstraints
+ *** OID:                      CSSMOID_PolicyConstraints
+ ***/
+void setFieldPolicyConstraints(                
+       DecodedItem     &cert, 
+       const CssmData &fieldValue)  
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = 
+               verifySetFreeExtension(fieldValue, false);
+       CE_PolicyConstraints *cdsaObj = 
+               (CE_PolicyConstraints *)cssmExt->value.parsedValue;
+       SecNssCoder &coder = cert.coder();
+       NSS_PolicyConstraints *nssObj = 
+               (NSS_PolicyConstraints *)coder.malloc(
+                               sizeof(NSS_PolicyConstraints));
+       CL_cssmPolicyConstraintsToNss(cdsaObj, nssObj, coder);
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1PolicyConstraintsTemplate); 
+}
+
+bool getFieldPolicyConstraints( 
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       NSS_PolicyConstraints *nssObj;
+       CE_PolicyConstraints *cdsaObj;
+       bool brtn;
+       Allocator &alloc = fieldValue.allocator;
+
+       brtn = cert.GetExtenTop<NSS_PolicyConstraints, 
+                       CE_PolicyConstraints>(
+               index,
+               numFields,
+               alloc,
+               CSSMOID_PolicyConstraints,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       assert(nssObj != NULL);
+       CL_nssPolicyConstraintsToCssm(nssObj, cdsaObj, cert.coder(), alloc);
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+
+void freeFieldPolicyConstraints (
+       CssmOwnedData           &fieldValue)
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
+       Allocator &alloc = fieldValue.allocator;
+       CE_PolicyConstraints *cdsaObj = 
+               (CE_PolicyConstraints *)cssmExt->value.parsedValue;
+       CL_freeCssmPolicyConstraints(cdsaObj, alloc);
+       freeFieldExtenCommon(cssmExt, alloc);           // frees extnId, parsedValue, BERvalue
+}
+
+/***
+ *** Inhibit Any Policy
+ *** CDSA Format:      CE_InhibitAnyPolicy (an integer)
+ *** NSS format:       CSSM_DATA, sizeof(uint32)
+ *** OID:                      CSSMOID_InhibitAnyPolicy
+ ***/
+void setFieldInhibitAnyPolicy(         
+       DecodedItem     &cert, 
+       const CssmData &fieldValue) 
+{
+       CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, 
+               false);
+       CE_InhibitAnyPolicy *cdsaObj = 
+               (CE_InhibitAnyPolicy *)cssmExt->value.parsedValue;
+       
+       /* Alloc in cert.coder's memory */
+       SecNssCoder &coder = cert.coder();
+       CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
+       coder.allocItem(*nssObj, sizeof(uint32));
+       
+       /* cdsaObj --> nssObj */
+       nssObj->Data[0] = (*cdsaObj) >> 24;
+       nssObj->Data[1] = (*cdsaObj) >> 16;
+       nssObj->Data[2] = (*cdsaObj) >> 8;
+       nssObj->Data[3] = *cdsaObj;
+       
+       /* add to mExtensions */
+       cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
+               kSecAsn1IntegerTemplate); 
+}
+
+bool getFieldInhibitAnyPolicy(
+       DecodedItem             &cert,
+       unsigned                        index,                  // which occurrence (0 = first)
+       uint32                          &numFields,             // RETURNED
+       CssmOwnedData           &fieldValue) 
+{
+       const DecodedExten *decodedExt;
+       CSSM_DATA *nssObj;
+       CE_InhibitAnyPolicy *cdsaObj;
+       bool brtn;
+       
+       brtn = cert.GetExtenTop<CSSM_DATA, CE_InhibitAnyPolicy>(
+               index,
+               numFields,
+               fieldValue.allocator,
+               CSSMOID_InhibitAnyPolicy,
+               nssObj,
+               cdsaObj,
+               decodedExt);
+       if(!brtn) {
+               return false;
+       }
+       
+       *cdsaObj = *(nssObj->Data); //%%%FIXME check this
+       
+       /* pass back to caller */
+       getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
+       return true;
+}
+