CLCertExtensions.cpp [plain text]
#include "DecodedCert.h"
#include "cldebugging.h"
#include "CertBuilder.h"
#include "CLCertExtensions.h"
#include "SnaccUtils.h"
#include <Security/utilities.h>
#include <Security/oidscert.h>
#include <Security/cssmerr.h>
#include <Security/x509defs.h>
#include <Security/certextensions.h>
#include <Security/cdsaUtils.h>
#include <Security/sm_x509ce.h>
#include <Security/globalizer.h>
static AsnType *oidToSnaccObj(
const AsnOid &extnId);
#define MIN_EXTENSIONS 4 // initial size of *mExtensions
class ExtOidCache
{
public:
ExtOidCache() :
mId_ce_keyUsage(id_ce_keyUsage_arc),
mId_ce_basicConstraints(id_ce_basicConstraints_arc),
mId_ce_extKeyUsage(id_ce_extKeyUsage_arc),
mId_ce_subjectKeyIdentifier(id_ce_subjectKeyIdentifier_arc),
mId_ce_authorityKeyIdentifier(id_ce_authorityKeyIdentifier_arc),
mId_ce_subjectAltName(id_ce_subjectAltName_arc),
mId_ce_certificatePolicies(id_ce_certificatePolicies_arc),
mId_netscape_cert_type(id_netscape_cert_type_arc)
{ }
AsnOid mId_ce_keyUsage;
AsnOid mId_ce_basicConstraints;
AsnOid mId_ce_extKeyUsage;
AsnOid mId_ce_subjectKeyIdentifier;
AsnOid mId_ce_authorityKeyIdentifier;
AsnOid mId_ce_subjectAltName;
AsnOid mId_ce_certificatePolicies;
AsnOid mId_netscape_cert_type;
};
static ModuleNexus<ExtOidCache> extOidCache;
void DecodedCert::decodeExtensions()
{
CASSERT(certificateToSign != NULL);
Extensions *extensions = certificateToSign->extensions;
if(extensions == NULL) {
return;
}
Extension *snaccExten = extensions->First();
extensions->SetCurrToFirst();
while(snaccExten != 0) {
AsnOid &extnId = snaccExten->extnId;
bool berEncoded = false;
AsnType *snaccObj = oidToSnaccObj(extnId);
if(snaccObj == NULL) {
snaccObj = new AsnOcts(snaccExten->extnValue);
berEncoded = true;
}
else {
CssmData cData(snaccExten->extnValue, snaccExten->extnValue.Len());
try {
SC_decodeAsnObj(cData, *snaccObj);
}
catch (...) {
errorLog0("decodeExtensions: extension decode error\n");
delete snaccObj;
snaccObj = NULL;
}
}
if(snaccObj != NULL) {
bool critical = false; if(snaccExten->critical != NULL) {
critical = *snaccExten->critical;
}
addExtension(snaccObj,
snaccExten->extnId,
critical,
berEncoded);
}
extensions->GoNext();
snaccExten = extensions->Curr();
}
}
#define MAX_EXTEN_SIZE (4 * 1024)
void DecodedCert::encodeExtensions()
{
CertificateToSign *tbs = certificateToSign;
CASSERT(mState == CS_Building);
CASSERT((tbs != NULL) && (tbs->extensions == NULL));
if(mNumExtensions == 0) {
return;
}
tbs->extensions = new Extensions;
Extensions *extns = tbs->extensions;
unsigned extenDex;
for(extenDex=0; extenDex<mNumExtensions; extenDex++) {
Extension *snaccExt = extns->Append();
DecodedExten *decodedExt = &mExtensions[extenDex];
if(decodedExt->berEncoded) {
AsnOcts *rawOcts = dynamic_cast<AsnOcts *>(decodedExt->snaccObj);
if(rawOcts == NULL) {
errorLog0("encodeExtensions: dynamic_cast failure!\n");
CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
}
snaccExt->extnValue.Set(*rawOcts);
}
else {
CssmAutoData aData(alloc);
try {
SC_encodeAsnObj(*decodedExt->snaccObj, aData, MAX_EXTEN_SIZE);
}
catch (...) {
errorLog0("encodeExtensions: extension encode error\n");
throw;
}
CssmData &cData = aData.get();
snaccExt->extnValue.Set((char *)cData.data(), cData.length());
}
snaccExt->critical = new AsnBool(decodedExt->critical);
snaccExt->extnId.Set(*decodedExt->extnId);
}
}
void DecodedCert::addExtension(
AsnType *snaccObj, const AsnOid &extnId,
bool critical,
bool berEncoded) {
if(mNumExtensions == mSizeofExtensions) {
mSizeofExtensions = mNumExtensions ?
(2 * mNumExtensions) : MIN_EXTENSIONS;
mExtensions = (DecodedExten *)alloc.realloc(
mExtensions, mSizeofExtensions * sizeof(DecodedExten));
}
DecodedExten *decodedExt = &mExtensions[mNumExtensions++];
decodedExt->extnId = new AsnOid(extnId);
decodedExt->critical = critical;
decodedExt->snaccObj = snaccObj;
decodedExt->berEncoded = berEncoded;
}
DecodedExten *DecodedCert::findDecodedExt(
const AsnOid &extnId, bool unknown, uint32 index,
uint32 &numFields) const
{
unsigned dex;
DecodedExten *decodedExt;
DecodedExten *rtnExt = NULL;
unsigned found = 0;
for(dex=0; dex<mNumExtensions; dex++) {
CASSERT(mExtensions != NULL);
decodedExt = &mExtensions[dex];
if( (!unknown && (*decodedExt->extnId == extnId)) ||
(unknown && decodedExt->berEncoded)) {
if(found++ == index) {
rtnExt = decodedExt;
}
if((rtnExt != NULL) && (index != 0)) {
break;
}
}
}
if(rtnExt != NULL) {
if(index == 0) {
numFields = found;
}
return rtnExt;
}
else {
return NULL;
}
}
static void getFieldExtenCommon(
void *cdsaObj, const DecodedExten &decodedExt,
CssmOwnedData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt;
CssmAllocator &alloc = fieldValue.allocator;
CssmData &fdata = fieldValue.get();
cssmExt = (CSSM_X509_EXTENSION_PTR)alloc.malloc(sizeof(CSSM_X509_EXTENSION));
fdata.Data = (uint8 *)cssmExt;
fdata.Length = sizeof(CSSM_X509_EXTENSION);
CL_snaccOidToCssm(*decodedExt.extnId,
CssmOid::overlay(cssmExt->extnId),
alloc);
if(decodedExt.critical != NULL) {
cssmExt->critical = decodedExt.critical ? CSSM_TRUE : CSSM_FALSE;
}
else {
cssmExt->critical = false;
}
if(decodedExt.berEncoded) {
cssmExt->format = CSSM_X509_DATAFORMAT_ENCODED;
cssmExt->value.parsedValue = NULL;
cssmExt->BERvalue = *(reinterpret_cast<CSSM_DATA_PTR>(cdsaObj));
}
else {
cssmExt->format = CSSM_X509_DATAFORMAT_PARSED;
cssmExt->value.parsedValue = cdsaObj;
cssmExt->BERvalue.Data = NULL;
cssmExt->BERvalue.Length = 0;
}
}
static CSSM_X509_EXTENSION_PTR verifySetFreeExtension(
const CssmData &fieldValue,
bool berEncoded) {
if(fieldValue.length() != sizeof(CSSM_X509_EXTENSION)) {
errorLog2("Set/FreeExtension: bad length : exp %d got %d\n",
(int)sizeof(CSSM_X509_EXTENSION), (int)fieldValue.length());
CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
}
CSSM_X509_EXTENSION_PTR cssmExt =
reinterpret_cast<CSSM_X509_EXTENSION_PTR>(fieldValue.data());
if(berEncoded) {
if((cssmExt->value.parsedValue != NULL) || (cssmExt->BERvalue.Data == NULL)) {
CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
}
}
else {
if((cssmExt->value.parsedValue == NULL) || (cssmExt->BERvalue.Data != NULL)) {
CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
}
}
return cssmExt;
}
static void freeFieldExtenCommon(
CSSM_X509_EXTENSION_PTR exten,
CssmAllocator &alloc)
{
alloc.free(exten->extnId.Data);
alloc.free(exten->BERvalue.Data); alloc.free(exten->value.parsedValue); }
static AsnType *oidToSnaccObj(
const AsnOid &extnId)
{
ExtOidCache &oc = extOidCache();
if(extnId == oc.mId_ce_keyUsage) {
return new KeyUsage;
}
else if(extnId == oc.mId_ce_basicConstraints) {
return new BasicConstraintsSyntax;
}
else if(extnId == oc.mId_ce_extKeyUsage) {
return new ExtKeyUsageSyntax;
}
else if(extnId == oc.mId_ce_subjectKeyIdentifier) {
return new AsnOcts;
}
else if(extnId == oc.mId_ce_authorityKeyIdentifier) {
return new AuthorityKeyIdentifier;
}
else if(extnId == oc.mId_ce_subjectAltName) {
return new GeneralNames;
}
else if(extnId == oc.mId_ce_certificatePolicies) {
return new CertificatePoliciesSyntax;
}
else if(extnId == oc.mId_netscape_cert_type) {
return new AsnBits;
}
else {
return NULL;
}
}
template<class SnaccType, class CdsaType>
bool GetFieldTop(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmAllocator &alloc,
const AsnOid &fieldId,
SnaccType *&snaccObj,
CdsaType *&cdsaObj,
DecodedExten *&decodedExt)
{
decodedExt = cert.findDecodedExt(fieldId, false, index, numFields);
if(decodedExt == NULL) {
return false;
}
snaccObj = dynamic_cast<SnaccType *>(decodedExt->snaccObj);
if(snaccObj == NULL) {
errorLog0("GetFieldTop: dynamic_cast failure\n");
CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
}
cdsaObj = (CdsaType *)alloc.malloc(sizeof(CdsaType));
memset(cdsaObj, 0, sizeof(CdsaType));
return true;
}
void freeFieldSimpleExtension (
CssmOwnedData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
freeFieldExtenCommon(cssmExt, fieldValue.allocator);
}
void setFieldKeyUsage(
DecodedCert &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
CE_KeyUsage *cdsaObj = (CE_KeyUsage *)cssmExt->value.parsedValue;
char bits[sizeof(CE_KeyUsage)];
bits[0] = static_cast<char>((*cdsaObj) >> 8);
bits[1] = static_cast<char>(*cdsaObj);
memmove(bits, cdsaObj, sizeof(CE_KeyUsage));
KeyUsage *snaccObj = new KeyUsage(bits, sizeof(CE_KeyUsage) * 8);
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
}
bool getFieldKeyUsage(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
DecodedExten *decodedExt;
KeyUsage *snaccObj;
CE_KeyUsage *cdsaObj;
bool brtn;
brtn = GetFieldTop<KeyUsage, CE_KeyUsage>(
cert,
index,
numFields,
fieldValue.allocator,
id_ce_keyUsage,
snaccObj,
cdsaObj,
decodedExt);
if(!brtn) {
return false;
}
unsigned toCopy = (snaccObj->BitLen() + 7) / 8;
if(toCopy > 2) {
errorLog0("getFieldKeyUsage: KeyUsage larger than 2 bytes!\n");
toCopy = 2;
}
unsigned char bits[2] = {0, 0};
memmove(bits, snaccObj->BitOcts(), toCopy);
*cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
return true;
}
void setFieldBasicConstraints(
DecodedCert &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
BasicConstraintsSyntax *snaccObj = new BasicConstraintsSyntax;
CE_BasicConstraints *cdsaObj = (CE_BasicConstraints *)cssmExt->value.parsedValue;
snaccObj->cA = new AsnBool(cdsaObj->cA ? true : false);
if(cdsaObj->pathLenConstraintPresent) {
AsnIntType val = cdsaObj->pathLenConstraint;
snaccObj->pathLenConstraint = new AsnInt(val);
}
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
}
bool getFieldBasicConstraints(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
DecodedExten *decodedExt;
BasicConstraintsSyntax *snaccObj;
CE_BasicConstraints *cdsaObj;
bool brtn;
brtn = GetFieldTop<BasicConstraintsSyntax, CE_BasicConstraints>(
cert,
index,
numFields,
fieldValue.allocator,
id_ce_basicConstraints,
snaccObj,
cdsaObj,
decodedExt);
if(!brtn) {
return false;
}
if(snaccObj->cA == NULL) {
cdsaObj->cA = CSSM_FALSE;
}
else {
bool val = *snaccObj->cA;
cdsaObj->cA = val ? CSSM_TRUE : CSSM_FALSE;
}
if(snaccObj->pathLenConstraint == NULL) {
cdsaObj->pathLenConstraintPresent = CSSM_FALSE;
cdsaObj->pathLenConstraint = 0;
}
else {
cdsaObj->pathLenConstraintPresent = CSSM_TRUE;
AsnIntType val = *snaccObj->pathLenConstraint;
cdsaObj->pathLenConstraint = val;
}
getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
return true;
}
void setFieldExtKeyUsage(
DecodedCert &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
ExtKeyUsageSyntax *snaccObj = new ExtKeyUsageSyntax;
CE_ExtendedKeyUsage *cdsaObj = (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
unsigned oidDex;
for(oidDex=0; oidDex<cdsaObj->numPurposes; oidDex++) {
KeyPurposeId *snaccPurp = snaccObj->Append();
CSSM_OID_PTR cdsaPurp = &cdsaObj->purposes[oidDex];
snaccPurp->Set(reinterpret_cast<char *>(cdsaPurp->Data), cdsaPurp->Length);
}
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
}
bool getFieldExtKeyUsage(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
DecodedExten *decodedExt;
ExtKeyUsageSyntax *snaccObj;
CE_ExtendedKeyUsage *cdsaObj;
bool brtn;
brtn = GetFieldTop<ExtKeyUsageSyntax, CE_ExtendedKeyUsage>(
cert,
index,
numFields,
fieldValue.allocator,
id_ce_extKeyUsage,
snaccObj,
cdsaObj,
decodedExt);
if(!brtn) {
return false;
}
CssmAllocator &alloc = fieldValue.allocator;
cdsaObj->numPurposes = snaccObj->Count();
cdsaObj->purposes = (CSSM_OID_PTR)alloc.malloc(cdsaObj->numPurposes *
sizeof(CSSM_OID));
snaccObj->SetCurrToFirst();
unsigned oidDex;
for(oidDex=0; oidDex<cdsaObj->numPurposes; oidDex++) {
CL_snaccOidToCssm(*snaccObj->Curr(),
CssmOid::overlay(cdsaObj->purposes[oidDex]),
alloc);
snaccObj->GoNext();
}
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; oidDex<cdsaObj->numPurposes; oidDex++) {
alloc.free(cdsaObj->purposes[oidDex].Data);
}
alloc.free(cdsaObj->purposes);
freeFieldExtenCommon(cssmExt, alloc); }
void setFieldSubjectKeyId(
DecodedCert &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue;
AsnOcts *snaccObj = new AsnOcts((char *)cdsaObj->Data, cdsaObj->Length);
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
}
bool getFieldSubjectKeyId(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
DecodedExten *decodedExt;
AsnOcts *snaccObj;
CE_SubjectKeyID *cdsaObj;
bool brtn;
brtn = GetFieldTop<AsnOcts, CE_SubjectKeyID>(
cert,
index,
numFields,
fieldValue.allocator,
id_ce_subjectKeyIdentifier,
snaccObj,
cdsaObj,
decodedExt);
if(!brtn) {
return false;
}
CL_AsnOctsToCssmData(*snaccObj, *cdsaObj, fieldValue.allocator);
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); }
void setFieldAuthorityKeyId(
DecodedCert &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
AuthorityKeyIdentifier *snaccObj = new AuthorityKeyIdentifier;
if(cdsaObj->keyIdentifierPresent) {
snaccObj->keyIdentifier = new AsnOcts((char *)cdsaObj->keyIdentifier.Data,
cdsaObj->keyIdentifier.Length);
}
if(cdsaObj->generalNamesPresent ) {
snaccObj->authorityCertIssuer = CL_cdsaGeneralNamesToSnacc(
*cdsaObj->generalNames);
}
if(cdsaObj->serialNumberPresent) {
snaccObj->authorityCertSerialNumber =
new CertificateSerialNumber((char *)cdsaObj->serialNumber.Data,
cdsaObj->serialNumber.Length);
}
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
}
bool getFieldAuthorityKeyId(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
DecodedExten *decodedExt;
AuthorityKeyIdentifier *snaccObj;
CE_AuthorityKeyID *cdsaObj;
bool brtn;
CssmAllocator &alloc = fieldValue.allocator;
brtn = GetFieldTop<AuthorityKeyIdentifier, CE_AuthorityKeyID>(
cert,
index,
numFields,
alloc,
id_ce_authorityKeyIdentifier,
snaccObj,
cdsaObj,
decodedExt);
if(!brtn) {
return false;
}
if(snaccObj->keyIdentifier != NULL) {
cdsaObj->keyIdentifierPresent = CSSM_TRUE;
CL_AsnOctsToCssmData(*snaccObj->keyIdentifier,
cdsaObj->keyIdentifier,
alloc);
}
if(snaccObj->authorityCertIssuer != NULL) {
cdsaObj->generalNamesPresent = CSSM_TRUE;
cdsaObj->generalNames = (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralName));
CL_snaccGeneralNamesToCdsa(*snaccObj->authorityCertIssuer,
*cdsaObj->generalNames,
alloc);
}
if(snaccObj->authorityCertSerialNumber != NULL) {
cdsaObj->serialNumberPresent = CSSM_TRUE;
CL_AsnOctsToCssmData(*snaccObj->authorityCertSerialNumber,
cdsaObj->serialNumber,
alloc);
}
getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
return true;
}
static void freeFieldGeneralNames(
CE_GeneralNames *cdsaObj,
CssmAllocator &alloc)
{
if(cdsaObj == NULL) {
return;
}
for(unsigned i=0; i<cdsaObj->numNames; i++) {
alloc.free(cdsaObj->generalName[i].name.Data);
}
if(cdsaObj->numNames) {
memset(cdsaObj->generalName, 0, cdsaObj->numNames * sizeof(CE_GeneralName));
}
memset(cdsaObj, 0, sizeof(CE_GeneralNames));
}
void freeFieldAuthorityKeyId (
CssmOwnedData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
CssmAllocator &alloc = fieldValue.allocator;
CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
alloc.free(cdsaObj->keyIdentifier.Data);
freeFieldGeneralNames(cdsaObj->generalNames, alloc);
alloc.free(cdsaObj->serialNumber.Data);
memset(cdsaObj, 0, sizeof(CE_AuthorityKeyID));
freeFieldExtenCommon(cssmExt, alloc); }
void setFieldSubjAltName(
DecodedCert &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
GeneralNames *snaccObj = CL_cdsaGeneralNamesToSnacc(*cdsaObj);
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
}
bool getFieldSubjAltName(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
DecodedExten *decodedExt;
GeneralNames *snaccObj;
CE_GeneralNames *cdsaObj;
bool brtn;
brtn = GetFieldTop<GeneralNames, CE_GeneralNames>(
cert,
index,
numFields,
fieldValue.allocator,
id_ce_subjectAltName,
snaccObj,
cdsaObj,
decodedExt);
if(!brtn) {
return false;
}
CL_snaccGeneralNamesToCdsa(*snaccObj, *cdsaObj, fieldValue.allocator);
getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
return true;
}
void freeFieldSubjAltName (
CssmOwnedData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
CssmAllocator &alloc = fieldValue.allocator;
CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
freeFieldGeneralNames(cdsaObj, alloc);
freeFieldExtenCommon(cssmExt, alloc); }
#define MAX_IA5_NAME_SIZE 1024
void setFieldCertPolicies(
DecodedCert &cert,
const CssmData &fieldValue)
{
CssmAllocator &alloc = CssmAllocator::standard();
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
CertificatePoliciesSyntax *snaccObj = new CertificatePoliciesSyntax;
CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue;
for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
PolicyInformation *sPolInfo = snaccObj->Append();
sPolInfo->policyIdentifier.Set((char *)cPolInfo->certPolicyId.Data,
cPolInfo->certPolicyId.Length);
if(cPolInfo->numPolicyQualifiers != 0) {
sPolInfo->policyQualifiers = new PolicyInformationSeqOf;
}
for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; qualDex++) {
CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex];
PolicyQualifierInfo *sQualInfo = sPolInfo->policyQualifiers->Append();
sQualInfo->policyQualifierId.Set(
(char *)cQualInfo->policyQualifierId.Data,
cQualInfo->policyQualifierId.Length);
uint8 *rawData = cQualInfo->qualifier.Data;
unsigned rawDataLen = cQualInfo->qualifier.Length;
CssmAutoData aData(alloc);
if(sQualInfo->policyQualifierId == id_qt_cps) {
IA5String *ia5 = new IA5String((char *)rawData, rawDataLen);
SC_encodeAsnObj(*ia5, aData, MAX_IA5_NAME_SIZE);
delete ia5;
}
else {
aData.copy(rawData, rawDataLen);
}
sQualInfo->qualifier = new AsnAny;
char *cp = aData;
sQualInfo->qualifier->value = new CSM_Buffer(cp, aData.length());
aData.reset();
}
}
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
}
bool getFieldCertPolicies(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
DecodedExten *decodedExt;
CertificatePoliciesSyntax *snaccObj;
CE_CertPolicies *cdsaObj;
bool brtn;
CssmAllocator &alloc = fieldValue.allocator;
brtn = GetFieldTop<CertificatePoliciesSyntax, CE_CertPolicies>(
cert,
index,
numFields,
fieldValue.allocator,
id_ce_certificatePolicies,
snaccObj,
cdsaObj,
decodedExt);
if(!brtn) {
return false;
}
cdsaObj->numPolicies = snaccObj->Count();
unsigned sz = cdsaObj->numPolicies * sizeof(CE_PolicyInformation);
cdsaObj->policies = (CE_PolicyInformation *)alloc.malloc(sz);
memset(cdsaObj->policies, 0, sz);
snaccObj->SetCurrToFirst();
for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
PolicyInformation *sPolInfo = snaccObj->Curr();
CssmOid &cOid = CssmOid::overlay(cPolInfo->certPolicyId);
CL_snaccOidToCssm(sPolInfo->policyIdentifier, cOid, alloc);
if(sPolInfo->policyQualifiers == NULL) {
continue;
}
cPolInfo->numPolicyQualifiers = sPolInfo->policyQualifiers->Count();
cPolInfo->policyQualifiers = (CE_PolicyQualifierInfo *)
alloc.malloc(cPolInfo->numPolicyQualifiers *
sizeof(CE_PolicyQualifierInfo));
sPolInfo->policyQualifiers->SetCurrToFirst();
for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; qualDex++) {
PolicyQualifierInfo *sQualInfo = sPolInfo->policyQualifiers->Curr();
CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex];
CssmOid &cOid2 = CssmOid::overlay(cQualInfo->policyQualifierId);
CL_snaccOidToCssm(sQualInfo->policyQualifierId, cOid2, alloc);
CSM_Buffer *cbuf = sQualInfo->qualifier->value;
CssmRemoteData outData(alloc, cQualInfo->qualifier);
if(sQualInfo->policyQualifierId == id_qt_cps) {
IA5String ia5;
CssmAutoData berData(alloc, cbuf->Access(), cbuf->Length());
SC_decodeAsnObj(berData, ia5);
char *src = ia5;
outData.copy(src, ia5.Len());
}
else {
outData.copy(cbuf->Access(), cbuf->Length());
}
outData.release();
sPolInfo->policyQualifiers->GoNext();
}
snaccObj->GoNext();
}
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; 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); }
void setFieldNetscapeCertType(
DecodedCert &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
CE_NetscapeCertType *cdsaObj = (CE_NetscapeCertType *)cssmExt->value.parsedValue;
char bits[sizeof(CE_NetscapeCertType)];
bits[0] = static_cast<char>((*cdsaObj) >> 8);
bits[1] = static_cast<char>(*cdsaObj);
memmove(bits, cdsaObj, sizeof(CE_NetscapeCertType));
AsnBits *snaccObj = new AsnBits(bits, sizeof(CE_NetscapeCertType) * 8);
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
}
bool getFieldNetscapeCertType(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
DecodedExten *decodedExt;
AsnBits *snaccObj;
CE_NetscapeCertType *cdsaObj;
bool brtn;
brtn = GetFieldTop<AsnBits, CE_NetscapeCertType>(
cert,
index,
numFields,
fieldValue.allocator,
id_netscape_cert_type,
snaccObj,
cdsaObj,
decodedExt);
if(!brtn) {
return false;
}
unsigned toCopy = (snaccObj->BitLen() + 7) / 8;
if(toCopy > 2) {
errorLog0("getFieldNetscapeCertType: bitstring larger than 2 bytes!\n");
toCopy = 2;
}
unsigned char bits[2] = {0, 0};
memmove(bits, snaccObj->BitOcts(), toCopy);
*cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
return true;
}
void setFieldUnknownExt(
DecodedCert &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
AsnOcts *snaccObj = new AsnOcts(
reinterpret_cast<char *>(cssmExt->BERvalue.Data),
cssmExt->BERvalue.Length);
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, true);
}
bool getFieldUnknownExt(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
AsnOid noOidLikeThis (1, 2); DecodedExten *decodedExt = cert.findDecodedExt(noOidLikeThis,
true, index, numFields);
if(decodedExt == NULL) {
return false;
}
AsnOcts *snaccObj = dynamic_cast<AsnOcts *>(decodedExt->snaccObj);
if(snaccObj == NULL) {
errorLog0("getFieldUnknownExt: dynamic_cast failure\n");
CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
}
char *octData = *snaccObj;
CssmAutoData encodedBytes(fieldValue.allocator, octData, snaccObj->Len());
CssmData cData = encodedBytes.release();
getFieldExtenCommon(&cData, *decodedExt, fieldValue);
return true;
}
void freeFieldUnknownExt (
CssmOwnedData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
CssmAllocator &alloc = fieldValue.allocator;
freeFieldExtenCommon(cssmExt, alloc); }
#if template_pcode
void setFieldSomeExt(
DecodedCert &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
new an approppriate AsnType snaccObj (KeyUsage, etc.);
extension-specific e.g. CE_KeyUsage *cdsaObj = cssmExt->value.parsedValue;
...
cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
}
bool getFieldSomeExt(
const DecodedCert &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
DecodedExten *decodedExt;
e.g. ExtKeyUsageSyntax *snaccObj;
e.g. CE_ExtendedKeyUsage *cdsaObj;
bool brtn;
brtn = GetFieldTop<ExtKeyUsageSyntax, CE_ExtendedKeyUsage>(
cert,
index,
numFields,
fieldValue.allocator,
e.g. id_ce_extKeyUsage,
snaccObj,
cdsaObj,
decodedExt);
if(!brtn) {
return false;
}
brute force snaccObj --> cdsaObj;
getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
return true;
}
void freeFieldSomeExt (
CssmOwnedData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
CssmAllocator &alloc = fieldValue.allocator;
free the stuff in cssmExt->value.parsedValue;
freeFieldExtenCommon(cssmExt, alloc); }
#endif