X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/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 index 00000000..aa198e08 --- /dev/null +++ b/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp @@ -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 +#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; +} +