X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_apple_x509_tp/lib/TPDatabase.cpp diff --git a/Security/libsecurity_apple_x509_tp/lib/TPDatabase.cpp b/Security/libsecurity_apple_x509_tp/lib/TPDatabase.cpp deleted file mode 100644 index 5ba632f9..00000000 --- a/Security/libsecurity_apple_x509_tp/lib/TPDatabase.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (c) 2002-2009,2011-2012,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS - * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT - * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the - * specific language governing rights and limitations under the License. - */ - - -/* - * TPDatabase.cpp - TP's DL/DB access functions. - * - */ - -#include -#include -#include /* private API */ -#include /* private SecTrustKeychainsGetMutex() */ -#include /* private SecInferLabelFromX509Name() */ -#include -#include "TPDatabase.h" -#include "tpdebugging.h" -#include "certGroupUtils.h" -#include "TPCertInfo.h" -#include "TPCrlInfo.h" -#include "tpCrlVerify.h" -#include "tpTime.h" - - -/* - * Given a DL/DB, look up cert by subject name. Subsequent - * certs can be found using the returned result handle. - */ -static CSSM_DB_UNIQUE_RECORD_PTR tpCertLookup( - CSSM_DL_DB_HANDLE dlDb, - const CSSM_DATA *subjectName, // DER-encoded - CSSM_HANDLE_PTR resultHand, // RETURNED - CSSM_DATA_PTR cert) // RETURNED -{ - CSSM_QUERY query; - CSSM_SELECTION_PREDICATE predicate; - CSSM_DB_UNIQUE_RECORD_PTR record = NULL; - - cert->Data = NULL; - cert->Length = 0; - - /* SWAG until cert schema nailed down */ - predicate.DbOperator = CSSM_DB_EQUAL; - predicate.Attribute.Info.AttributeNameFormat = - CSSM_DB_ATTRIBUTE_NAME_AS_STRING; - predicate.Attribute.Info.Label.AttributeName = (char*) "Subject"; - predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; - predicate.Attribute.Value = const_cast(subjectName); - predicate.Attribute.NumberOfValues = 1; - - query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; - query.Conjunctive = CSSM_DB_NONE; - query.NumSelectionPredicates = 1; - query.SelectionPredicate = &predicate; - query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? - query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? - query.QueryFlags = 0; // FIXME - used? - - CSSM_DL_DataGetFirst(dlDb, - &query, - resultHand, - NULL, // don't fetch attributes - cert, - &record); - - return record; -} - -/* - * Search a list of DBs for a cert which verifies specified subject item. - * Just a boolean return - we found it, or not. If we did, we return - * TPCertInfo associated with the raw cert. - * A true partialIssuerKey on return indicates that caller must deal - * with partial public key processing later. - * If verifyCurrent is true, we will not return a cert which is not - * temporally valid; else we may well do so. - */ -TPCertInfo *tpDbFindIssuerCert( - Allocator &alloc, - CSSM_CL_HANDLE clHand, - CSSM_CSP_HANDLE cspHand, - const TPClItemInfo *subjectItem, - const CSSM_DL_DB_LIST *dbList, - const char *verifyTime, // may be NULL - bool &partialIssuerKey, // RETURNED - TPCertInfo *oldRoot) -{ - StLock _(SecTrustKeychainsGetMutex()); - - uint32 dbDex; - CSSM_HANDLE resultHand; - CSSM_DATA cert; - CSSM_DL_DB_HANDLE dlDb; - CSSM_DB_UNIQUE_RECORD_PTR record; - TPCertInfo *issuerCert = NULL; - bool foundIt; - TPCertInfo *expiredIssuer = NULL; - TPCertInfo *nonRootIssuer = NULL; - - partialIssuerKey = false; - if(dbList == NULL) { - return NULL; - } - for(dbDex=0; dbDexNumHandles; dbDex++) { - dlDb = dbList->DLDBHandle[dbDex]; - cert.Data = NULL; - cert.Length = 0; - resultHand = 0; - record = tpCertLookup(dlDb, - subjectItem->issuerName(), - &resultHand, - &cert); - /* remember we have to: - * -- abort this query regardless, and - * -- free the CSSM_DATA cert regardless, and - * -- free the unique record if we don't use it - * (by placing it in issuerCert)... - */ - if(record != NULL) { - /* Found one */ - assert(cert.Data != NULL); - tpDbDebug("tpDbFindIssuerCert: found cert record (1) %p", record); - issuerCert = NULL; - CSSM_RETURN crtn = CSSM_OK; - try { - issuerCert = new TPCertInfo(clHand, cspHand, &cert, TIC_CopyData, verifyTime); - } - catch(...) { - crtn = CSSMERR_TP_INVALID_CERTIFICATE; - } - - /* we're done with raw cert data */ - tpFreePluginMemory(dlDb.DLHandle, cert.Data); - cert.Data = NULL; - cert.Length = 0; - - /* Does it verify the subject cert? */ - if(crtn == CSSM_OK) { - crtn = subjectItem->verifyWithIssuer(issuerCert); - } - - /* - * Handle temporal invalidity - if so and this is the first one - * we've seen, hold on to it while we search for better one. - */ - if((crtn == CSSM_OK) && (expiredIssuer == NULL)) { - if(issuerCert->isExpired() || issuerCert->isNotValidYet()) { - /* - * Exact value not important here, this just uniquely identifies - * this situation in the switch below. - */ - tpDbDebug("tpDbFindIssuerCert: holding expired cert (1)"); - crtn = CSSM_CERT_STATUS_EXPIRED; - expiredIssuer = issuerCert; - expiredIssuer->dlDbHandle(dlDb); - expiredIssuer->uniqueRecord(record); - } - } - /* - * Prefer a root over an intermediate issuer if we can get one - * (in case a cross-signed intermediate and root are both available) - */ - if((crtn == CSSM_OK) && (nonRootIssuer == NULL)) { - if(!issuerCert->isSelfSigned()) { - /* - * Exact value not important here, this just uniquely identifies - * this situation in the switch below. - */ - tpDbDebug("tpDbFindIssuerCert: holding non-root cert (1)"); - crtn = CSSM_CERT_STATUS_IS_ROOT; - nonRootIssuer = issuerCert; - nonRootIssuer->dlDbHandle(dlDb); - nonRootIssuer->uniqueRecord(record); - } - } - switch(crtn) { - case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: - partialIssuerKey = true; - break; - case CSSM_OK: - if((oldRoot == NULL) || - !tp_CompareCerts(issuerCert->itemData(), oldRoot->itemData())) { - /* We found a new root cert which does not match the old one */ - break; - } - /* else fall through to search for a different one */ - default: - if(issuerCert != NULL) { - /* either holding onto this cert, or done with it. */ - if(crtn != CSSM_CERT_STATUS_EXPIRED && - crtn != CSSM_CERT_STATUS_IS_ROOT) { - delete issuerCert; - CSSM_DL_FreeUniqueRecord(dlDb, record); - } - issuerCert = NULL; - } - - /* - * Continue searching this DB. Break on finding the holy - * grail or no more records found. - */ - for(;;) { - cert.Data = NULL; - cert.Length = 0; - record = NULL; - CSSM_RETURN crtn = CSSM_DL_DataGetNext(dlDb, - resultHand, - NULL, // no attrs - &cert, - &record); - if(crtn) { - /* no more, done with this DB */ - assert(cert.Data == NULL); - break; - } - assert(cert.Data != NULL); - tpDbDebug("tpDbFindIssuerCert: found cert record (2) %p", record); - - /* found one - does it verify subject? */ - try { - issuerCert = new TPCertInfo(clHand, cspHand, &cert, TIC_CopyData, - verifyTime); - } - catch(...) { - crtn = CSSMERR_TP_INVALID_CERTIFICATE; - } - /* we're done with raw cert data */ - tpFreePluginMemory(dlDb.DLHandle, cert.Data); - cert.Data = NULL; - cert.Length = 0; - - if(crtn == CSSM_OK) { - crtn = subjectItem->verifyWithIssuer(issuerCert); - } - - /* temporal validity check, again */ - if((crtn == CSSM_OK) && (expiredIssuer == NULL)) { - if(issuerCert->isExpired() || issuerCert->isNotValidYet()) { - tpDbDebug("tpDbFindIssuerCert: holding expired cert (2)"); - crtn = CSSM_CERT_STATUS_EXPIRED; - expiredIssuer = issuerCert; - expiredIssuer->dlDbHandle(dlDb); - expiredIssuer->uniqueRecord(record); - } - } - /* self-signed check, again */ - if((crtn == CSSM_OK) && (nonRootIssuer == NULL)) { - if(!issuerCert->isSelfSigned()) { - tpDbDebug("tpDbFindIssuerCert: holding non-root cert (2)"); - crtn = CSSM_CERT_STATUS_IS_ROOT; - nonRootIssuer = issuerCert; - nonRootIssuer->dlDbHandle(dlDb); - nonRootIssuer->uniqueRecord(record); - } - } - - foundIt = false; - switch(crtn) { - case CSSM_OK: - /* duplicate check, again */ - if((oldRoot == NULL) || - !tp_CompareCerts(issuerCert->itemData(), oldRoot->itemData())) { - foundIt = true; - } - break; - case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: - partialIssuerKey = true; - foundIt = true; - break; - default: - break; - } - if(foundIt) { - /* yes! */ - break; - } - if(issuerCert != NULL) { - /* either holding onto this cert, or done with it. */ - if(crtn != CSSM_CERT_STATUS_EXPIRED && - crtn != CSSM_CERT_STATUS_IS_ROOT) { - delete issuerCert; - CSSM_DL_FreeUniqueRecord(dlDb, record); - } - issuerCert = NULL; - } - } /* searching subsequent records */ - } /* switch verify */ - - if(record != NULL) { - /* NULL record --> end of search --> DB auto-aborted */ - crtn = CSSM_DL_DataAbortQuery(dlDb, resultHand); - assert(crtn == CSSM_OK); - } - if(issuerCert != NULL) { - /* successful return */ - tpDbDebug("tpDbFindIssuer: returning record %p", record); - issuerCert->dlDbHandle(dlDb); - issuerCert->uniqueRecord(record); - if(expiredIssuer != NULL) { - /* We found a replacement */ - tpDbDebug("tpDbFindIssuer: discarding expired cert"); - expiredIssuer->freeUniqueRecord(); - delete expiredIssuer; - } - /* Avoid deleting the non-root cert if same as expired cert */ - if(nonRootIssuer != NULL && nonRootIssuer != expiredIssuer) { - /* We found a replacement */ - tpDbDebug("tpDbFindIssuer: discarding non-root cert"); - nonRootIssuer->freeUniqueRecord(); - delete nonRootIssuer; - } - return issuerCert; - } - } /* tpCertLookup, i.e., CSSM_DL_DataGetFirst, succeeded */ - else { - assert(cert.Data == NULL); - assert(resultHand == 0); - } - } /* main loop searching dbList */ - - if(nonRootIssuer != NULL) { - /* didn't find root issuer, so use this one */ - tpDbDebug("tpDbFindIssuer: taking non-root issuer cert, record %p", - nonRootIssuer->uniqueRecord()); - if(expiredIssuer != NULL && expiredIssuer != nonRootIssuer) { - expiredIssuer->freeUniqueRecord(); - delete expiredIssuer; - } - return nonRootIssuer; - } - - if(expiredIssuer != NULL) { - /* OK, we'll take this one */ - tpDbDebug("tpDbFindIssuer: taking expired cert after all, record %p", - expiredIssuer->uniqueRecord()); - return expiredIssuer; - } - /* issuer not found */ - return NULL; -} - -/* - * Given a DL/DB, look up CRL by issuer name and validity time. - * Subsequent CRLs can be found using the returned result handle. - */ -#define SEARCH_BY_DATE 1 - -static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( - CSSM_DL_DB_HANDLE dlDb, - const CSSM_DATA *issuerName, // DER-encoded - CSSM_TIMESTRING verifyTime, // may be NULL, implies "now" - CSSM_HANDLE_PTR resultHand, // RETURNED - CSSM_DATA_PTR crl) // RETURNED -{ - CSSM_QUERY query; - CSSM_SELECTION_PREDICATE pred[3]; - CSSM_DB_UNIQUE_RECORD_PTR record = NULL; - char timeStr[CSSM_TIME_STRLEN + 1]; - - crl->Data = NULL; - crl->Length = 0; - - /* Three predicates...first, the issuer name */ - pred[0].DbOperator = CSSM_DB_EQUAL; - pred[0].Attribute.Info.AttributeNameFormat = - CSSM_DB_ATTRIBUTE_NAME_AS_STRING; - pred[0].Attribute.Info.Label.AttributeName = (char*) "Issuer"; - pred[0].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; - pred[0].Attribute.Value = const_cast(issuerName); - pred[0].Attribute.NumberOfValues = 1; - - /* now before/after. Cook up an appropriate time string. */ - if(verifyTime != NULL) { - /* Caller spec'd tolerate any format */ - int rtn = tpTimeToCssmTimestring(verifyTime, (unsigned)strlen(verifyTime), timeStr); - if(rtn) { - tpErrorLog("tpCrlLookup: Invalid VerifyTime string\n"); - return NULL; - } - } - else { - /* right now */ - StLock _(tpTimeLock()); - timeAtNowPlus(0, TIME_CSSM, timeStr); - } - CSSM_DATA timeData; - timeData.Data = (uint8 *)timeStr; - timeData.Length = CSSM_TIME_STRLEN; - - #if SEARCH_BY_DATE - pred[1].DbOperator = CSSM_DB_LESS_THAN; - pred[1].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; - pred[1].Attribute.Info.Label.AttributeName = (char*) "NextUpdate"; - pred[1].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; - pred[1].Attribute.Value = &timeData; - pred[1].Attribute.NumberOfValues = 1; - - pred[2].DbOperator = CSSM_DB_GREATER_THAN; - pred[2].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; - pred[2].Attribute.Info.Label.AttributeName = (char*) "ThisUpdate"; - pred[2].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; - pred[2].Attribute.Value = &timeData; - pred[2].Attribute.NumberOfValues = 1; - #endif - - query.RecordType = CSSM_DL_DB_RECORD_X509_CRL; - query.Conjunctive = CSSM_DB_AND; - #if SEARCH_BY_DATE - query.NumSelectionPredicates = 3; - #else - query.NumSelectionPredicates = 1; - #endif - query.SelectionPredicate = pred; - query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? - query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? - query.QueryFlags = 0; // FIXME - used? - - CSSM_DL_DataGetFirst(dlDb, - &query, - resultHand, - NULL, // don't fetch attributes - crl, - &record); - return record; -} - -/* - * Search a list of DBs for a CRL from the specified issuer and (optional) - * TPVerifyContext.verifyTime. - * Just a boolean return - we found it, or not. If we did, we return a - * TPCrlInfo which has been verified with the specified TPVerifyContext. - */ -TPCrlInfo *tpDbFindIssuerCrl( - TPVerifyContext &vfyCtx, - const CSSM_DATA &issuer, - TPCertInfo &forCert) -{ - StLock _(SecTrustKeychainsGetMutex()); - - uint32 dbDex; - CSSM_HANDLE resultHand; - CSSM_DATA crl; - CSSM_DL_DB_HANDLE dlDb; - CSSM_DB_UNIQUE_RECORD_PTR record; - TPCrlInfo *issuerCrl = NULL; - CSSM_DL_DB_LIST_PTR dbList = vfyCtx.dbList; - CSSM_RETURN crtn; - - if(dbList == NULL) { - return NULL; - } - for(dbDex=0; dbDexNumHandles; dbDex++) { - dlDb = dbList->DLDBHandle[dbDex]; - crl.Data = NULL; - crl.Length = 0; - record = tpCrlLookup(dlDb, - &issuer, - vfyCtx.verifyTime, - &resultHand, - &crl); - /* remember we have to: - * -- abort this query regardless, and - * -- free the CSSM_DATA crl regardless, and - * -- free the unique record if we don't use it - * (by placing it in issuerCert)... - */ - if(record != NULL) { - /* Found one */ - assert(crl.Data != NULL); - issuerCrl = new TPCrlInfo(vfyCtx.clHand, - vfyCtx.cspHand, - &crl, - TIC_CopyData, - vfyCtx.verifyTime); - /* we're done with raw CRL data */ - /* FIXME this assumes that vfyCtx.alloc is the same as the - * allocator associated with DlDB...OK? */ - tpFreeCssmData(vfyCtx.alloc, &crl, CSSM_FALSE); - crl.Data = NULL; - crl.Length = 0; - - /* and we're done with the record */ - CSSM_DL_FreeUniqueRecord(dlDb, record); - - /* Does it verify with specified context? */ - crtn = issuerCrl->verifyWithContextNow(vfyCtx, &forCert); - if(crtn) { - - delete issuerCrl; - issuerCrl = NULL; - - /* - * Verify fail. Continue searching this DB. Break on - * finding the holy grail or no more records found. - */ - for(;;) { - crl.Data = NULL; - crl.Length = 0; - crtn = CSSM_DL_DataGetNext(dlDb, - resultHand, - NULL, // no attrs - &crl, - &record); - if(crtn) { - /* no more, done with this DB */ - assert(crl.Data == NULL); - break; - } - assert(crl.Data != NULL); - - /* found one - is it any good? */ - issuerCrl = new TPCrlInfo(vfyCtx.clHand, - vfyCtx.cspHand, - &crl, - TIC_CopyData, - vfyCtx.verifyTime); - /* we're done with raw CRL data */ - /* FIXME this assumes that vfyCtx.alloc is the same as the - * allocator associated with DlDB...OK? */ - tpFreeCssmData(vfyCtx.alloc, &crl, CSSM_FALSE); - crl.Data = NULL; - crl.Length = 0; - - CSSM_DL_FreeUniqueRecord(dlDb, record); - - crtn = issuerCrl->verifyWithContextNow(vfyCtx, &forCert); - if(crtn == CSSM_OK) { - /* yes! */ - break; - } - delete issuerCrl; - issuerCrl = NULL; - } /* searching subsequent records */ - } /* verify fail */ - /* else success! */ - - if(issuerCrl != NULL) { - /* successful return */ - CSSM_DL_DataAbortQuery(dlDb, resultHand); - tpDebug("tpDbFindIssuerCrl: found CRL record %p", record); - return issuerCrl; - } - } /* tpCrlLookup, i.e., CSSM_DL_DataGetFirst, succeeded */ - else { - assert(crl.Data == NULL); - } - /* in any case, abort the query for this db */ - CSSM_DL_DataAbortQuery(dlDb, resultHand); - - } /* main loop searching dbList */ - - /* issuer not found */ - return NULL; -} -