+++ /dev/null
-/*
- * Copyright (c) 2002,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.
- */
-
-
-/*
- * TPCrlInfo.h - TP's private CRL and CRL group
- *
- */
-
-#include "TPCrlInfo.h"
-#include "tpdebugging.h"
-#include "certGroupUtils.h"
-#include "tpCrlVerify.h"
-#include "tpPolicies.h"
-#include "tpTime.h"
-#include <Security/cssmapi.h>
-#include <Security/x509defs.h>
-#include <Security/oidscert.h>
-#include <Security/oidscrl.h>
-#include <security_cdsa_utilities/cssmerrors.h>
-#include <string.h> /* for memcmp */
-#include <Security/cssmapple.h>
-
-/*
- * Replacement for CSSM_CL_CrlGetFirstCachedFieldValue for use with
- * TPCrlItemInfo's generic getFirstCachedField mechanism.
- */
-static CSSM_RETURN tpGetFirstCachedFieldValue (CSSM_CL_HANDLE CLHandle,
- CSSM_HANDLE CrlHandle,
- const CSSM_OID *CrlField,
- CSSM_HANDLE_PTR ResultsHandle,
- uint32 *NumberOfMatchedFields,
- CSSM_DATA_PTR *Value)
-{
- return CSSM_CL_CrlGetFirstCachedFieldValue(CLHandle,
- CrlHandle,
- NULL, // const CSSM_DATA *CrlRecordIndex,
- CrlField,
- ResultsHandle,
- NumberOfMatchedFields,
- Value);
-}
-
-static const TPClItemCalls tpCrlClCalls =
-{
- tpGetFirstCachedFieldValue,
- CSSM_CL_CrlAbortQuery,
- CSSM_CL_CrlCache,
- CSSM_CL_CrlAbortCache,
- CSSM_CL_CrlVerify,
- &CSSMOID_X509V1CRLThisUpdate,
- &CSSMOID_X509V1CRLNextUpdate,
- CSSMERR_TP_INVALID_CRL_POINTER,
- CSSMERR_APPLETP_CRL_EXPIRED,
- CSSMERR_APPLETP_CRL_NOT_VALID_YET
-};
-
-
-/*
- * No default constructor - this is the only way.
- * This caches the cert and fetches subjectName and issuerName
- * to ensure the incoming certData is well-constructed.
- */
-TPCrlInfo::TPCrlInfo(
- CSSM_CL_HANDLE clHand,
- CSSM_CSP_HANDLE cspHand,
- const CSSM_DATA *crlData,
- TPItemCopy copyCrlData, // true: we copy, we free
- // false - caller owns
- const char *verifyTime) // = NULL
-
- : TPClItemInfo(clHand, cspHand, tpCrlClCalls, crlData,
- copyCrlData, verifyTime),
- mRefCount(0),
- mFromWhere(CFW_Nowhere),
- mX509Crl(NULL),
- mCrlFieldToFree(NULL),
- mVerifyState(CVS_Unknown),
- mVerifyError(CSSMERR_TP_INTERNAL_ERROR)
-{
- CSSM_RETURN crtn;
-
- mUri.Data = NULL;
- mUri.Length = 0;
-
- /* fetch parsed CRL */
- crtn = fetchField(&CSSMOID_X509V2CRLSignedCrlCStruct, &mCrlFieldToFree);
- if(crtn) {
- /* bad CRL */
- releaseResources();
- CssmError::throwMe(crtn);
- }
- if(mCrlFieldToFree->Length != sizeof(CSSM_X509_SIGNED_CRL)) {
- tpErrorLog("fetchField(SignedCrlCStruct) length error\n");
- releaseResources();
- CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR);
- }
- mX509Crl = (CSSM_X509_SIGNED_CRL *)mCrlFieldToFree->Data;
- /* any other other commonly used fields? */
-}
-
-TPCrlInfo::~TPCrlInfo()
-{
- releaseResources();
-}
-
-void TPCrlInfo::releaseResources()
-{
- if(mCrlFieldToFree) {
- freeField(&CSSMOID_X509V2CRLSignedCrlCStruct, mCrlFieldToFree);
- mCrlFieldToFree = NULL;
- }
- if(mUri.Data) {
- Allocator::standard().free(mUri.Data);
- mUri.Data = NULL;
- mUri.Length = 0;
- }
- TPClItemInfo::releaseResources();
-}
-
-void TPCrlInfo::uri(const CSSM_DATA &uri)
-{
- tpCopyCssmData(Allocator::standard(), &uri, &mUri);
-}
-
-/*
- * List of extensions we understand and can accept as critical.
- */
-static const CSSM_OID *const TPGoodCrlExtens[] =
-{
- &CSSMOID_CrlNumber,
- /* Note NOT CSSMOID_DeltaCrlIndicator! That's fatal */
- &CSSMOID_CrlReason,
- &CSSMOID_CertIssuer,
- &CSSMOID_IssuingDistributionPoint,
- &CSSMOID_HoldInstructionCode,
- &CSSMOID_InvalidityDate,
- &CSSMOID_AuthorityKeyIdentifier,
- &CSSMOID_SubjectAltName,
- &CSSMOID_IssuerAltName
-};
-
-#define NUM_KNOWN_EXTENS (sizeof(TPGoodCrlExtens) / sizeof(CSSM_OID_PTR))
-
-/*
- * Do our best to understand all the entries in a CSSM_X509_EXTENSIONS,
- * which may be per-CRL or per-entry.
- *
- * For now, we just ensure that for every critical extension,
- * we actually understand it and can deal it.
- */
-CSSM_RETURN TPCrlInfo::parseExtensions(
- TPVerifyContext &vfyCtx,
- bool isPerEntry,
- uint32 entryIndex, // if isPerEntry
- const CSSM_X509_EXTENSIONS &extens,
- TPCertInfo *forCert, // optional
- bool &isIndirectCrl) // RETURNED
-{
- isIndirectCrl = false;
- for(uint32 dex=0; dex<extens.numberOfExtensions; dex++) {
- CSSM_X509_EXTENSION_PTR exten = &extens.extensions[dex];
- if(exten->critical) {
- /* critical: is it in our list of understood extensions? */
- unsigned i;
- for(i=0; i<NUM_KNOWN_EXTENS; i++) {
- if(tpCompareOids(&exten->extnId, TPGoodCrlExtens[i])) {
- /* we're cool with this one */
- break;
- }
- }
- if(i == NUM_KNOWN_EXTENS) {
- tpCrlDebug("parseExtensions: Unknown Critical Extension\n");
- return CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN;
- }
- }
-
- /* Specific extension handling. */
- if(tpCompareOids(&exten->extnId,
- &CSSMOID_IssuingDistributionPoint)) {
- /*
- * If this assertion fails, we're out of sync with the CL
- */
- assert(exten->format == CSSM_X509_DATAFORMAT_PARSED);
- CE_IssuingDistributionPoint *idp =
- (CE_IssuingDistributionPoint *)
- exten->value.parsedValue;
-
- /*
- * Snag indirectCrl flag for caller in any case
- */
- if(idp->indirectCrlPresent && idp->indirectCrl) {
- isIndirectCrl = true;
- }
- if(forCert != NULL) {
- /* If no target cert, i.e., we're just verifying a CRL,
- * skip the remaining IDP checks. */
-
- /* verify onlyCACerts/onlyUserCerts */
- bool isUserCert;
- if(forCert->isLeaf() &&
- !(vfyCtx.actionFlags & CSSM_TP_ACTION_LEAF_IS_CA)) {
- isUserCert = true;
- }
- else {
- isUserCert = false;
- }
- if((idp->onlyUserCertsPresent) && (idp->onlyUserCerts)) {
- if(!isUserCert) {
- tpCrlDebug("parseExtensions: onlyUserCerts, "
- "!leaf\n");
- return CSSMERR_APPLETP_IDP_FAIL;
- }
- }
- if((idp->onlyCACertsPresent) && (idp->onlyCACerts)) {
- if(isUserCert) {
- tpCrlDebug("parseExtensions: onlyCACerts, leaf\n");
- return CSSMERR_APPLETP_IDP_FAIL;
- }
- }
- } /* IDP */
- } /* have target cert */
- }
-
- return CSSM_OK;
-}
-
-/*
- * The heavyweight "perform full verification of this CRL" op.
- * Must verify to an anchor cert in tpVerifyContext or via
- * Trust Settings if so enabled.
- * Intermediate certs can come from signerCerts or dBList.
- */
-CSSM_RETURN TPCrlInfo::verifyWithContext(
- TPVerifyContext &tpVerifyContext,
- TPCertInfo *forCert, // optional
- bool doCrlVerify)
-{
- /*
- * Step 1: this CRL must be current. Caller might have re-evaluated
- * expired/notValidYet since our construction via calculateCurrent().
- */
- if(isExpired()) {
- return CSSMERR_APPLETP_CRL_EXPIRED;
- }
- if(isNotValidYet()) {
- return CSSMERR_APPLETP_CRL_NOT_VALID_YET;
- }
-
- /* subsequent verify state is cached */
- switch(mVerifyState) {
- case CVS_Good:
- return CSSM_OK;
- case CVS_Bad:
- return mVerifyError;
- case CVS_Unknown:
- break;
- default:
- tpErrorLog("verifyWithContext: bad verifyState\n");
- return CSSMERR_TP_INTERNAL_ERROR;
- }
-
- /*
- * Step 2: parse & understand all critical CRL extensions.
- */
- CSSM_RETURN crtn;
- bool isIndirectCrl;
- crtn = parseExtensions(tpVerifyContext,
- false,
- 0,
- mX509Crl->tbsCertList.extensions,
- forCert,
- isIndirectCrl);
- if(crtn) {
- mVerifyState = CVS_Bad;
- if(!forCert || forCert->addStatusCode(crtn)) {
- return crtn;
- }
- /* else continue */
- }
- CSSM_X509_REVOKED_CERT_LIST_PTR revoked =
- mX509Crl->tbsCertList.revokedCertificates;
- if(revoked != NULL) {
- for(uint32 dex=0; dex<revoked->numberOfRevokedCertEntries; dex++) {
- bool dummyIsIndirect; // can't be set here
- crtn = parseExtensions(tpVerifyContext,
- true,
- dex,
- revoked->revokedCertEntry[dex].extensions,
- forCert,
- dummyIsIndirect);
- if(crtn) {
- if(!forCert || forCert->addStatusCode(crtn)) {
- mVerifyState = CVS_Bad;
- return crtn;
- }
- }
- }
- }
-
- /*
- * Step 3: obtain a fully verified cert chain which verifies this CRL.
- */
- CSSM_BOOL verifiedToRoot;
- CSSM_BOOL verifiedToAnchor;
- CSSM_BOOL verifiedViaTrustSetting;
-
- TPCertGroup outCertGroup(tpVerifyContext.alloc,
- TGO_Caller); // CRLs owned by inCertGroup
-
- /* set up for disposal of TPCertInfos created by
- * CertGroupConstructPriv */
- TPCertGroup certsToBeFreed(tpVerifyContext.alloc, TGO_Group);
-
- if(tpVerifyContext.signerCerts) {
- /* start from scratch with this group */
- tpVerifyContext.signerCerts->setAllUnused();
- }
- crtn = outCertGroup.buildCertGroup(
- *this, // subject item
- tpVerifyContext.signerCerts, // inCertGroup, optional
- tpVerifyContext.dbList, // optional
- tpVerifyContext.clHand,
- tpVerifyContext.cspHand,
- tpVerifyContext.verifyTime,
- tpVerifyContext.numAnchorCerts,
- tpVerifyContext.anchorCerts,
- certsToBeFreed,
- &tpVerifyContext.gatheredCerts,
- CSSM_FALSE, // subjectIsInGroup
- tpVerifyContext.actionFlags,
- tpVerifyContext.policyOid,
- tpVerifyContext.policyStr,
- tpVerifyContext.policyStrLen,
- kSecTrustSettingsKeyUseSignRevocation,
- verifiedToRoot,
- verifiedToAnchor,
- verifiedViaTrustSetting);
- /* subsequent errors to errOut: */
-
- if(crtn) {
- tpCrlDebug("TPCrlInfo::verifyWithContext buildCertGroup failure "
- "index %u", index());
- if(!forCert || forCert->addStatusCode(crtn)) {
- goto errOut;
- }
- }
- if (verifiedToRoot && (tpVerifyContext.actionFlags & CSSM_TP_ACTION_IMPLICIT_ANCHORS))
- verifiedToAnchor = CSSM_TRUE;
- if(!verifiedToAnchor && !verifiedViaTrustSetting) {
- /* required */
- if(verifiedToRoot) {
- /* verified to root which is not an anchor */
- tpCrlDebug("TPCrlInfo::verifyWithContext root, no anchor, "
- "index %u", index());
- crtn = CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT;
- }
- else {
- /* partial chain, no root, not verifiable by anchor */
- tpCrlDebug("TPCrlInfo::verifyWithContext no root, no anchor, "
- "index %u", index());
- crtn = CSSMERR_APPLETP_CRL_NOT_TRUSTED;
- }
- if(!forCert || forCert->addStatusCode(crtn)) {
- mVerifyState = CVS_Bad;
- goto errOut;
- }
- }
-
- /*
- * Step 4: policy verification on the returned cert group
- * We need to (temporarily) assert the "leaf cert is a CA" flag
- * here.
- */
- outCertGroup.certAtIndex(0)->isLeaf(true);
- crtn = tp_policyVerify(kCrlPolicy,
- tpVerifyContext.alloc,
- tpVerifyContext.clHand,
- tpVerifyContext.cspHand,
- &outCertGroup,
- verifiedToRoot,
- verifiedViaTrustSetting,
- tpVerifyContext.actionFlags | CSSM_TP_ACTION_LEAF_IS_CA,
- NULL, // sslOpts
- NULL); // policyOpts, not currently used
- if(crtn) {
- tpCrlDebug(" ...verifyWithContext policy FAILURE CRL %u",
- index());
- if(!forCert || forCert->addStatusCode(CSSMERR_APPLETP_CRL_POLICY_FAIL)) {
- mVerifyState = CVS_Bad;
- goto errOut;
- }
- }
-
- /*
- * Step 5: recursively perform CRL verification on the certs
- * gathered to verify this CRL.
- * Only performed if this CRL is an indirect CRL or the caller
- * explicitly told us to do this (i.e., caller is verifying a
- * CRL, not a cert chain).
- */
- if(isIndirectCrl || doCrlVerify) {
- tpCrlDebug("verifyWithContext recursing to "
- "tpVerifyCertGroupWithCrls");
- crtn = tpVerifyCertGroupWithCrls(tpVerifyContext,
- outCertGroup);
- if(crtn) {
- tpCrlDebug(" ...verifyWithContext CRL reverify FAILURE CRL %u",
- index());
- if(!forCert || forCert->addStatusCode(crtn)) {
- mVerifyState = CVS_Bad;
- goto errOut;
- }
- }
- }
-
- tpCrlDebug(" ...verifyWithContext CRL %u SUCCESS", index());
- mVerifyState = CVS_Good;
-errOut:
- /* we own these, we free the DB records */
- certsToBeFreed.freeDbRecords();
- return crtn;
-}
-
-/*
- * Wrapper for verifyWithContext for use when evaluating a CRL
- * "now" instead of at the time in TPVerifyContext.verifyTime.
- * In this case, on entry, TPVerifyContext.verifyTime is the
- * time at which a cert is being evaluated.
- */
-CSSM_RETURN TPCrlInfo::verifyWithContextNow(
- TPVerifyContext &tpVerifyContext,
- TPCertInfo *forCert, // optional
- bool doCrlVerify)
-{
- CSSM_TIMESTRING ctxTime = tpVerifyContext.verifyTime;
- CSSM_RETURN crtn = verifyWithContext(tpVerifyContext, forCert, doCrlVerify);
- tpVerifyContext.verifyTime = ctxTime;
- return crtn;
-}
-
-/*
- * Do I have the same issuer as the specified subject cert? Returns
- * true if so.
- */
-bool TPCrlInfo::hasSameIssuer(
- const TPCertInfo &subject)
-{
- assert(subject.issuerName() != NULL);
- if(tpCompareCssmData(issuerName(), subject.issuerName())) {
- return true;
- }
- else {
- return false;
- }
-}
-
-/*
- * Determine if specified cert has been revoked as of the
- * provided time; a NULL timestring indicates "now".
- *
- * Assumes current CRL is verified good and that issuer names of
- * the cert and CRL match.
- *
- * This duplicates similar logic in the CL, but to avoid re-parsing
- * the subject cert (which we have parsed and cached), we just do it
- * here.
- *
- * Possible errors are
- * CSSMERR_TP_CERT_REVOKED
- * CSSMERR_TP_CERT_SUSPENDED
- * TBD
- *
- * Error status is added to subjectCert.
- */
-CSSM_RETURN TPCrlInfo::isCertRevoked(
- TPCertInfo &subjectCert,
- CSSM_TIMESTRING verifyTime)
-{
- assert(mVerifyState == CVS_Good);
- CSSM_X509_TBS_CERTLIST_PTR tbs = &mX509Crl->tbsCertList;
-
- /* trivial case - empty CRL */
- if((tbs->revokedCertificates == NULL) ||
- (tbs->revokedCertificates->numberOfRevokedCertEntries == 0)) {
- tpCrlDebug(" isCertRevoked: empty CRL at index %u", index());
- return CSSM_OK;
- }
-
- /* is subject cert's serial number in this CRL? */
- CSSM_DATA_PTR subjSerial = NULL;
- CSSM_RETURN crtn;
- crtn = subjectCert.fetchField(&CSSMOID_X509V1SerialNumber, &subjSerial);
- if(crtn) {
- /* should never happen */
- tpErrorLog("TPCrlInfo:isCertRevoked: error fetching serial number\n");
- if(subjectCert.addStatusCode(crtn)) {
- return crtn;
- }
- else {
- /* allowed error - can't proceed; punt with success */
- return CSSM_OK;
- }
- }
- /* subsequent errors to errOut: */
-
- uint32 numEntries = tbs->revokedCertificates->numberOfRevokedCertEntries;
- CSSM_X509_REVOKED_CERT_ENTRY_PTR entries =
- tbs->revokedCertificates->revokedCertEntry;
- crtn = CSSM_OK;
- CFDateRef cfRevokedTime = NULL;
- CFDateRef cfVerifyTime = NULL;
-
- for(uint32 dex=0; dex<numEntries; dex++) {
- CSSM_X509_REVOKED_CERT_ENTRY_PTR entry = &entries[dex];
- if(tpCompareCssmData(subjSerial, &entry->certificateSerialNumber)) {
- /*
- * It's in there. Compare revocation time in the CRL to
- * our caller-specified verifyTime.
- */
- CSSM_X509_TIME_PTR xTime = &entry->revocationDate;
- int rtn;
- rtn = timeStringToCfDate((char *)xTime->time.Data, (unsigned)xTime->time.Length,
- &cfRevokedTime);
- if(rtn) {
- tpErrorLog("fetchNotBeforeAfter: malformed revocationDate\n");
- }
- else {
- if(verifyTime != NULL) {
- rtn = timeStringToCfDate((char *)verifyTime, (unsigned)strlen(verifyTime),
- &cfVerifyTime);
- }
- else {
- /* verify right now */
- cfVerifyTime = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
- }
- if((rtn == 0) && cfVerifyTime != NULL) {
- CFComparisonResult res = CFDateCompare(cfVerifyTime, cfRevokedTime, NULL);
- if(res == kCFCompareLessThan) {
- /* cfVerifyTime < cfRevokedTime; I guess this one's OK */
- tpCrlDebug(" isCertRevoked: cert %u NOT YET REVOKED by CRL %u",
- subjectCert.index(), index());
- break;
- }
- }
- }
-
- /*
- * REQUIRED TBD: parse the entry's extensions, specifically to
- * get a reason. This will entail a bunch of new TP/cert specific
- * CSSM_RETURNS.
- * For now, just flag it revoked.
- */
- crtn = CSSMERR_TP_CERT_REVOKED;
- tpCrlDebug(" isCertRevoked: cert %u REVOKED by CRL %u",
- subjectCert.index(), index());
- break;
- }
- }
-
- subjectCert.freeField(&CSSMOID_X509V1SerialNumber, subjSerial);
- if(crtn && !subjectCert.addStatusCode(crtn)) {
- return CSSM_OK;
- }
- if(cfRevokedTime) {
- CFRelease(cfRevokedTime);
- }
- if(cfVerifyTime) {
- CFRelease(cfVerifyTime);
- }
- return crtn;
-}
-
-/***
- *** TPCrlGroup class
- ***/
-
-/* build empty group */
-TPCrlGroup::TPCrlGroup(
- Allocator &alloc,
- TPGroupOwner whoOwns) :
- mAlloc(alloc),
- mCrlInfo(NULL),
- mNumCrls(0),
- mSizeofCrlInfo(0),
- mWhoOwns(whoOwns)
-{
- /* nothing for now */
-}
-
-/*
- * Construct from unordered, untrusted CSSM_CRLGROUP. Resulting
- * TPCrlInfos are more or less in the same order as the incoming
- * CRLs, though incoming CRLs are discarded if they don't parse.
- * No verification of any sort is performed.
- */
-TPCrlGroup::TPCrlGroup(
- const CSSM_CRLGROUP *cssmCrlGroup, // optional
- CSSM_CL_HANDLE clHand,
- CSSM_CSP_HANDLE cspHand,
- Allocator &alloc,
- const char *verifyTime, // may be NULL
- TPGroupOwner whoOwns) :
- mAlloc(alloc),
- mCrlInfo(NULL),
- mNumCrls(0),
- mSizeofCrlInfo(0),
- mWhoOwns(whoOwns)
-{
- /* verify input args */
- if((cssmCrlGroup == NULL) || (cssmCrlGroup->NumberOfCrls == 0)) {
- return;
- }
- if(cspHand == CSSM_INVALID_HANDLE) {
- CssmError::throwMe(CSSMERR_TP_INVALID_CSP_HANDLE);
- }
- if(clHand == CSSM_INVALID_HANDLE) {
- CssmError::throwMe(CSSMERR_TP_INVALID_CL_HANDLE);
- }
- if(cssmCrlGroup->CrlGroupType != CSSM_CRLGROUP_DATA) {
- CssmError::throwMe(CSSMERR_TP_INVALID_CERTGROUP);
- }
- switch(cssmCrlGroup->CrlType) {
- case CSSM_CRL_TYPE_X_509v1:
- case CSSM_CRL_TYPE_X_509v2:
- break;
- default:
- CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT);
- }
- switch(cssmCrlGroup->CrlEncoding) {
- case CSSM_CRL_ENCODING_BER:
- case CSSM_CRL_ENCODING_DER:
- break;
- default:
- CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT);
- }
-
- /*
- * Add remaining input certs to mCrlInfo.
- */
- TPCrlInfo *crlInfo = NULL;
- for(unsigned crlDex=0; crlDex<cssmCrlGroup->NumberOfCrls; crlDex++) {
- try {
- crlInfo = new TPCrlInfo(clHand,
- cspHand,
- &cssmCrlGroup->GroupCrlList.CrlList[crlDex],
- TIC_NoCopy, // don't copy data
- verifyTime);
- }
- catch (...) {
- /* just ignore this CRL */
- continue;
- }
- crlInfo->index(crlDex);
- appendCrl(*crlInfo);
- }
-}
-
-/*
- * Deletes all TPCrlInfo's if appropriate.
- */
-TPCrlGroup::~TPCrlGroup()
-{
- if(mWhoOwns == TGO_Group) {
- unsigned i;
- for(i=0; i<mNumCrls; i++) {
- delete mCrlInfo[i];
- }
- }
- mAlloc.free(mCrlInfo);
-}
-
-/* add/remove/access TPTCrlInfo's. */
-/*
- * NOTE: I am aware that most folks would just use an array<> here, but
- * gdb is so lame that it doesn't even let one examine the contents
- * of an array<> (or just about anything else in the STL). I prefer
- * debuggability over saving a few lines of trivial code.
- */
-void TPCrlGroup::appendCrl(
- TPCrlInfo &crlInfo)
-{
- if(mNumCrls == mSizeofCrlInfo) {
- if(mSizeofCrlInfo == 0) {
- /* appending to empty array */
- mSizeofCrlInfo = 1;
- }
- else {
- mSizeofCrlInfo *= 2;
- }
- mCrlInfo = (TPCrlInfo **)mAlloc.realloc(mCrlInfo,
- mSizeofCrlInfo * sizeof(TPCrlInfo *));
- }
- mCrlInfo[mNumCrls++] = &crlInfo;
-}
-
-TPCrlInfo *TPCrlGroup::crlAtIndex(
- unsigned index)
-{
- if(index > (mNumCrls - 1)) {
- CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR);
- }
- return mCrlInfo[index];
-}
-
-TPCrlInfo &TPCrlGroup::removeCrlAtIndex(
- unsigned index) // doesn't delete the cert, just
- // removes it from our list
-{
- if(index > (mNumCrls - 1)) {
- CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR);
- }
- TPCrlInfo &rtn = *mCrlInfo[index];
-
- /* removed requested element and compact remaining array */
- unsigned i;
- for(i=index; i<(mNumCrls - 1); i++) {
- mCrlInfo[i] = mCrlInfo[i+1];
- }
- mNumCrls--;
- return rtn;
-}
-
-void TPCrlGroup::removeCrl(
- TPCrlInfo &crlInfo)
-{
- for(unsigned dex=0; dex<mNumCrls; dex++) {
- if(mCrlInfo[dex] == &crlInfo) {
- removeCrlAtIndex(dex);
- return;
- }
- }
- tpErrorLog("TPCrlGroup::removeCrl: CRL NOT FOUND\n");
- assert(0);
-}
-
-TPCrlInfo *TPCrlGroup::firstCrl()
-{
- if(mNumCrls == 0) {
- /* the caller really should not do this... */
- CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR);
- }
- else {
- return mCrlInfo[0];
- }
-}
-
-TPCrlInfo *TPCrlGroup::lastCrl()
-{
- if(mNumCrls == 0) {
- /* the caller really should not do this... */
- CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR);
- }
- else {
- return mCrlInfo[mNumCrls - 1];
- }
-}
-
- /*
- * Find a CRL whose issuer matches specified subject cert.
- * Returned CRL has not necessarily been verified.
- */
-TPCrlInfo *TPCrlGroup::findCrlForCert(
- TPCertInfo &subject)
-{
- for(unsigned dex=0; dex<mNumCrls; dex++) {
- TPCrlInfo *crl = mCrlInfo[dex];
- if(crl->hasSameIssuer(subject)) {
- return crl;
- }
- }
- return NULL;
-}