]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_apple_x509_tp/lib/TPDatabase.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / 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 (file)
index 5ba632f..0000000
+++ /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 <Security/cssmtype.h>
-#include <Security/cssmapi.h>
-#include <security_cdsa_utilities/Schema.h>            /* private API */
-#include <security_keychain/TrustKeychains.h>  /* private SecTrustKeychainsGetMutex() */
-#include <Security/SecCertificatePriv.h>               /* private SecInferLabelFromX509Name() */
-#include <Security/oidscert.h>
-#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<CSSM_DATA_PTR>(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<Mutex> _(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; dbDex<dbList->NumHandles; 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<CSSM_DATA_PTR>(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<Mutex> _(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<Mutex> _(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; dbDex<dbList->NumHandles; 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;
-}
-