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 <Security/SecAsn1Coder.h>
#include <Security/keyTemplates.h>
#include "certGroupUtils.h"
#include "tpdebugging.h"
#include "tpTime.h"
#include <string.h>
void tpCopyCssmData(
Allocator &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(
Allocator &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(
Allocator &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;
}
}
void tpFreePluginMemory(
CSSM_HANDLE hand,
void *p)
{
CSSM_API_MEMORY_FUNCS memFuncs;
CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs);
if(crtn) {
tpErrorLog("CSSM_GetAPIMemoryFunctions failure\n");
return;
}
memFuncs.free_func(p, memFuncs.AllocRef);
}
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) {
tpErrorLog("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) {
tpErrorLog("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 tp_CompareCerts(
const CSSM_DATA *cert1,
const CSSM_DATA *cert2)
{
return tpCompareCssmData(cert1, cert2);
}
void tpToLower(
char *str,
unsigned strLen)
{
for(unsigned i=0; i<strLen; i++) {
*str = tolower(*str);
str++;
}
}
void tpNormalizeAddrSpec(
char *addr,
unsigned addrLen,
bool normalizeAll)
{
if (addr == NULL) {
tpPolicyError("tpNormalizeAddrSpec: bad addr");
return;
}
if(!normalizeAll) {
while((addrLen != 0) && (*addr != '@')) {
addr++;
addrLen--;
}
if(addrLen == 0) {
tpPolicyError("tpNormalizeAddrSpec: bad addr-spec");
return;
}
}
tpToLower(addr, addrLen);
}
#define MAX_DNS_COMP_LEN 128
static bool tpNextDnsComp(
const char *inBuf,
uint32 &inBufLen, char *outBuf, uint32 &outBufLen) {
outBufLen = 0;
if(inBufLen == 0) {
return false;
}
if(*inBuf == '.') {
inBuf++;
if(--inBufLen == 0) {
return false;
}
}
do {
if(*inBuf == '.') {
break;
}
*outBuf++ = *inBuf++;
inBufLen--;
outBufLen++;
if(outBufLen >= MAX_DNS_COMP_LEN) {
break;
}
} while(inBufLen != 0);
if(outBufLen) {
return true;
}
else {
return false;
}
}
static const char *tpSubStr(
const char *bigstr,
uint32 bigstrLen,
const char *substr,
uint32 substrLen)
{
if(!bigstr || !substr || bigstrLen == 0 || substrLen == 0) {
return NULL;
}
const char *endBigStr = bigstr + bigstrLen - substrLen;
for( ; bigstr <= endBigStr; ) {
if(*bigstr == *substr) {
if(substrLen == 1) {
return bigstr;
}
if(!memcmp(bigstr+1, substr+1, substrLen - 1)) {
return bigstr;
}
}
bigstr++;
}
return NULL;
}
static CSSM_BOOL tpCompareComps(
const char *hostComp, uint32 hostCompLen,
const char *certComp, uint32 certCompLen)
{
const char *endCertComp = certComp + certCompLen;
const char *endHostComp = hostComp + hostCompLen;
do {
const char *wildCard = tpSubStr(certComp, certCompLen,
"*", 1);
if(wildCard == NULL) {
if((hostCompLen == certCompLen) &&
!memcmp(hostComp, certComp, certCompLen)) {
return CSSM_TRUE;
}
else {
return CSSM_FALSE;
}
}
if(wildCard != certComp) {
ptrdiff_t subStrLen = wildCard - certComp;
if(subStrLen > hostCompLen) {
return CSSM_FALSE;
}
if(memcmp(certComp, hostComp, subStrLen)) {
return CSSM_FALSE;
}
hostComp += subStrLen;
hostCompLen -= subStrLen;
certComp = wildCard;
certCompLen -= subStrLen;
continue;
}
wildCard++;
if(wildCard == endCertComp) {
return CSSM_TRUE;
}
const char *afterSubStr; afterSubStr = tpSubStr(wildCard, (uint32)(endCertComp - wildCard),
"*", 1);
if(afterSubStr == NULL) {
afterSubStr = endCertComp;
}
uint32 subStrLen = (uint32)(afterSubStr - wildCard);
const char *foundSub = tpSubStr(hostComp, hostCompLen,
wildCard, subStrLen);
if(foundSub == NULL) {
return CSSM_FALSE;
}
hostComp = foundSub + subStrLen;
hostCompLen = (uint32)(endHostComp - hostComp);
certComp = afterSubStr;
certCompLen = (uint32)(endCertComp - afterSubStr);
} while((hostCompLen != 0) || (certCompLen != 0));
if((hostCompLen == 0) && (certCompLen == 0)) {
return CSSM_TRUE;
}
else {
return CSSM_FALSE;
}
}
CSSM_BOOL tpCompareHostNames(
const char *hostName, uint32 hostNameLen,
char *certName, uint32 certNameLen)
{
tpToLower(certName, certNameLen);
if(hostNameLen && (hostName[hostNameLen - 1] == '\0')) {
hostNameLen--;
}
if(certNameLen && (certName[certNameLen - 1] == '\0')) {
certNameLen--;
}
if((hostNameLen == 0) || (certNameLen == 0)) {
if(hostNameLen == certNameLen) {
return CSSM_TRUE;
}
else {
return CSSM_FALSE;
}
}
if(hostName[hostNameLen - 1] == '.') {
hostNameLen--;
}
if(certName[certNameLen - 1] == '.') {
certNameLen--;
}
if((certNameLen == hostNameLen) &&
!memcmp(certName, hostName, certNameLen)) {
return CSSM_TRUE;
}
do {
char hostComp[MAX_DNS_COMP_LEN];
char certComp[MAX_DNS_COMP_LEN];
uint32 hostCompLen;
uint32 certCompLen;
bool foundHost = tpNextDnsComp(hostName, hostNameLen,
hostComp, hostCompLen);
bool foundCert = tpNextDnsComp(certName, certNameLen,
certComp, certCompLen);
if(foundHost != foundCert) {
tpPolicyError("tpCompareHostNames: wildcard mismatch (1)");
return CSSM_FALSE;
}
if(!foundHost) {
return CSSM_TRUE;
}
if(!tpCompareComps(hostComp, hostCompLen,
certComp, certCompLen)) {
tpPolicyError("tpCompareHostNames: wildcard mismatch (2)");
return CSSM_FALSE;
}
if(*hostName == '.') hostName++;
hostName += hostCompLen;
if(*certName == '.') certName++;
certName += certCompLen;
} while(1);
}
CSSM_BOOL tpCompareEmailAddr(
const char *appEmail, uint32 appEmailLen,
char *certEmail, uint32 certEmailLen,
bool normalizeAll)
{
tpNormalizeAddrSpec(certEmail, certEmailLen, normalizeAll);
if(appEmailLen > 0 && appEmail[appEmailLen - 1] == '\0') {
appEmailLen--;
}
if(certEmailLen > 0 && certEmail[certEmailLen - 1] == '\0') {
certEmailLen--;
}
if((certEmailLen == appEmailLen) &&
!memcmp(certEmail, appEmail, certEmailLen)) {
return CSSM_TRUE;
}
else {
tpPolicyError("tpCompareEmailAddr: app/cert email addrs mismatch");
return CSSM_FALSE;
}
}
CSSM_BOOL tpCompareDomainSuffix(
const char *hostName, uint32 hostNameLen,
char *domainName, uint32 domainNameLen)
{
tpToLower(domainName, domainNameLen);
if(hostNameLen && (hostName[hostNameLen - 1] == '\0')) {
hostNameLen--;
}
if(domainNameLen && (domainName[domainNameLen - 1] == '\0')) {
domainNameLen--;
}
if((hostNameLen == 0) || (domainNameLen == 0)) {
if(hostNameLen == domainNameLen) {
return CSSM_TRUE;
}
else {
return CSSM_FALSE;
}
}
if(hostName[hostNameLen - 1] == '.') {
hostNameLen--;
}
if(domainName[domainNameLen - 1] == '.') {
domainNameLen--;
}
if((domainNameLen > 0) && (domainName[0] == '.')) {
domainName++;
domainNameLen--;
}
if(hostNameLen < domainNameLen) {
return CSSM_FALSE;
}
if(memcmp(hostName+(hostNameLen-domainNameLen),domainName,domainNameLen)) {
return CSSM_FALSE;
}
if(hostNameLen > domainNameLen) {
if(hostName[hostNameLen-(domainNameLen+1)] != '.') {
return CSSM_FALSE;
}
}
return CSSM_TRUE;
}
int decodeECDSA_SigAlgParams(
const CSSM_DATA *params,
CSSM_ALGORITHMS *cssmAlg)
{
SecAsn1CoderRef coder = NULL;
if(SecAsn1CoderCreate(&coder)) {
tpErrorLog("***Error in SecAsn1CoderCreate()\n");
return -1;
}
CSSM_X509_ALGORITHM_IDENTIFIER algParams;
memset(&algParams, 0, sizeof(algParams));
int ourRtn = 0;
bool algFound = false;
if(SecAsn1DecodeData(coder, params, kSecAsn1AlgorithmIDTemplate,
&algParams)) {
tpErrorLog("***Error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n");
ourRtn = -1;
goto errOut;
}
CSSM_ALGORITHMS digestAlg;
algFound = cssmOidToAlg(&algParams.algorithm, &digestAlg);
if(!algFound) {
tpErrorLog("***Unknown algorithm in CSSM_X509_ALGORITHM_IDENTIFIER\n");
ourRtn = -1;
goto errOut;
}
switch(digestAlg) {
case CSSM_ALGID_SHA1:
*cssmAlg = CSSM_ALGID_SHA1WithECDSA;
break;
case CSSM_ALGID_SHA224:
*cssmAlg = CSSM_ALGID_SHA224WithECDSA;
break;
case CSSM_ALGID_SHA256:
*cssmAlg = CSSM_ALGID_SHA256WithECDSA;
break;
case CSSM_ALGID_SHA384:
*cssmAlg = CSSM_ALGID_SHA384WithECDSA;
break;
case CSSM_ALGID_SHA512:
*cssmAlg = CSSM_ALGID_SHA512WithECDSA;
break;
default:
tpErrorLog("***Unknown algorithm in ECDSA_SigAlgParams\n");
ourRtn = -1;
}
errOut:
SecAsn1CoderRelease(coder);
return ourRtn;
}