X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/b04fe171f0375ecd5d8a24747ca1dff85720a0ca..6b200bc335dc93c5516ccb52f14bd896d8c7fad7:/SecurityTests/clxutils/clAppUtils/tpUtils.cpp?ds=inline diff --git a/SecurityTests/clxutils/clAppUtils/tpUtils.cpp b/SecurityTests/clxutils/clAppUtils/tpUtils.cpp deleted file mode 100644 index 1e5e83d2..00000000 --- a/SecurityTests/clxutils/clAppUtils/tpUtils.cpp +++ /dev/null @@ -1,1215 +0,0 @@ -/* - * tpUtils.cpp - TP and cert group test support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * 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; certDexNumHandles != 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; certDexGroupList.CertList[certDex].Data == NULL) { - /* find next non-NULL cert */ - for(i=certDex+1; iGroupList.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=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; iNumCerts; 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; dexNumCerts; 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; iNumberOfEvidences; 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; iStatusBits; - 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; jNumStatusCodes; 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; dexEvidence[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; -} -