certGroupUtils.cpp [plain text]
#include <Security/cssmtype.h>
#include <Security/cssmapi.h>
#include <Security/x509defs.h>
#include <Security/oidscert.h>
#include <Security/oidsalg.h>
#include <Security/cssmapple.h>
#include "certGroupUtils.h"
#include "cldebugging.h"
#include "tpTime.h"
#include <string.h>
#if 0
void *tpCalloc(CssmAllocator &alloc, uint32 num, uint32 size)
{
void *p = alloc.malloc(num * size);
memset(p, 0, num* size);
return p;
}
#endif
void tpCopyCssmData(
CssmAllocator &alloc,
const CSSM_DATA *src,
CSSM_DATA_PTR dst)
{
dst->Data = (uint8 *)alloc.malloc(src->Length);
dst->Length = src->Length;
memmove(dst->Data, src->Data, src->Length);
}
CSSM_DATA_PTR tpMallocCopyCssmData(
CssmAllocator &alloc,
const CSSM_DATA *src)
{
CSSM_DATA_PTR dst = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA));
tpCopyCssmData(alloc, src, dst);
return dst;
}
void tpFreeCssmData(
CssmAllocator &alloc,
CSSM_DATA_PTR data,
CSSM_BOOL freeStruct)
{
if(data == NULL) {
return;
}
if(data->Length != 0) {
tpFree(alloc, data->Data);
}
if(freeStruct) {
tpFree(alloc, data);
}
else {
data->Length = 0;
data->Data = NULL;
}
}
CSSM_BOOL tpCompareCssmData(
const CSSM_DATA *data1,
const CSSM_DATA *data2)
{
if((data1 == NULL) || (data1->Data == NULL) ||
(data2 == NULL) || (data2->Data == NULL) ||
(data1->Length != data2->Length)) {
return CSSM_FALSE;
}
if(data1->Length != data2->Length) {
return CSSM_FALSE;
}
if(memcmp(data1->Data, data2->Data, data1->Length) == 0) {
return CSSM_TRUE;
}
else {
return CSSM_FALSE;
}
}
CSSM_BOOL tpCompareOids(
const CSSM_OID *oid1,
const CSSM_OID *oid2)
{
return tpCompareCssmData(oid1, oid2);
}
CSSM_DATA_PTR tp_CertGetPublicKey(
TPCertInfo *cert,
CSSM_DATA_PTR *valueToFree) {
CSSM_RETURN crtn;
CSSM_DATA_PTR val;
CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *keyInfo;
*valueToFree = NULL;
crtn = cert->fetchField(&CSSMOID_X509V1SubjectPublicKeyCStruct, &val);
if(crtn) {
errorLog0("Error on CSSM_CL_CertGetFirstFieldValue(PublicKeyCStruct)\n");
return NULL;
}
*valueToFree = val;
keyInfo = (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)val->Data;
return &keyInfo->subjectPublicKey;
}
void tp_CertFreePublicKey(
CSSM_CL_HANDLE clHand,
CSSM_DATA_PTR value)
{
CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SubjectPublicKeyCStruct, value);
}
CSSM_X509_ALGORITHM_IDENTIFIER_PTR tp_CertGetAlgId(
TPCertInfo *cert,
CSSM_DATA_PTR *valueToFree) {
CSSM_RETURN crtn;
CSSM_DATA_PTR val;
*valueToFree = NULL;
crtn = cert->fetchField(&CSSMOID_X509V1SignatureAlgorithm, &val);
if(crtn) {
errorLog0("Error on fetchField(CSSMOID_X509V1SignatureAlgorithm)\n");
return NULL;
}
*valueToFree = val;
return (CSSM_X509_ALGORITHM_IDENTIFIER_PTR)val->Data;
}
void tp_CertFreeAlgId(
CSSM_CL_HANDLE clHand,
CSSM_DATA_PTR value)
{
CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SignatureAlgorithm, value);
}
CSSM_BOOL tpIsSameName(
const CSSM_DATA *name1,
const CSSM_DATA *name2)
{
return tpCompareCssmData(name1, name2);
}
CSSM_RETURN tp_VerifyCert(
CSSM_CL_HANDLE clHand,
CSSM_CSP_HANDLE cspHand,
TPCertInfo *subjectCert,
TPCertInfo *issuerCert,
CSSM_BOOL checkIssuerCurrent,
CSSM_BOOL allowExpired) {
CSSM_RETURN crtn;
crtn = CSSM_CL_CertVerify(clHand,
CSSM_INVALID_HANDLE,
subjectCert->certData(),
issuerCert->certData(),
NULL, 0); if(crtn == CSSM_OK) {
#if TP_CERT_CURRENT_CHECK_INLINE
if(checkIssuerCurrent) {
crtn = issuerCert->isCurrent(allowExpired);
}
#endif
}
else {
crtn = CSSMERR_TP_VERIFICATION_FAILURE;
}
return crtn;
}
CSSM_BOOL tp_CompareCerts(
const CSSM_DATA *cert1,
const CSSM_DATA *cert2)
{
return tpCompareCssmData(cert1, cert2);
}
#if TP_DL_ENABLE
static CSSM_DB_UNIQUE_RECORD_PTR tpCertLookup(
CSSM_DL_DB_HANDLE dlDb,
const CSSM_DATA *subjectName, CSSM_HANDLE_PTR resultHand,
CSSM_DATA_PTR cert) {
CSSM_QUERY query;
CSSM_SELECTION_PREDICATE predicate;
CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
cert->Data = NULL;
cert->Length = 0;
predicate.DbOperator = CSSM_DB_EQUAL;
predicate.Attribute.Info.AttributeNameFormat =
CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
predicate.Attribute.Info.Label.AttributeName = "Subject";
predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
predicate.Attribute.Value = const_cast<CSSM_DATA_PTR>(subjectName);
predicate.Attribute.NumberOfValues = 1;
query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE;
query.Conjunctive = CSSM_DB_NONE;
query.NumSelectionPredicates = 1;
query.SelectionPredicate = &predicate;
query.QueryLimits.TimeLimit = 0; query.QueryLimits.SizeLimit = 1; query.QueryFlags = 0;
CSSM_DL_DataGetFirst(dlDb,
&query,
resultHand,
NULL, cert,
&record);
return record;
}
TPCertInfo *tpFindIssuer(
CssmAllocator &alloc,
CSSM_CL_HANDLE clHand,
CSSM_CSP_HANDLE cspHand,
TPCertInfo *subjectCert,
const CSSM_DATA *issuerName, const CSSM_DL_DB_LIST *dbList,
const char *cssmTimeStr, CSSM_RETURN *issuerExpired) {
uint32 dbDex;
CSSM_HANDLE resultHand;
CSSM_DATA_PTR cert; CSSM_DL_DB_HANDLE dlDb;
CSSM_DB_UNIQUE_RECORD_PTR record;
TPCertInfo *issuerCert = NULL;
*issuerExpired = CSSM_OK;
if(dbList == NULL) {
return NULL;
}
cert = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA));
cert->Data = NULL;
cert->Length = 0;
for(dbDex=0; dbDex<dbList->NumHandles; dbDex++) {
dlDb = dbList->DLDBHandle[dbDex];
record = tpCertLookup(dlDb,
issuerName,
&resultHand,
cert);
if(record != NULL) {
issuerCert = new TPCertInfo(cert, clHand, cssmTimeStr, CSSM_TRUE);
if(tp_VerifyCert(clHand,
cspHand,
subjectCert,
issuerCert,
CSSM_FALSE, CSSM_FALSE)) {
delete issuerCert;
issuerCert = NULL;
if((*issuerExpired) != CSSM_OK) {
CSSM_DL_DataAbortQuery(dlDb, resultHand);
goto abort;
}
for(;;) {
tpFreeCssmData(alloc, cert, CSSM_FALSE);
CSSM_RETURN crtn = CSSM_DL_DataGetNext(dlDb,
resultHand,
NULL, cert,
&record);
if(crtn) {
break;
}
issuerCert = new TPCertInfo(cert, clHand, cssmTimeStr,
CSSM_TRUE);
if(tp_VerifyCert(clHand,
cspHand,
subjectCert,
issuerCert,
CSSM_FALSE,
CSSM_FALSE)) {
break;
}
delete issuerCert;
issuerCert = NULL;
}
}
if(issuerCert != NULL) {
CSSM_DL_DataAbortQuery(dlDb, resultHand);
issuerCert->dlDbHandle(dlDb);
issuerCert->uniqueRecord(record);
return issuerCert;
}
}
CSSM_DL_DataAbortQuery(dlDb, resultHand);
}
abort:
tpFreeCssmData(alloc, cert, CSSM_TRUE);
return NULL;
}
#endif
CSSM_ALGORITHMS tpOidToAldId(
const CSSM_OID *oid,
CSSM_ALGORITHMS *keyAlg) {
*keyAlg = CSSM_ALGID_RSA; if(tpCompareOids(oid, &CSSMOID_MD2WithRSA)) {
return CSSM_ALGID_MD2WithRSA;
}
else if(tpCompareOids(oid, &CSSMOID_MD5WithRSA)) {
return CSSM_ALGID_MD5WithRSA;
}
else if(tpCompareOids(oid, &CSSMOID_SHA1WithRSA)) {
return CSSM_ALGID_SHA1WithRSA;
}
else if(tpCompareOids(oid, &CSSMOID_SHA1WithDSA)) {
*keyAlg = CSSM_ALGID_DSA;
return CSSM_ALGID_SHA1WithDSA;
}
else if(tpCompareOids(oid, &CSSMOID_APPLE_FEE_MD5)) {
*keyAlg = CSSM_ALGID_FEE;
return CSSM_ALGID_FEE_MD5;
}
else if(tpCompareOids(oid, &CSSMOID_APPLE_FEE_SHA1)) {
*keyAlg = CSSM_ALGID_FEE;
return CSSM_ALGID_FEE_SHA1;
}
else if(tpCompareOids(oid, &CSSMOID_APPLE_ECDSA)) {
*keyAlg = CSSM_ALGID_FEE;
return CSSM_ALGID_SHA1WithECDSA;
}
else {
*keyAlg = CSSM_ALGID_NONE;
return CSSM_ALGID_NONE;
}
}
void tpToLower(
char *str,
unsigned strLen)
{
for(unsigned i=0; i<strLen; i++) {
*str++ = tolower(*str);
}
}
CSSM_BOOL tpCompareHostNames(
const char *hostName, uint32 hostNameLen,
char *serverName, uint32 serverNameLen)
{
tpToLower(serverName, serverNameLen);
if(hostName[hostNameLen - 1] == '\0') {
hostNameLen--;
}
if(serverName[serverNameLen - 1] == '\0') {
serverNameLen--;
}
if((serverNameLen == hostNameLen) &&
!memcmp(serverName, hostName, serverNameLen)) {
return CSSM_TRUE;
}
if(serverName[0] == '*') {
unsigned effectLen = serverNameLen - 1; if(serverNameLen < effectLen) {
errorLog0("tp_verifySslOpts: subject/server name wildcard "
"mismatch (1)");
return CSSM_FALSE;
}
else if(memcmp(serverName+1, hostName + hostNameLen - effectLen,
effectLen)) {
errorLog0("tp_verifySslOpts: subject/server name wildcard "
"mismatch (2)");
return CSSM_FALSE;
}
else {
return CSSM_TRUE;
}
}
else {
errorLog0("tp_verifySslOpts: subject/server name mismatch");
return CSSM_FALSE;
}
}