/* * Copyright (c) 2000-2001 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. */ /* * CLCertExtensions.cpp - extensions support. A major component of DecodedCert. * * Created 9/8/2000 by Doug Mitchell. * Copyright (c) 2000 by Apple Computer. * */ #include "DecodedCert.h" #include "cldebugging.h" #include "CLCertExtensions.h" #include "CLFieldsCommon.h" #include "clNssUtils.h" #include "clNameUtils.h" #include #include #include #include #include #include #include #include /*** *** 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, NSS_KeyUsageTemplate); } 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( 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); unsigned 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, NSS_BasicConstraintsTemplate); } 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( 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; dexnumPurposes; 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, NSS_ExtKeyUsageTemplate); } 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; CssmAllocator &alloc = fieldValue.allocator; brtn = cert.GetExtenTop( 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; dexpurposes[dex], cdsaObj->purposes[dex]); } getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); return true; } void freeFieldExtKeyUsage( CssmOwnedData &fieldValue) { CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); CssmAllocator &alloc = fieldValue.allocator; CE_ExtendedKeyUsage *cdsaObj = (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue; unsigned oidDex; for(oidDex=0; oidDexnumPurposes; 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, NSS_SubjectKeyIdTemplate); } 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; CssmAllocator &alloc = fieldValue.allocator; brtn = cert.GetExtenTop( 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); CssmAllocator &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, NSS_AuthorityKeyIdTemplate); } 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; CssmAllocator &alloc = fieldValue.allocator; brtn = cert.GetExtenTop( 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); CssmAllocator &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, NSS_GeneralNamesTemplate); } 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( 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( 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); CssmAllocator &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; polDexnumPolicies; 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; qualDexpolicyQualifiers[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, SEC_IA5StringTemplate, 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, NSS_CertPoliciesTemplate); } 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; CssmAllocator &alloc = fieldValue.allocator; brtn = cert.GetExtenTop( 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; polDexnumPolicies; 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; qualDexnumPolicyQualifiers; 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, SEC_IA5StringTemplate, &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); CssmAllocator &alloc = fieldValue.allocator; CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue; for(unsigned polDex=0; polDexnumPolicies; polDex++) { CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex]; alloc.free(cPolInfo->certPolicyId.Data); for(unsigned qualDex=0; qualDexnumPolicyQualifiers; 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, NSS_NetscapeCertTypeTemplate); } 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( 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); unsigned 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, NSS_CRLDistributionPointsTemplate); } 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; CssmAllocator &alloc = fieldValue.allocator; brtn = cert.GetExtenTop( 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); CssmAllocator &alloc = fieldValue.allocator; CE_CRLDistPointsSyntax *cdsaObj = (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; CL_freeCssmDistPoints(cdsaObj, alloc); freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue }