#include <Security/cssmtype.h>
#include <clAppUtils/tpUtils.h>
#include <clAppUtils/clutils.h>
#include <utilLib/common.h>
#include <utilLib/cspwrap.h>
#include <clAppUtils/CertBuilderApp.h>
#include <Security/oidsattr.h>
#include <Security/oidscert.h>
#include <Security/SecTrustSettingsPriv.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Security/SecKeychainItem.h>
#include <Security/SecKeychain.h>
#include <Security/SecCertificate.h>
#include <security_cdsa_utils/cuFileIo.h>
#define FAKE_ADD_CERT_SCHEMA 1
#if FAKE_ADD_CERT_SCHEMA
#define SCHEMA_ATTR_INFO(id, name, type) \
{ id, (char *)name, {0, NULL}, CSSM_DB_ATTRIBUTE_FORMAT_ ## type }
static CSSM_DB_SCHEMA_ATTRIBUTE_INFO certSchemaAttrInfo[] =
{
SCHEMA_ATTR_INFO(kSecCertTypeItemAttr, "CertType", UINT32),
SCHEMA_ATTR_INFO(kSecCertEncodingItemAttr, "CertEncoding", UINT32),
SCHEMA_ATTR_INFO(kSecLabelItemAttr, "PrintName", BLOB),
SCHEMA_ATTR_INFO(kSecAlias, "Alias", BLOB),
SCHEMA_ATTR_INFO(kSecSubjectItemAttr, "Subject", BLOB),
SCHEMA_ATTR_INFO(kSecIssuerItemAttr, "Issuer", BLOB),
SCHEMA_ATTR_INFO(kSecSerialNumberItemAttr, "SerialNumber", BLOB),
SCHEMA_ATTR_INFO(kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", BLOB),
SCHEMA_ATTR_INFO(kSecPublicKeyHashItemAttr, "PublicKeyHash", BLOB)
};
#define NUM_CERT_SCHEMA_ATTRS \
(sizeof(certSchemaAttrInfo) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO))
#define SCHEMA_INDEX_INFO(id, indexNum, indexType) \
{ id, CSSM_DB_INDEX_ ## indexType, CSSM_DB_INDEX_ON_ATTRIBUTE }
static CSSM_DB_SCHEMA_INDEX_INFO certSchemaIndices[] =
{
SCHEMA_INDEX_INFO(kSecCertTypeItemAttr, 0, UNIQUE),
SCHEMA_INDEX_INFO(kSecIssuerItemAttr, 0, UNIQUE),
SCHEMA_INDEX_INFO(kSecSerialNumberItemAttr, 0, UNIQUE),
SCHEMA_INDEX_INFO(kSecCertTypeItemAttr, 1, NONUNIQUE),
SCHEMA_INDEX_INFO(kSecSubjectItemAttr, 2, NONUNIQUE),
SCHEMA_INDEX_INFO(kSecIssuerItemAttr, 3, NONUNIQUE),
SCHEMA_INDEX_INFO(kSecSerialNumberItemAttr, 4, NONUNIQUE),
SCHEMA_INDEX_INFO(kSecSubjectKeyIdentifierItemAttr, 5, NONUNIQUE),
SCHEMA_INDEX_INFO(kSecPublicKeyHashItemAttr, 6, NONUNIQUE)
};
#define NUM_CERT_INDICES \
(sizeof(certSchemaIndices) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO))
CSSM_RETURN tpAddCertSchema(
CSSM_DL_DB_HANDLE dlDbHand)
{
return CSSM_DL_CreateRelation(dlDbHand,
CSSM_DL_DB_RECORD_X509_CERTIFICATE,
"CSSM_DL_DB_RECORD_X509_CERTIFICATE",
NUM_CERT_SCHEMA_ATTRS,
certSchemaAttrInfo,
NUM_CERT_INDICES,
certSchemaIndices);
}
#endif
static CSSM_DATA_PTR tpGetNormSubject(
CSSM_CL_HANDLE clHand,
const CSSM_DATA *rawCert)
{
CSSM_RETURN crtn;
CSSM_HANDLE searchHand = CSSM_INVALID_HANDLE;
uint32 numFields;
CSSM_DATA_PTR fieldValue;
crtn = CSSM_CL_CertGetFirstFieldValue(clHand,
rawCert,
&CSSMOID_X509V1SubjectName,
&searchHand,
&numFields,
&fieldValue);
if(crtn) {
printError("CSSM_CL_CertGetFirstFieldValue", crtn);
return NULL;
}
CSSM_CL_CertAbortQuery(clHand, searchHand);
return fieldValue;
}
static CSSM_DATA_PTR tpGetNormIssuer(
CSSM_CL_HANDLE clHand,
const CSSM_DATA *rawCert)
{
CSSM_RETURN crtn;
CSSM_HANDLE searchHand = CSSM_INVALID_HANDLE;
uint32 numFields;
CSSM_DATA_PTR fieldValue;
crtn = CSSM_CL_CertGetFirstFieldValue(clHand,
rawCert,
&CSSMOID_X509V1IssuerName,
&searchHand,
&numFields,
&fieldValue);
if(crtn) {
printError("CSSM_CL_CertGetFirstFieldValue", crtn);
return NULL;
}
CSSM_CL_CertAbortQuery(clHand, searchHand);
return fieldValue;
}
#define SERIAL_NUMBER_BASE 0x33445566
CSSM_RETURN tpMakeRandCertGroup(
CSSM_CL_HANDLE clHand,
CSSM_DL_DB_LIST_PTR dbList,
const CSSM_DATA_PTR certs,
unsigned numCerts,
CSSM_CERTGROUP_PTR certGroup,
CSSM_BOOL firstCertIsSubject, CSSM_BOOL verbose,
CSSM_BOOL allInDbs, CSSM_BOOL skipFirstDb) {
unsigned startDex = 0; unsigned certDex; unsigned die;
CSSM_RETURN crtn;
#if TP_DB_ENABLE
if((dbList == NULL) && (allInDbs | skipFirstDb)) {
printf("need dbList for allInDbs or skipFirstDb\n");
return CSSM_ERRCODE_INTERNAL_ERROR;
}
if(skipFirstDb && (dbList->NumHandles == 1)) {
printf("Need more than one DB for skipFirstDb\n");
return CSSM_ERRCODE_INTERNAL_ERROR;
}
#else
if(dbList != NULL) {
printf("TP/DB not supported yet\n");
return CSSMERR_CSSM_INTERNAL_ERROR;
}
#endif
certGroup->NumCerts = 0;
certGroup->CertGroupType = CSSM_CERTGROUP_DATA;
certGroup->CertType = CSSM_CERT_X_509v3;
certGroup->CertEncoding = CSSM_CERT_ENCODING_DER;
if(numCerts == 0) {
certGroup->GroupList.CertList = NULL;
return CSSM_OK;
}
certGroup->GroupList.CertList = (CSSM_DATA_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_DATA));
if(certGroup->GroupList.CertList == NULL) {
printf("Memory error!\n");
return CSSMERR_CSSM_MEMORY_ERROR;
}
if(firstCertIsSubject) {
certGroup->GroupList.CertList[0] = certs[0];
certGroup->NumCerts = 1;
startDex = 1;
}
for(certDex=startDex; certDex<numCerts; certDex++) {
die = genRand(1, 2); if( ( (dbList != NULL) && (dbList->NumHandles != 0) ) &&
( (die == 1) || allInDbs) ) {
if(skipFirstDb) {
die = genRand(1, dbList->NumHandles-1);
}
else {
die = genRand(0, dbList->NumHandles-1);
}
if(verbose) {
printf(" ...cert %d to DB[%d]\n", certDex, die);
}
crtn = tpStoreRawCert(dbList->DLDBHandle[die],
clHand,
&certs[certDex]);
if(crtn) {
return crtn;
}
}
else {
CSSM_DATA_PTR certData;
while(1) {
die = genRand(0, numCerts-1);
certData = &certGroup->GroupList.CertList[die];
if(certData->Data == NULL) {
*certData = certs[certDex];
certGroup->NumCerts++;
if(verbose) {
printf(" ...cert %d to frag[%d]\n",
certDex, die);
}
break;
}
}
}
}
if(dbList != NULL) {
unsigned i;
for(certDex=0; certDex<numCerts; certDex++) {
if(certGroup->GroupList.CertList[certDex].Data == NULL) {
for(i=certDex+1; i<numCerts; i++) {
if(certGroup->GroupList.CertList[i].Data != NULL) {
if(verbose) {
printf(" ...frag[%d] to frag[%d]\n",
i, certDex);
}
certGroup->GroupList.CertList[certDex] =
certGroup->GroupList.CertList[i];
certGroup->GroupList.CertList[i].Data = NULL;
break;
}
}
}
}
}
return CSSM_OK;
}
CSSM_RETURN tpStoreCert(
CSSM_DL_DB_HANDLE dlDb,
const CSSM_DATA_PTR cert,
CSSM_CERT_TYPE certType, uint32 serialNum,
const CSSM_DATA *issuer,
CSSM_CERT_ENCODING certEncoding, const CSSM_DATA *printName,
const CSSM_DATA *subject) {
CSSM_DB_ATTRIBUTE_DATA attrs[6];
CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs;
CSSM_DB_ATTRIBUTE_DATA_PTR attr = &attrs[0];
CSSM_DB_UNIQUE_RECORD_PTR recordPtr = NULL;
CSSM_DATA certTypeData;
CSSM_DATA certEncData;
CSSM_DATA_PTR serialNumData;
uint32 numAttributes;
if(issuer == NULL) {
printf("***For now, must specify cert issuer when storing\n");
return CSSM_ERRCODE_INTERNAL_ERROR;
}
numAttributes = 4; if(printName != NULL) {
numAttributes++;
}
if(subject != NULL) {
numAttributes++;
}
recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE;
recordAttrs.SemanticInformation = 0;
recordAttrs.NumberOfAttributes = numAttributes;
recordAttrs.AttributeData = attrs;
certTypeData.Data = (uint8 *)&certType;
certTypeData.Length = sizeof(CSSM_CERT_TYPE);
certEncData.Data = (uint8 *)&certEncoding;
certEncData.Length = sizeof(CSSM_CERT_ENCODING);
serialNumData = intToDER(serialNum);
attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
attr->Info.Label.AttributeName = (char *)"CertType";
attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32;
attr->NumberOfValues = 1;
attr->Value = &certTypeData;
attr++;
attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
attr->Info.Label.AttributeName = (char *)"CertEncoding";
attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32;
attr->NumberOfValues = 1;
attr->Value = &certEncData;
attr++;
attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
attr->Info.Label.AttributeName = (char *)"SerialNumber";
attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
attr->NumberOfValues = 1;
attr->Value = serialNumData;
attr++;
attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
attr->Info.Label.AttributeName = (char *)"Issuer";
attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
attr->NumberOfValues = 1;
attr->Value = (CSSM_DATA_PTR)issuer;
attr++;
if(printName != NULL) {
attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
attr->Info.Label.AttributeName = (char *)"PrintName";
attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
attr->NumberOfValues = 1;
attr->Value = (CSSM_DATA_PTR)printName;
attr++;
}
if(subject != NULL) {
attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
attr->Info.Label.AttributeName = (char *)"Subject";
attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
attr->NumberOfValues = 1;
attr->Value = (CSSM_DATA_PTR)subject;
attr++;
}
CSSM_RETURN crtn = CSSM_DL_DataInsert(dlDb,
CSSM_DL_DB_RECORD_X509_CERTIFICATE,
&recordAttrs,
cert,
&recordPtr);
#if FAKE_ADD_CERT_SCHEMA
if(crtn == CSSMERR_DL_INVALID_RECORDTYPE) {
crtn = tpAddCertSchema(dlDb);
if(crtn == CSSM_OK) {
crtn = CSSM_DL_DataInsert(dlDb,
CSSM_DL_DB_RECORD_X509_CERTIFICATE,
&recordAttrs,
cert,
&recordPtr);
}
}
#endif
appFreeCssmData(serialNumData, CSSM_TRUE);
if(recordPtr != NULL) {
CSSM_DL_FreeUniqueRecord(dlDb, recordPtr);
}
if(crtn) {
printError("CSSM_DL_DataInsert", crtn);
}
return crtn;
}
CSSM_RETURN tpStoreRawCert(
CSSM_DL_DB_HANDLE dlDb,
CSSM_CL_HANDLE clHand,
const CSSM_DATA_PTR cert)
{
CSSM_DATA_PTR normSubj;
CSSM_DATA_PTR normIssuer;
CSSM_DATA printName;
CSSM_RETURN crtn;
static uint32 fakeSerialNum = 0;
normSubj = tpGetNormSubject(clHand, cert);
normIssuer = tpGetNormIssuer(clHand, cert);
if((normSubj == NULL) || (normIssuer == NULL)) {
return CSSM_ERRCODE_INTERNAL_ERROR;
}
printName.Data = (uint8 *)"Some Printable Name";
printName.Length = strlen((char *)printName.Data);
crtn = tpStoreCert(dlDb,
cert,
CSSM_CERT_X_509v3,
fakeSerialNum++,
normIssuer,
CSSM_CERT_ENCODING_DER,
&printName,
normSubj);
appFreeCssmData(normSubj, CSSM_TRUE);
appFreeCssmData(normIssuer, CSSM_TRUE);
return crtn;
}
CSSM_RETURN tpGenKeys(
CSSM_CSP_HANDLE cspHand,
CSSM_DL_DB_HANDLE dbHand,
unsigned numKeyPairs,
uint32 keyGenAlg,
uint32 keySizeInBits,
const char *keyLabelBase,
CSSM_KEY_PTR pubKeys,
CSSM_KEY_PTR privKeys,
CSSM_DATA_PTR paramData)
{
CSSM_RETURN crtn;
unsigned i;
char label[80];
unsigned labelLen = strlen(keyLabelBase);
memset(pubKeys, 0, numKeyPairs * sizeof(CSSM_KEY));
memset(privKeys, 0, numKeyPairs * sizeof(CSSM_KEY));
memmove(label, keyLabelBase, labelLen);
for(i=0; i<numKeyPairs; i++) {
sprintf(label+labelLen, "%04d", i);
if(keyGenAlg == CSSM_ALGID_DSA) {
crtn = cspGenDSAKeyPair(cspHand,
label,
labelLen + 4,
keySizeInBits,
&pubKeys[i],
CSSM_FALSE, CSSM_KEYUSE_VERIFY, CSSM_KEYBLOB_RAW_FORMAT_NONE,
&privKeys[i],
CSSM_TRUE, CSSM_KEYUSE_SIGN,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
CSSM_FALSE, paramData);
}
else {
crtn = cspGenKeyPair(cspHand,
keyGenAlg,
label,
labelLen + 4,
keySizeInBits,
&pubKeys[i],
CSSM_FALSE, CSSM_KEYUSE_VERIFY, CSSM_KEYBLOB_RAW_FORMAT_NONE,
&privKeys[i],
CSSM_TRUE, CSSM_KEYUSE_SIGN,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
CSSM_FALSE);
}
if(crtn) {
return crtn;
}
}
for(i=0; i<numKeyPairs; i++) {
CSSM_DATA_PTR k1 = &pubKeys[i].KeyData;
for(unsigned j=i+1; j<numKeyPairs; j++) {
CSSM_DATA_PTR k2 = &pubKeys[j].KeyData;
if(appCompareCssmData(k1, k2)) {
printf("***HEY! public keys %d and %d are indentical!\n", i, j);
}
}
}
return crtn;
}
CSSM_RETURN tpGenCerts(
CSSM_CSP_HANDLE cspHand,
CSSM_CL_HANDLE clHand,
unsigned numCerts,
uint32 sigAlg,
const char *nameBase,
CSSM_KEY_PTR pubKeys,
CSSM_KEY_PTR privKeys,
CSSM_DATA_PTR certs,
const char *notBeforeStr,
const char *notAfterStr)
{
return tpGenCertsStore(cspHand,
clHand,
numCerts,
sigAlg,
nameBase,
pubKeys,
privKeys,
NULL, certs,
notBeforeStr,
notAfterStr);
}
CSSM_RETURN tpGenCertsStore(
CSSM_CSP_HANDLE cspHand,
CSSM_CL_HANDLE clHand,
unsigned numCerts,
uint32 sigAlg,
const char *nameBase,
CSSM_KEY_PTR pubKeys,
CSSM_KEY_PTR privKeys,
CSSM_DL_DB_HANDLE *storeArray,
CSSM_DATA_PTR certs,
const char *notBeforeStr,
const char *notAfterStr)
{
int dex;
CSSM_RETURN crtn;
CSSM_X509_NAME *issuerName = NULL;
CSSM_X509_NAME *subjectName = NULL;
CSSM_X509_TIME *notBefore; CSSM_X509_TIME *notAfter; CSSM_DATA_PTR rawCert = NULL; CSSM_DATA signedCert; uint32 rtn;
CSSM_KEY_PTR signerKey; CSSM_CC_HANDLE signContext;
char nameStr[100];
CSSM_DATA_PTR thisCert; CB_NameOid nameOid;
CE_BasicConstraints bc;
CSSM_X509_EXTENSION exten;
nameOid.oid = &CSSMOID_OrganizationName; nameOid.string = nameStr;
exten.extnId = CSSMOID_BasicConstraints;
exten.critical = CSSM_TRUE;
exten.format = CSSM_X509_DATAFORMAT_PARSED;
exten.value.parsedValue = &bc;
exten.BERvalue.Data = NULL;
exten.BERvalue.Length = 0;
bc.cA = CSSM_TRUE;
bc.pathLenConstraintPresent = CSSM_FALSE;
bc.pathLenConstraint = 0;
for(dex=numCerts-1; dex>=0; dex--) {
thisCert = &certs[dex];
thisCert->Data = NULL;
thisCert->Length = 0;
sprintf(nameStr, "%s%04d", nameBase, dex);
if(issuerName == NULL) {
issuerName = CB_BuildX509Name(&nameOid, 1);
signerKey = &privKeys[dex];
}
else {
CB_FreeX509Name(issuerName);
issuerName = subjectName;
signerKey = &privKeys[dex+1];
}
subjectName = CB_BuildX509Name(&nameOid, 1);
if((subjectName == NULL) || (issuerName == NULL)) {
printf("Error creating X509Names\n");
crtn = CSSMERR_CSSM_MEMORY_ERROR;
break;
}
notBefore = CB_BuildX509Time(0, notBeforeStr);
notAfter = CB_BuildX509Time(0, notAfterStr);
rawCert = CB_MakeCertTemplate(clHand,
SERIAL_NUMBER_BASE + dex, issuerName,
subjectName,
notBefore,
notAfter,
&pubKeys[dex],
sigAlg,
NULL, NULL, &exten, (dex == 0) ? 0 : 1);
if(rawCert == NULL) {
crtn = CSSM_ERRCODE_INTERNAL_ERROR;
break;
}
CB_FreeX509Time(notBefore);
CB_FreeX509Time(notAfter);
crtn = CSSM_CSP_CreateSignatureContext(cspHand,
sigAlg,
NULL, signerKey,
&signContext);
if(crtn) {
printError("CreateSignatureContext", crtn);
break;
}
signedCert.Data = NULL;
signedCert.Length = 0;
crtn = CSSM_CL_CertSign(clHand,
signContext,
rawCert, NULL, 0, &signedCert);
if(crtn) {
printError("CSSM_CL_CertSign", crtn);
break;
}
if((storeArray != NULL) && storeArray[dex].DBHandle != 0) {
crtn = tpStoreRawCert(storeArray[dex],
clHand,
&signedCert);
if(crtn) {
break;
}
}
crtn = CSSM_DeleteContext(signContext);
if(crtn) {
printError("CSSM_DeleteContext", crtn);
break;
}
certs[dex] = signedCert;
appFreeCssmData(rawCert, CSSM_TRUE);
rtn = 0;
}
if(issuerName != NULL) {
CB_FreeX509Name(issuerName);
}
if(subjectName != NULL) {
CB_FreeX509Name(subjectName);
}
return crtn;
}
CSSM_BOOL tpCompareCertGroups(
const CSSM_CERTGROUP *grp1,
const CSSM_CERTGROUP *grp2)
{
unsigned i;
CSSM_DATA_PTR d1;
CSSM_DATA_PTR d2;
if(grp1->NumCerts != grp2->NumCerts) {
return CSSM_FALSE;
}
for(i=0; i<grp1->NumCerts; i++) {
d1 = &grp1->GroupList.CertList[i];
d2 = &grp2->GroupList.CertList[i];
if((d1->Data == NULL) ||
(d1->Length == 0) ||
(d2->Data == NULL) ||
(d2->Length == 0)) {
printf("compareCertGroups: bad cert group!\n");
return CSSM_FALSE;
}
if(d1->Length != d2->Length) {
return CSSM_FALSE;
}
if(memcmp(d1->Data, d2->Data, d1->Length)) {
return CSSM_FALSE;
}
}
return CSSM_TRUE;
}
void tpFreeCertGroup(
CSSM_CERTGROUP_PTR certGroup,
CSSM_BOOL freeCertData, CSSM_BOOL freeStruct) {
unsigned dex;
if(certGroup == NULL) {
return;
}
if(freeCertData) {
for(dex=0; dex<certGroup->NumCerts; dex++) {
appFreeCssmData(&certGroup->GroupList.CertList[dex], CSSM_FALSE);
}
}
if(certGroup->GroupList.CertList) {
CSSM_FREE(certGroup->GroupList.CertList);
}
if(freeStruct) {
CSSM_FREE(certGroup);
}
}
CSSM_RETURN clDeleteAllCerts(CSSM_DL_DB_HANDLE dlDb)
{
CSSM_QUERY query;
CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
CSSM_RETURN crtn;
CSSM_HANDLE resultHand;
CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs;
recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE;
recordAttrs.NumberOfAttributes = 0;
recordAttrs.AttributeData = NULL;
query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE;
query.Conjunctive = CSSM_DB_NONE;
query.NumSelectionPredicates = 0;
query.SelectionPredicate = NULL;
query.QueryLimits.TimeLimit = 0; query.QueryLimits.SizeLimit = 1; query.QueryFlags = 0;
crtn = CSSM_DL_DataGetFirst(dlDb,
&query,
&resultHand,
&recordAttrs,
NULL, &record);
switch(crtn) {
case CSSM_OK:
break; case CSSMERR_DL_ENDOFDATA:
return CSSM_OK;
default:
printError("DataGetFirst", crtn);
return crtn;
}
crtn = CSSM_DL_DataDelete(dlDb, record);
if(crtn) {
printError("CSSM_DL_DataDelete", crtn);
return crtn;
}
CSSM_DL_FreeUniqueRecord(dlDb, record);
for(;;) {
crtn = CSSM_DL_DataGetNext(dlDb,
resultHand,
&recordAttrs,
NULL,
&record);
switch(crtn) {
case CSSM_OK:
crtn = CSSM_DL_DataDelete(dlDb, record);
if(crtn) {
printError("CSSM_DL_DataDelete", crtn);
return crtn;
}
CSSM_DL_FreeUniqueRecord(dlDb, record);
break; case CSSMERR_DL_ENDOFDATA:
break;
default:
printError("DataGetNext", crtn);
return crtn;
}
if(crtn != CSSM_OK) {
break;
}
}
CSSM_DL_DataAbortQuery(dlDb, resultHand);
return CSSM_OK;
}
CSSM_RETURN tpCertGroupVerify(
CSSM_TP_HANDLE tpHand,
CSSM_CL_HANDLE clHand,
CSSM_CSP_HANDLE cspHand,
CSSM_DL_DB_LIST_PTR dbListPtr,
const CSSM_OID *policy, const CSSM_DATA *fieldOpts, const CSSM_DATA *actionData, void *policyOpts,
const CSSM_CERTGROUP *certGroup,
CSSM_DATA_PTR anchorCerts,
unsigned numAnchorCerts,
CSSM_TP_STOP_ON stopOn, CSSM_TIMESTRING cssmTimeStr, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR result) {
CSSM_TP_VERIFY_CONTEXT vfyCtx;
CSSM_TP_CALLERAUTH_CONTEXT authCtx;
memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT));
vfyCtx.Action = CSSM_TP_ACTION_DEFAULT;
if(actionData) {
vfyCtx.ActionData = *actionData;
}
else {
vfyCtx.ActionData.Data = NULL;
vfyCtx.ActionData.Length = 0;
}
vfyCtx.Cred = &authCtx;
CSSM_FIELD policyId;
if(policy != NULL) {
policyId.FieldOid = (CSSM_OID)*policy;
authCtx.Policy.NumberOfPolicyIds = 1;
authCtx.Policy.PolicyIds = &policyId;
if(fieldOpts != NULL) {
policyId.FieldValue = *fieldOpts;
}
else {
policyId.FieldValue.Data = NULL;
policyId.FieldValue.Length = 0;
}
}
else {
authCtx.Policy.NumberOfPolicyIds = 0;
authCtx.Policy.PolicyIds = NULL;
}
authCtx.Policy.PolicyControl = policyOpts;
authCtx.VerifyTime = cssmTimeStr; authCtx.VerificationAbortOn = stopOn;
authCtx.CallbackWithVerifiedCert = NULL;
authCtx.NumberOfAnchorCerts = numAnchorCerts;
authCtx.AnchorCerts = anchorCerts;
authCtx.DBList = dbListPtr;
authCtx.CallerCredentials = NULL;
return CSSM_TP_CertGroupVerify(tpHand,
clHand,
cspHand,
certGroup,
&vfyCtx,
result);
}
#define KC_DB_PATH "Library/Keychains"
CSSM_RETURN tpKcOpen(
CSSM_DL_HANDLE dlHand,
const char *kcName,
const char *pwd, CSSM_BOOL doCreate,
CSSM_DB_HANDLE *dbHand) {
char kcPath[300];
const char *kcFileName = kcName;
char *userHome = getenv("HOME");
if(userHome == NULL) {
userHome = (char *)"";
}
sprintf(kcPath, "%s/%s/%s", userHome, KC_DB_PATH, kcFileName);
return dbCreateOpen(dlHand, kcPath,
doCreate, CSSM_FALSE, pwd, dbHand);
}
CSSM_RETURN freeVfyResult(
CSSM_TP_VERIFY_CONTEXT_RESULT *ctx)
{
int numCerts = -1;
CSSM_RETURN crtn = CSSM_OK;
for(unsigned i=0; i<ctx->NumberOfEvidences; i++) {
CSSM_EVIDENCE_PTR evp = &ctx->Evidence[i];
switch(evp->EvidenceForm) {
case CSSM_EVIDENCE_FORM_APPLE_HEADER:
appFree(evp->Evidence, NULL);
evp->Evidence = NULL;
break;
case CSSM_EVIDENCE_FORM_APPLE_CERTGROUP:
{
CSSM_CERTGROUP_PTR cgp = (CSSM_CERTGROUP_PTR)evp->Evidence;
numCerts = cgp->NumCerts;
tpFreeCertGroup(cgp, CSSM_TRUE, CSSM_TRUE);
evp->Evidence = NULL;
break;
}
case CSSM_EVIDENCE_FORM_APPLE_CERT_INFO:
{
if(numCerts < 0) {
printf("***Malformed VerifyContextResult (2)\n");
crtn = CSSMERR_TP_INTERNAL_ERROR;
break;
}
CSSM_TP_APPLE_EVIDENCE_INFO *evInfo =
(CSSM_TP_APPLE_EVIDENCE_INFO *)evp->Evidence;
for(unsigned k=0; k<(unsigned)numCerts; k++) {
CSSM_TP_APPLE_EVIDENCE_INFO *thisEvInfo =
&evInfo[k];
if(thisEvInfo->StatusCodes) {
appFree(thisEvInfo->StatusCodes, NULL);
}
if(thisEvInfo->UniqueRecord) {
CSSM_RETURN crtn =
CSSM_DL_FreeUniqueRecord(thisEvInfo->DlDbHandle,
thisEvInfo->UniqueRecord);
if(crtn) {
printError("CSSM_DL_FreeUniqueRecord", crtn);
printf(" Record %p\n", thisEvInfo->UniqueRecord);
break;
}
thisEvInfo->UniqueRecord = NULL;
}
}
appFree(evp->Evidence, NULL);
evp->Evidence = NULL;
break;
}
}
}
if(ctx->Evidence) {
appFree(ctx->Evidence, NULL);
ctx->Evidence = NULL;
}
return crtn;
}
static void statusBitTest(
CSSM_TP_APPLE_CERT_STATUS certStatus,
uint32 bit,
const char *str)
{
if(certStatus & bit) {
printf("%s ", str);
}
}
void printCertInfo(
unsigned numCerts, const CSSM_TP_APPLE_EVIDENCE_INFO *info)
{
CSSM_TP_APPLE_CERT_STATUS cs;
for(unsigned i=0; i<numCerts; i++) {
const CSSM_TP_APPLE_EVIDENCE_INFO *thisInfo = &info[i];
cs = thisInfo->StatusBits;
printf(" cert %u:\n", i);
printf(" StatusBits : 0x%x", (unsigned)cs);
if(cs) {
printf(" ( ");
statusBitTest(cs, CSSM_CERT_STATUS_EXPIRED, "EXPIRED");
statusBitTest(cs, CSSM_CERT_STATUS_NOT_VALID_YET,
"NOT_VALID_YET");
statusBitTest(cs, CSSM_CERT_STATUS_IS_IN_INPUT_CERTS,
"IS_IN_INPUT_CERTS");
statusBitTest(cs, CSSM_CERT_STATUS_IS_IN_ANCHORS,
"IS_IN_ANCHORS");
statusBitTest(cs, CSSM_CERT_STATUS_IS_ROOT, "IS_ROOT");
statusBitTest(cs, CSSM_CERT_STATUS_IS_FROM_NET, "IS_FROM_NET");
statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER,
"TRUST_SETTINGS_FOUND_USER");
statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN,
"TRUST_SETTINGS_FOUND_ADMIN");
statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM,
"TRUST_SETTINGS_FOUND_SYSTEM");
statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST,
"TRUST_SETTINGS_TRUST");
statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_DENY,
"TRUST_SETTINGS_DENY");
statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR,
"TRUST_SETTINGS_IGNORED_ERROR");
printf(")\n");
}
else {
printf("\n");
}
printf(" NumStatusCodes : %u ",
(unsigned)thisInfo->NumStatusCodes);
for(unsigned j=0; j<thisInfo->NumStatusCodes; j++) {
printf("%s ",
cssmErrToStr(thisInfo->StatusCodes[j]));
}
printf("\n");
printf(" Index: %u\n", (unsigned)thisInfo->Index);
}
return;
}
#define SHOW_ALL_VFY_RESULTS 0
void dumpVfyResult(
const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult)
{
unsigned numEvidences = vfyResult->NumberOfEvidences;
unsigned numCerts = 0;
printf("Returned evidence:\n");
for(unsigned dex=0; dex<numEvidences; dex++) {
CSSM_EVIDENCE_PTR ev = &vfyResult->Evidence[dex];
#if SHOW_ALL_VFY_RESULTS
printf(" Evidence %u:\n", dex);
#endif
switch(ev->EvidenceForm) {
case CSSM_EVIDENCE_FORM_APPLE_HEADER:
{
#if SHOW_ALL_VFY_RESULTS
const CSSM_TP_APPLE_EVIDENCE_HEADER *hdr =
(const CSSM_TP_APPLE_EVIDENCE_HEADER *)(ev->Evidence);
printf(" Form = HEADER; Version = %u\n", hdr->Version);
#endif
break;
}
case CSSM_EVIDENCE_FORM_APPLE_CERTGROUP:
{
const CSSM_CERTGROUP *grp =
(const CSSM_CERTGROUP *)ev->Evidence;
numCerts = grp->NumCerts;
#if SHOW_ALL_VFY_RESULTS
printf(" Form = CERTGROUP; numCerts = %u\n", numCerts);
#endif
break;
}
case CSSM_EVIDENCE_FORM_APPLE_CERT_INFO:
{
const CSSM_TP_APPLE_EVIDENCE_INFO *info =
(const CSSM_TP_APPLE_EVIDENCE_INFO *)ev->Evidence;
printCertInfo(numCerts, info);
break;
}
default:
printf("***UNKNOWN Evidence form (%u)\n",
(unsigned)ev->EvidenceForm);
break;
}
}
}
OSStatus getSystemAnchors(
CFArrayRef *rootArray,
CSSM_DATA **anchors,
unsigned *numAnchors)
{
OSStatus ortn;
CFArrayRef cfAnchors;
CSSM_DATA *cssmAnchors;
ortn = SecTrustSettingsCopyUnrestrictedRoots(false, false, true,
&cfAnchors);
if(ortn) {
cssmPerror("SecTrustSettingsCopyUnrestrictedRoots", ortn);
return ortn;
}
unsigned _numAnchors = CFArrayGetCount(cfAnchors);
cssmAnchors = (CSSM_DATA *)malloc(sizeof(CSSM_DATA) * _numAnchors);
unsigned dex;
for(dex=0; dex<_numAnchors; dex++) {
SecCertificateRef root = (SecCertificateRef)CFArrayGetValueAtIndex(
cfAnchors, dex);
ortn = SecCertificateGetData(root, &cssmAnchors[dex]);
if(ortn) {
cssmPerror("SecCertificateGetData", ortn);
return ortn;
}
}
*rootArray = cfAnchors;
*anchors = cssmAnchors;
*numAnchors = _numAnchors;
return noErr;
}
SecCertificateRef certFromFile(
const char *fileName)
{
unsigned char *cp = NULL;
unsigned len = 0;
if(readFile(fileName, &cp, &len)) {
printf("***Error reading file %s\n", fileName);
return NULL;
}
SecCertificateRef certRef;
CSSM_DATA certData = {len, cp};
OSStatus ortn = SecCertificateCreateFromData(&certData,
CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certRef);
if(ortn) {
cssmPerror("SecCertificateCreateFromData", ortn);
return NULL;
}
free(cp);
return certRef;
}