/* * 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 #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, 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( 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( 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, 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( 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); Allocator &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, 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( 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( 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( 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); 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; 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, 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( 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, 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; 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, 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( 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( 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( 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( 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( 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( 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( 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( 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( 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; }