X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/clAppUtils/crlUtils.cpp?ds=sidebyside diff --git a/SecurityTests/clxutils/clAppUtils/crlUtils.cpp b/SecurityTests/clxutils/clAppUtils/crlUtils.cpp new file mode 100644 index 00000000..e126955b --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/crlUtils.cpp @@ -0,0 +1,318 @@ +/* + * crlUtils.cpp - CRL CL/TP/DL utilities. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* private API */ + +/* crlAddCrlToDb() removed due to build problem; obsoleted in favor of + * cuAddCrlToDb() in security_cdsa_utils + */ +#define CRL_ADD_TO_DB 0 + +#if CRL_ADD_TO_DB +#include /* private */ + /* SecInferLabelFromX509Name() */ + +/* + * Update an existing DLDB to be CRL-capable. + */ +static CSSM_RETURN crlAddCrlSchema( + CSSM_DL_DB_HANDLE dlDbHand) +{ + return CSSM_DL_CreateRelation(dlDbHand, + CSSM_DL_DB_RECORD_X509_CRL, + "CSSM_DL_DB_RECORD_X509_CRL", + Security::KeychainCore::Schema::X509CrlSchemaAttributeCount, + Security::KeychainCore::Schema::X509CrlSchemaAttributeList, + Security::KeychainCore::Schema::X509CrlSchemaIndexCount, + Security::KeychainCore::Schema::X509CrlSchemaIndexList); +} + +static void crlInferCrlLabel( + const CSSM_X509_NAME *x509Name, + CSSM_DATA *label) // not mallocd; contents are + // from the x509Name +{ + /* use private API for common "infer label" logic */ + const CSSM_DATA *printValue = SecInferLabelFromX509Name(x509Name); + if(printValue == NULL) { + /* punt! */ + label->Data = (uint8 *)"X509 CRL"; + label->Length = 8; + } + else { + *label = *printValue; + } +} + +/* + * Search extensions for specified OID, assumed to have underlying + * value type of uint32; returns the value and true if found. + */ +static bool crlSearchNumericExtension( + const CSSM_X509_EXTENSIONS *extens, + const CSSM_OID *oid, + uint32 *val) +{ + for(uint32 dex=0; dexnumberOfExtensions; dex++) { + const CSSM_X509_EXTENSION *exten = &extens->extensions[dex]; + if(!appCompareCssmData(&exten->extnId, oid)) { + continue; + } + if(exten->format != CSSM_X509_DATAFORMAT_PARSED) { + printf("***Malformed extension\n"); + continue; + } + *val = *((uint32 *)exten->value.parsedValue); + return true; + } + return false; +} + +/* + * Add a CRL to an existing DL/DB. + */ +#define MAX_CRL_ATTRS 8 + +CSSM_RETURN crlAddCrlToDb( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_CL_HANDLE clHand, + const CSSM_DATA *crl) +{ + CSSM_DB_ATTRIBUTE_DATA attrs[MAX_CRL_ATTRS]; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA_PTR attr = &attrs[0]; + CSSM_DATA crlTypeData; + CSSM_DATA crlEncData; + CSSM_DATA printNameData; + CSSM_RETURN crtn; + CSSM_DB_UNIQUE_RECORD_PTR recordPtr; + CSSM_DATA_PTR issuer; // mallocd by CL + CSSM_DATA_PTR crlValue; // ditto + uint32 numFields; + CSSM_HANDLE result; + CSSM_CRL_ENCODING crlEnc = CSSM_CRL_ENCODING_DER; + const CSSM_X509_SIGNED_CRL *signedCrl; + const CSSM_X509_TBS_CERTLIST *tbsCrl; + CSSM_CRL_TYPE crlType; + CSSM_DATA thisUpdateData = {0, NULL}; + CSSM_DATA nextUpdateData = {0, NULL}; + char *thisUpdate, *nextUpdate; + unsigned timeLen; + uint32 crlNumber; + uint32 deltaCrlNumber; + CSSM_DATA crlNumberData; + CSSM_DATA deltaCrlNumberData; + bool crlNumberPresent = false; + bool deltaCrlPresent = false; + + /* get normalized issuer name as Issuer attr */ + crtn = CSSM_CL_CrlGetFirstFieldValue(clHand, + crl, + &CSSMOID_X509V1IssuerName, + &result, + &numFields, + &issuer); + if(crtn) { + printError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn); + return crtn; + } + CSSM_CL_CrlAbortQuery(clHand, result); + + /* get parsed CRL from the CL */ + crtn = CSSM_CL_CrlGetFirstFieldValue(clHand, + crl, + &CSSMOID_X509V2CRLSignedCrlCStruct, + &result, + &numFields, + &crlValue); + if(crtn) { + printError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn); + return crtn; + } + CSSM_CL_CrlAbortQuery(clHand, result); + if(crlValue == NULL) { + printf("***CSSM_CL_CrlGetFirstFieldValue: value error (1)\n"); + return CSSMERR_CL_INVALID_CRL_POINTER; + } + if((crlValue->Data == NULL) || + (crlValue->Length != sizeof(CSSM_X509_SIGNED_CRL))) { + printf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n"); + return CSSMERR_CL_INVALID_CRL_POINTER; + } + signedCrl = (const CSSM_X509_SIGNED_CRL *)crlValue->Data; + tbsCrl = &signedCrl->tbsCertList; + + /* CrlType inferred from version */ + if(tbsCrl->version.Length == 0) { + /* should never happen... */ + crlType = CSSM_CRL_TYPE_X_509v1; + } + else { + uint8 vers = tbsCrl->version.Data[tbsCrl->version.Length - 1]; + switch(vers) { + case 0: + crlType = CSSM_CRL_TYPE_X_509v1; + break; + case 1: + crlType = CSSM_CRL_TYPE_X_509v2; + break; + default: + printf("***Unknown version in CRL (%u)\n", vers); + crlType = CSSM_CRL_TYPE_X_509v1; + break; + } + } + crlTypeData.Data = (uint8 *)&crlType; + crlTypeData.Length = sizeof(CSSM_CRL_TYPE); + /* encoding more-or-less assumed here */ + crlEncData.Data = (uint8 *)&crlEnc; + crlEncData.Length = sizeof(CSSM_CRL_ENCODING); + + /* printName inferred from issuer */ + crlInferCrlLabel(&tbsCrl->issuer, &printNameData); + + /* cook up CSSM_TIMESTRING versions of this/next update */ + thisUpdate = x509TimeToCssmTimestring(&tbsCrl->thisUpdate, &timeLen); + if(thisUpdate == NULL) { + printf("***Badly formatted thisUpdate\n"); + } + else { + thisUpdateData.Data = (uint8 *)thisUpdate; + thisUpdateData.Length = timeLen; + } + nextUpdate = x509TimeToCssmTimestring(&tbsCrl->nextUpdate, &timeLen); + if(nextUpdate == NULL) { + printf("***Badly formatted nextUpdate\n"); + } + else { + nextUpdateData.Data = (uint8 *)nextUpdate; + nextUpdateData.Length = timeLen; + } + + /* optional CrlNumber and DeltaCrlNumber */ + if(crlSearchNumericExtension(&tbsCrl->extensions, + &CSSMOID_CrlNumber, + &crlNumber)) { + crlNumberData.Data = (uint8 *)&crlNumber; + crlNumberData.Length = sizeof(uint32); + crlNumberPresent = true; + } + if(crlSearchNumericExtension(&tbsCrl->extensions, + &CSSMOID_DeltaCrlIndicator, + &deltaCrlNumber)) { + deltaCrlNumberData.Data = (uint8 *)&deltaCrlNumber; + deltaCrlNumberData.Length = sizeof(uint32); + deltaCrlPresent = true; + } + /* we spec six attributes, skipping alias and URI */ + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "CrlType"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &crlTypeData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "CrlEncoding"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &crlEncData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "PrintName"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = &printNameData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "Issuer"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = issuer; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "ThisUpdate"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = &thisUpdateData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "NextUpdate"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = &nextUpdateData; + attr++; + + /* now the optional attributes */ + if(crlNumberPresent) { + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "CrlNumber"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &crlNumberData; + attr++; + } + if(deltaCrlPresent) { + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "DeltaCrlNumber"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &deltaCrlNumberData; + attr++; + } + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CRL; + recordAttrs.SemanticInformation = 0; + recordAttrs.NumberOfAttributes = attr - attrs; + recordAttrs.AttributeData = attrs; + + crtn = CSSM_DL_DataInsert(dlDbHand, + CSSM_DL_DB_RECORD_X509_CRL, + &recordAttrs, + crl, + &recordPtr); + if(crtn == CSSMERR_DL_INVALID_RECORDTYPE) { + /* gross hack of inserting this "new" schema that + * Keychain didn't specify */ + crtn = crlAddCrlSchema(dlDbHand); + if(crtn == CSSM_OK) { + /* Retry with a fully capable DLDB */ + crtn = CSSM_DL_DataInsert(dlDbHand, + CSSM_DL_DB_RECORD_X509_CRL, + &recordAttrs, + crl, + &recordPtr); + } + } + if(crtn) { + printError("CSSM_DL_DataInsert", crtn); + } + else { + CSSM_DL_FreeUniqueRecord(dlDbHand, recordPtr); + } + + /* free all the stuff we allocated to get here */ + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1IssuerName, issuer); + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V2CRLSignedCrlCStruct, + crlValue); + free(thisUpdate); + free(nextUpdate); + return crtn; +} + +#endif /* CRL_ADD_TO_DB */