CLFieldsCommon.cpp [plain text]
#include "CLFieldsCommon.h"
#include "clNameUtils.h"
#include "clNssUtils.h"
#include "AppleX509CLSession.h"
#include <Security/cssmapple.h>
#include <Security/oidscert.h>
#include <Security/nameTemplates.h>
#include <Security/certExtensionTemplates.h>
#include <Security/SecAsn1Templates.h>
typedef struct {
const CSSM_OID &oid;
unsigned nssObjLen;
const SecAsn1Template *templ;
} NssExtenInfo;
static const NssExtenInfo nssExtenInfo[] = {
{ CSSMOID_KeyUsage,
sizeof(CSSM_DATA),
kSecAsn1KeyUsageTemplate },
{ CSSMOID_BasicConstraints,
sizeof(NSS_BasicConstraints),
kSecAsn1BasicConstraintsTemplate },
{ CSSMOID_ExtendedKeyUsage,
sizeof(NSS_ExtKeyUsage),
kSecAsn1ExtKeyUsageTemplate },
{ CSSMOID_SubjectKeyIdentifier,
sizeof(CSSM_DATA),
kSecAsn1SubjectKeyIdTemplate },
{ CSSMOID_AuthorityKeyIdentifier,
sizeof(NSS_AuthorityKeyId),
kSecAsn1AuthorityKeyIdTemplate },
{ CSSMOID_SubjectAltName,
sizeof(NSS_GeneralNames),
kSecAsn1GeneralNamesTemplate },
{ CSSMOID_IssuerAltName,
sizeof(NSS_GeneralNames),
kSecAsn1GeneralNamesTemplate },
{ CSSMOID_CertificatePolicies,
sizeof(NSS_CertPolicies),
kSecAsn1CertPoliciesTemplate },
{ CSSMOID_NetscapeCertType,
sizeof(CSSM_DATA),
kSecAsn1NetscapeCertTypeTemplate },
{ CSSMOID_CrlDistributionPoints,
sizeof(NSS_CRLDistributionPoints),
kSecAsn1CRLDistributionPointsTemplate },
{ CSSMOID_CertIssuer,
sizeof(NSS_GeneralNames),
kSecAsn1GeneralNamesTemplate },
{ CSSMOID_AuthorityInfoAccess,
sizeof(NSS_AuthorityInfoAccess),
kSecAsn1AuthorityInfoAccessTemplate },
{ CSSMOID_SubjectInfoAccess,
sizeof(NSS_AuthorityInfoAccess),
kSecAsn1AuthorityInfoAccessTemplate },
{ CSSMOID_CrlNumber,
sizeof(CSSM_DATA),
kSecAsn1IntegerTemplate },
{ CSSMOID_IssuingDistributionPoint,
sizeof(NSS_IssuingDistributionPoint),
kSecAsn1IssuingDistributionPointTemplate },
{ CSSMOID_HoldInstructionCode,
sizeof(CSSM_OID),
kSecAsn1ObjectIDTemplate },
{ CSSMOID_CrlReason,
sizeof(CSSM_DATA),
kSecAsn1EnumeratedTemplate },
{ CSSMOID_DeltaCrlIndicator,
sizeof(CSSM_DATA),
kSecAsn1IntegerTemplate },
{ CSSMOID_InvalidityDate,
sizeof(CSSM_DATA),
kSecAsn1GeneralizedTimeTemplate },
{ CSSMOID_QC_Statements,
sizeof(NSS_QC_Statements),
kSecAsn1QC_StatementsTemplate },
{ CSSMOID_NameConstraints,
sizeof(NSS_NameConstraints),
kSecAsn1NameConstraintsTemplate },
{ CSSMOID_PolicyMappings,
sizeof(NSS_PolicyMappings),
kSecAsn1PolicyMappingsTemplate },
{ CSSMOID_PolicyConstraints,
sizeof(NSS_PolicyConstraints),
kSecAsn1PolicyConstraintsTemplate },
{ CSSMOID_InhibitAnyPolicy,
sizeof(CSSM_DATA),
kSecAsn1IntegerTemplate },
};
#define NUM_NSS_EXTEN_INFOS (sizeof(nssExtenInfo) / sizeof(nssExtenInfo[0]))
bool clOidToNssInfo(
const CSSM_OID &oid,
unsigned &nssObjLen, const SecAsn1Template *&templ) {
for(unsigned dex=0; dex<NUM_NSS_EXTEN_INFOS; dex++) {
const NssExtenInfo &info = nssExtenInfo[dex];
if(clCompareCssmData(&info.oid, &oid)) {
nssObjLen = info.nssObjLen;
templ = info.templ;
return true;
}
}
return false;
}
void getFieldExtenCommon(
void *cdsaObj, const DecodedExten &decodedExt,
CssmOwnedData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt;
Allocator &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);
decodedExt.convertToCdsa(cdsaObj, cssmExt, alloc);
}
CSSM_X509_EXTENSION_PTR verifySetFreeExtension(
const CssmData &fieldValue,
bool berEncoded) {
if(fieldValue.length() != sizeof(CSSM_X509_EXTENSION)) {
clFieldLog("Set/FreeExtension: bad length : exp %d got %d",
(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->BERvalue.Data == NULL) {
CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
}
}
else {
if(cssmExt->value.parsedValue == NULL) {
CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
}
}
return cssmExt;
}
void freeFieldExtenCommon(
CSSM_X509_EXTENSION_PTR exten,
Allocator &alloc)
{
alloc.free(exten->extnId.Data);
alloc.free(exten->BERvalue.Data); alloc.free(exten->value.parsedValue); }
void freeFieldSimpleExtension (
CssmOwnedData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
false);
freeFieldExtenCommon(cssmExt, fieldValue.allocator);
}
bool getField_RDN_NSS (
const NSS_Name &nssName,
CssmOwnedData &fieldValue) {
Allocator &alloc = fieldValue.allocator;
fieldValue.malloc(sizeof(CSSM_X509_NAME));
CSSM_X509_NAME_PTR cssmName = (CSSM_X509_NAME_PTR)fieldValue.data();
CL_nssNameToCssm(nssName, *cssmName, alloc);
return true;
}
void freeField_RDN (
CssmOwnedData &fieldValue)
{
if(fieldValue.data() == NULL) {
return;
}
if(fieldValue.length() != sizeof(CSSM_X509_NAME)) {
CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
}
Allocator &alloc = fieldValue.allocator;
CSSM_X509_NAME_PTR x509Name = (CSSM_X509_NAME_PTR)fieldValue.data();
CL_freeX509Name(x509Name, alloc);
}
bool getField_normRDN_NSS (
const CSSM_DATA &derName,
uint32 &numFields, CssmOwnedData &fieldValue) {
if(derName.Data == NULL) {
return false;
}
SecNssCoder coder;
NSS_Name decodedName;
memset(&decodedName, 0, sizeof(decodedName));
PRErrorCode prtn = coder.decodeItem(derName, kSecAsn1NameTemplate, &decodedName);
if(prtn) {
clErrorLog("getField_normRDN decode error\n");
CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
}
CL_normalizeX509NameNSS(decodedName, coder);
prtn = SecNssEncodeItemOdata(&decodedName, kSecAsn1NameTemplate, fieldValue);
if(prtn) {
clErrorLog("getField_normRDN encode error\n");
CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
}
numFields = 1;
return true;
}
bool getField_TimeNSS (
const NSS_Time &nssTime,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue) {
if(!tbsGetCheck(nssTime.item.Data, index)) {
return false;
}
Allocator &alloc = fieldValue.allocator;
fieldValue.malloc(sizeof(CSSM_X509_TIME));
CSSM_X509_TIME *cssmTime =
(CSSM_X509_TIME *)fieldValue.data();
if(CL_nssTimeToCssm(nssTime, *cssmTime, alloc)) {
numFields = 1;
return true;
}
else {
return false;
}
}
void setField_TimeNSS (
const CssmData &fieldValue,
NSS_Time &nssTime,
SecNssCoder &coder)
{
CSSM_X509_TIME *cssmTime =
(CSSM_X509_TIME *)fieldValue.data();
CL_cssmTimeToNss(*cssmTime, nssTime, coder);
}
void freeField_Time (
CssmOwnedData &fieldValue)
{
CSSM_X509_TIME *cssmTime = (CSSM_X509_TIME *)fieldValue.data();
if(cssmTime == NULL) {
return;
}
if(fieldValue.length() != sizeof(CSSM_X509_TIME)) {
CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
}
CL_freeCssmTime(cssmTime, fieldValue.allocator);
}
void getField_AlgIdNSS (
const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId,
CssmOwnedData &fieldValue) {
Allocator &alloc = fieldValue.allocator;
fieldValue.malloc(sizeof(CSSM_X509_ALGORITHM_IDENTIFIER));
CSSM_X509_ALGORITHM_IDENTIFIER *destAlgId =
(CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data();
CL_copyAlgId(srcAlgId, *destAlgId, alloc);
}
void setField_AlgIdNSS (
const CssmData &fieldValue,
CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId,
SecNssCoder &coder)
{
CSSM_X509_ALGORITHM_IDENTIFIER *srcAlgId =
(CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data();
ArenaAllocator areanAlloc(coder);
CL_copyAlgId(*srcAlgId, dstAlgId, areanAlloc);
}
void freeField_AlgId (
CssmOwnedData &fieldValue)
{
CSSM_X509_ALGORITHM_IDENTIFIER *cssmAlgId =
(CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data();
if(cssmAlgId == NULL) {
return;
}
if(fieldValue.length() != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)) {
CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
}
Allocator &alloc = fieldValue.allocator;
alloc.free(cssmAlgId->algorithm.Data);
alloc.free(cssmAlgId->parameters.Data);
memset(cssmAlgId, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER));
}
void tbsSetCheck(
void *fieldToSet,
const CssmData &fieldValue,
uint32 expLength,
const char *op)
{
if(fieldToSet != NULL) {
clErrorLog("setField(%s): field already set", op);
CssmError::throwMe(CSSMERR_CL_INVALID_NUMBER_OF_FIELDS);
}
if((expLength != 0) && (fieldValue.length() != expLength)) {
clErrorLog("setField(%s): bad length : exp %d got %d",
op, (int)expLength, (int)fieldValue.length());
CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
}
}
bool tbsGetCheck(
const void *requiredField,
uint32 reqIndex)
{
if((requiredField == NULL) || (reqIndex != 0)) {
return false;
}
else {
return true;
}
}
void setFieldUnknownExt(
DecodedItem &cert,
const CssmData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
SecNssCoder &coder = cert.coder();
CSSM_DATA *rawExtn = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
coder.allocCopyItem(cssmExt->BERvalue, *rawExtn);
cert.addExtension(NULL, cssmExt->extnId, cssmExt->critical,
true, NULL , rawExtn);
}
bool getFieldUnknownExt(
DecodedItem &cert,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue)
{
uint8 noOidDataLikeThis[2] = {1, 2}; CSSM_OID noOidLikeThis = {2, noOidDataLikeThis};
const DecodedExten *decodedExt =
cert.DecodedItem::findDecodedExt(noOidLikeThis,
true, index, numFields);
if(decodedExt == NULL) {
return false;
}
getFieldExtenCommon(NULL, *decodedExt, fieldValue);
return true;
}
void freeFieldUnknownExt (
CssmOwnedData &fieldValue)
{
CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
Allocator &alloc = fieldValue.allocator;
freeFieldExtenCommon(cssmExt, alloc); }
void setField_ReadOnly (
DecodedItem &item,
const CssmData &fieldValue)
{
clErrorLog("Attempt to set a read-only field");
CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
}
bool getField_Unimplemented (
DecodedItem &item,
unsigned index, uint32 &numFields, CssmOwnedData &fieldValue) {
clErrorLog("Attempt to get an unimplemented field");
CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
}