+++ /dev/null
-/*
- * tpUtils.cpp - TP and cert group test support
- */
-
-#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>
-
-/*
- * Currently, DBs created with SecKeychainCreateNew() do not contain
- * the schema for CSSM_DL_DB_RECORD_X509_CERTIFICATE records. Keychain
- * code (Certificate::add()) does this on the fly, I don't know why.
- * To avoid dependencies on KC - other than SecKeychainCreateNew - we'll
- * emulate that "add this schema on the fly" logic here.
- *
- * Turn this option off if and when Radar 2927378 is approved and
- * integrated into Security TOT.
- */
-#define FAKE_ADD_CERT_SCHEMA 1
-#if FAKE_ADD_CERT_SCHEMA
-
-/* defined in SecKeychainAPIPriv.h */
-// static const int kSecAlias = 'alis';
-
-/* Macro to declare a CSSM_DB_SCHEMA_ATTRIBUTE_INFO */
-#define SCHEMA_ATTR_INFO(id, name, type) \
- { id, (char *)name, {0, NULL}, CSSM_DB_ATTRIBUTE_FORMAT_ ## type }
-
-/* Too bad we can't get this from inside of the Security framework. */
-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))
-
-/* Macro to declare a CSSM_DB_SCHEMA_INDEX_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 /* FAKE_ADD_CERT_SCHEMA */
-
-/*
- * Given a raw cert, extract DER-encoded normalized subject and issuer names.
- */
-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
-
-/*
- * Given an array of certs and an uninitialized CSSM_CERTGROUP, place the
- * certs into the certgroup and optionally into one of a list of DBs in
- * random order. Optionally the first cert in the array is placed in the
- * first element of certgroup. Only error is memory error. It's legal to
- * pass in an empty cert array.
- */
-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, // true: certs[0] goes to head
- // of certGroup
- CSSM_BOOL verbose,
- CSSM_BOOL allInDbs, // all certs go to DBs
- CSSM_BOOL skipFirstDb) // no certs go to db[0]
-{
- unsigned startDex = 0; // where to start processing
- unsigned certDex; // into certs and certGroup
- 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) {
- /* legal */
- certGroup->GroupList.CertList = NULL;
- return CSSM_OK;
- }
-
- /* make CertList big enough for all certs */
- 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++) {
- /* flip a coin, half of the certs go into a DB */
- die = genRand(1, 2); // one random bit
- if( ( (dbList != NULL) && (dbList->NumHandles != 0) ) &&
- ( (die == 1) || allInDbs) ) {
- /* put this cert in one of the DBs */
- 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 {
- /* find a random unused place in certGroupFrag */
- 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;
- }
- /* else try again and hope we don't spin forever */
- }
- } /* random place in certGroup */
- } /* main loop */
-
- if(dbList != NULL) {
- /*
- * Since we put some of the certs in dlDb rather than in certGroup,
- * compact the contents of certGroup. Its NumCerts is correct,
- * but some of the entries in CertList are empty.
- */
- unsigned i;
-
- for(certDex=0; certDex<numCerts; certDex++) {
- if(certGroup->GroupList.CertList[certDex].Data == NULL) {
- /* find next non-NULL cert */
- 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;
-}
-
-/*
- * Store a cert in specified DL/DB. All attributes are optional except
- * as noted (right?).
- */
-CSSM_RETURN tpStoreCert(
- CSSM_DL_DB_HANDLE dlDb,
- const CSSM_DATA_PTR cert,
- /* REQUIRED fields */
- CSSM_CERT_TYPE certType, // e.g. CSSM_CERT_X_509v3
- uint32 serialNum,
- const CSSM_DATA *issuer, // (shouldn't this be subject?)
- // normalized & encoded
- /* OPTIONAL fields */
- CSSM_CERT_ENCODING certEncoding, // e.g. CSSM_CERT_ENCODING_DER
- const CSSM_DATA *printName,
- const CSSM_DATA *subject) // normalized & encoded
-{
- 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;
- }
-
- /* how many attributes are we storing? */
- numAttributes = 4; // certType, serialNum, issuer, certEncoding
- if(printName != NULL) {
- numAttributes++;
- }
- if(subject != NULL) {
- numAttributes++;
- }
-
- /* cook up CSSM_DB_RECORD_ATTRIBUTE_DATA */
- recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE;
- recordAttrs.SemanticInformation = 0;
- recordAttrs.NumberOfAttributes = numAttributes;
- recordAttrs.AttributeData = attrs;
-
- /* grind thru the attributes - first the required ones plus certEncoding */
- 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++;
-
- /* now the options */
- 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++;
- }
-
- /* Okay, here we go */
- 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) {
- /* gross hack of inserting this "new" schema that Keychain didn't specify */
- crtn = tpAddCertSchema(dlDb);
- if(crtn == CSSM_OK) {
- /* Retry with a fully capable DLDB */
- crtn = CSSM_DL_DataInsert(dlDb,
- CSSM_DL_DB_RECORD_X509_CERTIFICATE,
- &recordAttrs,
- cert,
- &recordPtr);
- }
- }
- #endif /* FAKE_ADD_CERT_SCHEMA */
-
- /* free resources allocated to get this far */
- appFreeCssmData(serialNumData, CSSM_TRUE);
- if(recordPtr != NULL) {
- CSSM_DL_FreeUniqueRecord(dlDb, recordPtr);
- }
- if(crtn) {
- printError("CSSM_DL_DataInsert", crtn);
- }
- return crtn;
-}
-
-/*
- * Store a cert when we don't already know the required fields. We'll
- * extract them or make them up.
- */
-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;
-}
-
-/*
- * Generate numKeyPairs key pairs of specified algorithm and size.
- * Key labels will be 'keyLabelBase' concatenated with a 4-digit
- * decimal number.
- */
-CSSM_RETURN tpGenKeys(
- CSSM_CSP_HANDLE cspHand,
- CSSM_DL_DB_HANDLE dbHand, /* keys go here */
- unsigned numKeyPairs,
- uint32 keyGenAlg, /* CSSM_ALGID_RSA, etc. */
- uint32 keySizeInBits,
- const char *keyLabelBase, /* C string */
- CSSM_KEY_PTR pubKeys, /* array of keys RETURNED here */
- CSSM_KEY_PTR privKeys, /* array of keys RETURNED here */
- CSSM_DATA_PTR paramData) /* optional DSA params */
-{
- 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++) {
- /* unique label */
- sprintf(label+labelLen, "%04d", i);
- if(keyGenAlg == CSSM_ALGID_DSA) {
- crtn = cspGenDSAKeyPair(cspHand,
- label,
- labelLen + 4,
- keySizeInBits,
- &pubKeys[i],
- CSSM_FALSE, // pubIsRef
- CSSM_KEYUSE_VERIFY, // pubKeyUsage
- CSSM_KEYBLOB_RAW_FORMAT_NONE,
- &privKeys[i],
- CSSM_TRUE, // privIsRef
- CSSM_KEYUSE_SIGN,
- CSSM_KEYBLOB_RAW_FORMAT_NONE,
- CSSM_FALSE, // genParams
- paramData);
- }
- else {
- crtn = cspGenKeyPair(cspHand,
- keyGenAlg,
- // not used in X, yet dbHand,
- label,
- labelLen + 4,
- keySizeInBits,
- &pubKeys[i],
- CSSM_FALSE, // pubIsRef
- CSSM_KEYUSE_VERIFY, // pubKeyUsage
- CSSM_KEYBLOB_RAW_FORMAT_NONE,
- &privKeys[i],
- CSSM_TRUE, /// privIsRef
- CSSM_KEYUSE_SIGN,
- CSSM_KEYBLOB_RAW_FORMAT_NONE,
- CSSM_FALSE);
- }
- if(crtn) {
- return crtn;
- }
- }
-
- /* verify they are all different keys */
- 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;
-}
-
-/*
- * Generate a cert chain using specified key pairs. The last cert in the
- * chain (certs[numCerts-1]) is a root cert, self-signed.
- */
-CSSM_RETURN tpGenCerts(
- CSSM_CSP_HANDLE cspHand,
- CSSM_CL_HANDLE clHand,
- unsigned numCerts,
- uint32 sigAlg, /* CSSM_ALGID_SHA1WithRSA, etc. */
- const char *nameBase, /* C string */
- CSSM_KEY_PTR pubKeys, /* array of public keys */
- CSSM_KEY_PTR privKeys, /* array of private keys */
- CSSM_DATA_PTR certs, /* array of certs RETURNED here */
- const char *notBeforeStr, /* from genTimeAtNowPlus() */
- const char *notAfterStr) /* from genTimeAtNowPlus() */
-{
- return tpGenCertsStore(cspHand,
- clHand,
- numCerts,
- sigAlg,
- nameBase,
- pubKeys,
- privKeys,
- NULL, // storeArray
- certs,
- notBeforeStr,
- notAfterStr);
-}
-
-/*
- * Generate a cert chain using specified key pairs. The last cert in the
- * chain (certs[numCerts-1]) is a root cert, self-signed. Store
- * the certs indicated by corresponding element on storeArray. If
- * storeArray[n].DLHandle == 0, the cert is not stored.
- */
-CSSM_RETURN tpGenCertsStore(
- CSSM_CSP_HANDLE cspHand,
- CSSM_CL_HANDLE clHand,
- unsigned numCerts,
- uint32 sigAlg, /* CSSM_ALGID_SHA1WithRSA, etc. */
- const char *nameBase, /* C string */
- CSSM_KEY_PTR pubKeys, /* array of public keys */
- CSSM_KEY_PTR privKeys, /* array of private keys */
- CSSM_DL_DB_HANDLE *storeArray, /* array of certs stored here */
- CSSM_DATA_PTR certs, /* array of certs RETURNED here */
- const char *notBeforeStr, /* from genTimeAtNowPlus() */
- const char *notAfterStr) /* from genTimeAtNowPlus() */
-
-{
- int dex;
- CSSM_RETURN crtn;
- CSSM_X509_NAME *issuerName = NULL;
- CSSM_X509_NAME *subjectName = NULL;
- CSSM_X509_TIME *notBefore; // UTC-style "not before" time
- CSSM_X509_TIME *notAfter; // UTC-style "not after" time
- CSSM_DATA_PTR rawCert = NULL; // from CSSM_CL_CertCreateTemplate
- CSSM_DATA signedCert; // from CSSM_CL_CertSign
- uint32 rtn;
- CSSM_KEY_PTR signerKey; // signs the cert
- CSSM_CC_HANDLE signContext;
- char nameStr[100];
- CSSM_DATA_PTR thisCert; // ptr into certs[]
- CB_NameOid nameOid;
- CE_BasicConstraints bc;
- CSSM_X509_EXTENSION exten;
-
- nameOid.oid = &CSSMOID_OrganizationName; // const
- nameOid.string = nameStr;
-
- /* one extension for nonleaf indicating cA */
- 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;
-
- /* main loop - once per keypair/cert - starting at end/root */
- 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) {
- /* last (root) cert - subject same as issuer */
- issuerName = CB_BuildX509Name(&nameOid, 1);
- /* self-signed */
- signerKey = &privKeys[dex];
- }
- else {
- /* previous subject becomes current issuer */
- 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;
- }
-
- /*
- * not before/after in Y2k-compliant generalized time format.
- * These come preformatted from our caller.
- */
- notBefore = CB_BuildX509Time(0, notBeforeStr);
- notAfter = CB_BuildX509Time(0, notAfterStr);
-
- /*
- * Cook up cert template
- * Note serial number would be app-specified in real world
- */
- rawCert = CB_MakeCertTemplate(clHand,
- SERIAL_NUMBER_BASE + dex, // serial number
- issuerName,
- subjectName,
- notBefore,
- notAfter,
- &pubKeys[dex],
- sigAlg,
- NULL, // subj unique ID
- NULL, // issuer unique ID
- &exten, // extensions
- (dex == 0) ? 0 : 1);// numExtensions
-
- if(rawCert == NULL) {
- crtn = CSSM_ERRCODE_INTERNAL_ERROR;
- break;
- }
-
- /* Free the stuff we allocd to get here */
- CB_FreeX509Time(notBefore);
- CB_FreeX509Time(notAfter);
-
- /**** sign the cert ****/
- /* 1. get a signing context */
- crtn = CSSM_CSP_CreateSignatureContext(cspHand,
- sigAlg,
- NULL, // no passphrase for now
- signerKey,
- &signContext);
- if(crtn) {
- printError("CreateSignatureContext", crtn);
- break;
- }
-
- /* 2. use CL to sign the cert */
- signedCert.Data = NULL;
- signedCert.Length = 0;
- crtn = CSSM_CL_CertSign(clHand,
- signContext,
- rawCert, // CertToBeSigned
- NULL, // SignScope per spec
- 0, // ScopeSize per spec
- &signedCert);
- if(crtn) {
- printError("CSSM_CL_CertSign", crtn);
- break;
- }
-
- /* 3. Optionally store the cert in DL */
- if((storeArray != NULL) && storeArray[dex].DBHandle != 0) {
- crtn = tpStoreRawCert(storeArray[dex],
- clHand,
- &signedCert);
- if(crtn) {
- break;
- }
- }
-
- /* 4. delete signing context */
- crtn = CSSM_DeleteContext(signContext);
- if(crtn) {
- printError("CSSM_DeleteContext", crtn);
- break;
- }
-
- /*
- * CSSM_CL_CertSign() returned us a mallocd CSSM_DATA. Copy
- * its fields to caller's cert.
- */
- certs[dex] = signedCert;
-
- /* and the raw unsigned cert as well */
- appFreeCssmData(rawCert, CSSM_TRUE);
- rtn = 0;
- }
-
- /* free resources */
- if(issuerName != NULL) {
- CB_FreeX509Name(issuerName);
- }
- if(subjectName != NULL) {
- CB_FreeX509Name(subjectName);
- }
- return crtn;
-}
-
-/* compare two CSSM_CERTGROUPs, returns CSSM_TRUE on success */
-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];
-
- /* these are all errors */
- 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;
-}
-
-/* free a CSSM_CERT_GROUP */
-void tpFreeCertGroup(
- CSSM_CERTGROUP_PTR certGroup,
- CSSM_BOOL freeCertData, // free individual CertList.Data
- CSSM_BOOL freeStruct) // free the overall CSSM_CERTGROUP
-{
- unsigned dex;
-
- if(certGroup == NULL) {
- return;
- }
-
- if(freeCertData) {
- /* free the individual cert Data fields */
- for(dex=0; dex<certGroup->NumCerts; dex++) {
- appFreeCssmData(&certGroup->GroupList.CertList[dex], CSSM_FALSE);
- }
- }
-
- /* and the array of CSSM_DATAs */
- 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;
-
- /* just search by recordType, no predicates */
- query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE;
- query.Conjunctive = CSSM_DB_NONE;
- query.NumSelectionPredicates = 0;
- query.SelectionPredicate = NULL;
- query.QueryLimits.TimeLimit = 0; // FIXME - meaningful?
- query.QueryLimits.SizeLimit = 1; // FIXME - meaningful?
- query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used?
-
- crtn = CSSM_DL_DataGetFirst(dlDb,
- &query,
- &resultHand,
- &recordAttrs,
- NULL, // No data
- &record);
- switch(crtn) {
- case CSSM_OK:
- break; // proceed
- case CSSMERR_DL_ENDOFDATA:
- /* OK, no certs */
- 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);
-
- /* now the rest of them */
- 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; // and go again
- case CSSMERR_DL_ENDOFDATA:
- /* normal termination */
- break;
- default:
- printError("DataGetNext", crtn);
- return crtn;
- }
- if(crtn != CSSM_OK) {
- break;
- }
- }
- CSSM_DL_DataAbortQuery(dlDb, resultHand);
- return CSSM_OK;
-}
-
-/*
- * Wrapper for CSSM_TP_CertGroupVerify. What an ugly API.
- */
-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, // optional
- const CSSM_DATA *fieldOpts, // optional
- const CSSM_DATA *actionData, // optional
- void *policyOpts,
- const CSSM_CERTGROUP *certGroup,
- CSSM_DATA_PTR anchorCerts,
- unsigned numAnchorCerts,
- CSSM_TP_STOP_ON stopOn, // CSSM_TP_STOP_ON_POLICY, etc.
- CSSM_TIMESTRING cssmTimeStr,// optional
- CSSM_TP_VERIFY_CONTEXT_RESULT_PTR result) // optional, RETURNED
-{
- /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */
- 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_TP_CALLERAUTH_CONTEXT components */
- /*
- typedef struct cssm_tp_callerauth_context {
- CSSM_TP_POLICYINFO Policy;
- CSSM_TIMESTRING VerifyTime;
- CSSM_TP_STOP_ON VerificationAbortOn;
- CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert;
- uint32 NumberOfAnchorCerts;
- CSSM_DATA_PTR AnchorCerts;
- CSSM_DL_DB_LIST_PTR DBList;
- CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials;
- } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR;
- */
- /* zero or one policy here */
- 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; // may be NULL
- 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);
-}
-
-/*
- * Open, optionally create, KC-style DLDB.
- */
-#define KC_DB_PATH "Library/Keychains" /* relative to home */
-
-CSSM_RETURN tpKcOpen(
- CSSM_DL_HANDLE dlHand,
- const char *kcName,
- const char *pwd, // optional to avoid UI
- CSSM_BOOL doCreate,
- CSSM_DB_HANDLE *dbHand) // RETURNED
-{
- char kcPath[300];
- const char *kcFileName = kcName;
- char *userHome = getenv("HOME");
-
- if(userHome == NULL) {
- /* well, this is probably not going to work */
- userHome = (char *)"";
- }
- sprintf(kcPath, "%s/%s/%s", userHome, KC_DB_PATH, kcFileName);
- return dbCreateOpen(dlHand, kcPath,
- doCreate, CSSM_FALSE, pwd, dbHand);
-}
-
-/*
- * Free the contents of a CSSM_TP_VERIFY_CONTEXT_RESULT returned from
- * CSSM_TP_CertGroupVerify().
- */
-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:
- /* Evidence = (CSSM_TP_APPLE_EVIDENCE_HEADER *) */
- appFree(evp->Evidence, NULL);
- evp->Evidence = NULL;
- break;
- case CSSM_EVIDENCE_FORM_APPLE_CERTGROUP:
- {
- /* Evidence = CSSM_CERTGROUP_PTR */
- 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:
- {
- /* Evidence = array of CSSM_TP_APPLE_EVIDENCE_INFO */
- if(numCerts < 0) {
- /* Haven't gotten a CSSM_CERTGROUP_PTR! */
- 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++) {
- /* Dispose of StatusCodes, UniqueRecord */
- 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;
- }
- } /* for each cert info */
- appFree(evp->Evidence, NULL);
- evp->Evidence = NULL;
- break;
- } /* CSSM_EVIDENCE_FORM_APPLE_CERT_INFO */
- } /* switch(evp->EvidenceForm) */
- } /* for each evidence */
- if(ctx->Evidence) {
- appFree(ctx->Evidence, NULL);
- ctx->Evidence = NULL;
- }
- return crtn;
-}
-
-/* Display verify results */
-static void statusBitTest(
- CSSM_TP_APPLE_CERT_STATUS certStatus,
- uint32 bit,
- const char *str)
-{
- if(certStatus & bit) {
- printf("%s ", str);
- }
-}
-
-void printCertInfo(
- unsigned numCerts, // from CertGroup
- 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;
-}
-
-/* we really only need CSSM_EVIDENCE_FORM_APPLE_CERT_INFO */
-#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
- /* parse the rest of this eventually */
- /* Note we depend on this coming before the CERT_INFO */
- 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;
- }
- }
-}
-
-/*
- * Obtain system anchors in CF and in CSSM_DATA form.
- * Caller must CFRelease the returned rootArray and
- * free() the returned CSSM_DATA array, but not its
- * contents - SecCertificates themselves own that.
- */
-OSStatus getSystemAnchors(
- CFArrayRef *rootArray, /* RETURNED */
- CSSM_DATA **anchors, /* RETURNED */
- unsigned *numAnchors) /* RETURNED */
-{
- 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;
-}
-
-/* get a SecCertificateRef from a file */
-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;
-}
-