2 * Copyright (c) 2002,2011-2012,2014-2015 Apple Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 * TPCrlInfo.h - TP's private CRL and CRL group
24 #include "TPCrlInfo.h"
25 #include "tpdebugging.h"
26 #include "certGroupUtils.h"
27 #include "tpCrlVerify.h"
28 #include "tpPolicies.h"
30 #include <Security/cssmapi.h>
31 #include <Security/x509defs.h>
32 #include <Security/oidscert.h>
33 #include <Security/oidscrl.h>
34 #include <security_cdsa_utilities/cssmerrors.h>
35 #include <string.h> /* for memcmp */
36 #include <Security/cssmapple.h>
39 * Replacement for CSSM_CL_CrlGetFirstCachedFieldValue for use with
40 * TPCrlItemInfo's generic getFirstCachedField mechanism.
42 static CSSM_RETURN
tpGetFirstCachedFieldValue (CSSM_CL_HANDLE CLHandle
,
43 CSSM_HANDLE CrlHandle
,
44 const CSSM_OID
*CrlField
,
45 CSSM_HANDLE_PTR ResultsHandle
,
46 uint32
*NumberOfMatchedFields
,
49 return CSSM_CL_CrlGetFirstCachedFieldValue(CLHandle
,
51 NULL
, // const CSSM_DATA *CrlRecordIndex,
54 NumberOfMatchedFields
,
58 static const TPClItemCalls tpCrlClCalls
=
60 tpGetFirstCachedFieldValue
,
61 CSSM_CL_CrlAbortQuery
,
63 CSSM_CL_CrlAbortCache
,
65 &CSSMOID_X509V1CRLThisUpdate
,
66 &CSSMOID_X509V1CRLNextUpdate
,
67 CSSMERR_TP_INVALID_CRL_POINTER
,
68 CSSMERR_APPLETP_CRL_EXPIRED
,
69 CSSMERR_APPLETP_CRL_NOT_VALID_YET
74 * No default constructor - this is the only way.
75 * This caches the cert and fetches subjectName and issuerName
76 * to ensure the incoming certData is well-constructed.
79 CSSM_CL_HANDLE clHand
,
80 CSSM_CSP_HANDLE cspHand
,
81 const CSSM_DATA
*crlData
,
82 TPItemCopy copyCrlData
, // true: we copy, we free
83 // false - caller owns
84 const char *verifyTime
) // = NULL
86 : TPClItemInfo(clHand
, cspHand
, tpCrlClCalls
, crlData
,
87 copyCrlData
, verifyTime
),
89 mFromWhere(CFW_Nowhere
),
91 mCrlFieldToFree(NULL
),
92 mVerifyState(CVS_Unknown
),
93 mVerifyError(CSSMERR_TP_INTERNAL_ERROR
)
100 /* fetch parsed CRL */
101 crtn
= fetchField(&CSSMOID_X509V2CRLSignedCrlCStruct
, &mCrlFieldToFree
);
105 CssmError::throwMe(crtn
);
107 if(mCrlFieldToFree
->Length
!= sizeof(CSSM_X509_SIGNED_CRL
)) {
108 tpErrorLog("fetchField(SignedCrlCStruct) length error\n");
110 CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR
);
112 mX509Crl
= (CSSM_X509_SIGNED_CRL
*)mCrlFieldToFree
->Data
;
113 /* any other other commonly used fields? */
116 TPCrlInfo::~TPCrlInfo()
121 void TPCrlInfo::releaseResources()
123 if(mCrlFieldToFree
) {
124 freeField(&CSSMOID_X509V2CRLSignedCrlCStruct
, mCrlFieldToFree
);
125 mCrlFieldToFree
= NULL
;
128 Allocator::standard().free(mUri
.Data
);
132 TPClItemInfo::releaseResources();
135 void TPCrlInfo::uri(const CSSM_DATA
&uri
)
137 tpCopyCssmData(Allocator::standard(), &uri
, &mUri
);
141 * List of extensions we understand and can accept as critical.
143 static const CSSM_OID
*const TPGoodCrlExtens
[] =
146 /* Note NOT CSSMOID_DeltaCrlIndicator! That's fatal */
149 &CSSMOID_IssuingDistributionPoint
,
150 &CSSMOID_HoldInstructionCode
,
151 &CSSMOID_InvalidityDate
,
152 &CSSMOID_AuthorityKeyIdentifier
,
153 &CSSMOID_SubjectAltName
,
154 &CSSMOID_IssuerAltName
157 #define NUM_KNOWN_EXTENS (sizeof(TPGoodCrlExtens) / sizeof(CSSM_OID_PTR))
160 * Do our best to understand all the entries in a CSSM_X509_EXTENSIONS,
161 * which may be per-CRL or per-entry.
163 * For now, we just ensure that for every critical extension,
164 * we actually understand it and can deal it.
166 CSSM_RETURN
TPCrlInfo::parseExtensions(
167 TPVerifyContext
&vfyCtx
,
169 uint32 entryIndex
, // if isPerEntry
170 const CSSM_X509_EXTENSIONS
&extens
,
171 TPCertInfo
*forCert
, // optional
172 bool &isIndirectCrl
) // RETURNED
174 isIndirectCrl
= false;
175 for(uint32 dex
=0; dex
<extens
.numberOfExtensions
; dex
++) {
176 CSSM_X509_EXTENSION_PTR exten
= &extens
.extensions
[dex
];
177 if(exten
->critical
) {
178 /* critical: is it in our list of understood extensions? */
180 for(i
=0; i
<NUM_KNOWN_EXTENS
; i
++) {
181 if(tpCompareOids(&exten
->extnId
, TPGoodCrlExtens
[i
])) {
182 /* we're cool with this one */
186 if(i
== NUM_KNOWN_EXTENS
) {
187 tpCrlDebug("parseExtensions: Unknown Critical Extension\n");
188 return CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN
;
192 /* Specific extension handling. */
193 if(tpCompareOids(&exten
->extnId
,
194 &CSSMOID_IssuingDistributionPoint
)) {
196 * If this assertion fails, we're out of sync with the CL
198 assert(exten
->format
== CSSM_X509_DATAFORMAT_PARSED
);
199 CE_IssuingDistributionPoint
*idp
=
200 (CE_IssuingDistributionPoint
*)
201 exten
->value
.parsedValue
;
204 * Snag indirectCrl flag for caller in any case
206 if(idp
->indirectCrlPresent
&& idp
->indirectCrl
) {
207 isIndirectCrl
= true;
209 if(forCert
!= NULL
) {
210 /* If no target cert, i.e., we're just verifying a CRL,
211 * skip the remaining IDP checks. */
213 /* verify onlyCACerts/onlyUserCerts */
215 if(forCert
->isLeaf() &&
216 !(vfyCtx
.actionFlags
& CSSM_TP_ACTION_LEAF_IS_CA
)) {
222 if((idp
->onlyUserCertsPresent
) && (idp
->onlyUserCerts
)) {
224 tpCrlDebug("parseExtensions: onlyUserCerts, "
226 return CSSMERR_APPLETP_IDP_FAIL
;
229 if((idp
->onlyCACertsPresent
) && (idp
->onlyCACerts
)) {
231 tpCrlDebug("parseExtensions: onlyCACerts, leaf\n");
232 return CSSMERR_APPLETP_IDP_FAIL
;
236 /* Verify DistributionPointName matches cRLDistributionPoints
239 if(idp
->distPointName
) {
240 CSSM_DATA_PTR certDistPoints
;
241 CSSM_RETURN crtn
= forCert
->fetchField(&CSSMOID_CrlDistributionPoints
, &certDistPoints
);
245 case CSSMERR_CL_NO_FIELD_VALUES
:
250 if (certDistPoints
->Length
!= sizeof(CSSM_X509_EXTENSION
)) {
251 forCert
->freeField(&CSSMOID_CrlDistributionPoints
, certDistPoints
);
252 return CSSMERR_TP_UNKNOWN_FORMAT
;
254 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)certDistPoints
->Data
;
255 if (cssmExt
== NULL
) {
256 forCert
->freeField(&CSSMOID_CrlDistributionPoints
, certDistPoints
);
257 return CSSMERR_TP_UNKNOWN_FORMAT
;
259 CE_CRLDistPointsSyntax
*dps
= (CE_CRLDistPointsSyntax
*)cssmExt
->value
.parsedValue
;
261 forCert
->freeField(&CSSMOID_CrlDistributionPoints
, certDistPoints
);
262 return CSSMERR_TP_UNKNOWN_FORMAT
;
264 if (!dps
->numDistPoints
) {
265 /* no distribution points in the cert extension */
266 forCert
->freeField(&CSSMOID_CrlDistributionPoints
, certDistPoints
);
270 /* Loop over the cRLDistributionPoints in the cert. */
271 CSSM_BOOL sameType
= CSSM_FALSE
;
272 CSSM_BOOL found
= CSSM_FALSE
;
273 for (unsigned dex
=0; dex
<dps
->numDistPoints
; dex
++) {
274 CE_CRLDistributionPoint
*dp
= &dps
->distPoints
[dex
];
275 if (dp
->distPointName
== NULL
) {
278 if (idp
->distPointName
->nameType
!= dp
->distPointName
->nameType
) {
279 /* Not the same name type; move on. */
282 sameType
= CSSM_TRUE
;
283 switch (dp
->distPointName
->nameType
) {
284 case CE_CDNT_NameRelativeToCrlIssuer
: {
286 /* RDN code below is not tested, so we won't use it.
287 * Defaulting to prior behavior of accepting without testing.
290 tpErrorLog("parseExtensions: "
291 "CE_CDNT_NameRelativeToCrlIssuer not implemented\n");
295 /* relativeName is a RDN sequence */
296 CSSM_X509_RDN_PTR idpName
= idp
->distPointName
->dpn
.rdn
;
297 CSSM_X509_RDN_PTR certName
= dp
->distPointName
->dpn
.rdn
;
298 if (idpName
== NULL
|| certName
== NULL
|| idpName
->numberOfPairs
!= certName
->numberOfPairs
) {
299 /* They don't have the same number of attribute/value pairs; move on. */
303 for (nDex
=0; nDex
<idpName
->numberOfPairs
; nDex
++) {
304 CSSM_X509_TYPE_VALUE_PAIR_PTR iPair
= idpName
->AttributeTypeAndValue
;
305 CSSM_X509_TYPE_VALUE_PAIR_PTR cPair
= certName
->AttributeTypeAndValue
;
306 if (!tpCompareCssmData(&iPair
->type
, &cPair
->type
) ||
307 !tpCompareCssmData(&iPair
->value
, &cPair
->value
)) {
311 if (nDex
==idpName
->numberOfPairs
) {
312 /* All the pairs matched. */
317 case CE_CDNT_FullName
: {
318 /* fullName is a GeneralNames sequence */
319 CE_GeneralNames
*idpNames
= idp
->distPointName
->dpn
.fullName
;
320 CE_GeneralNames
*certNames
= dp
->distPointName
->dpn
.fullName
;
321 if (idpNames
== NULL
|| certNames
== NULL
|| idpNames
->numNames
!= certNames
->numNames
) {
322 /* They don't have the same number of names; move on. */
326 for (nDex
=0; nDex
<idpNames
->numNames
; nDex
++) {
327 CE_GeneralName
*idpName
= &idpNames
->generalName
[nDex
];
328 CE_GeneralName
*certName
= &certNames
->generalName
[nDex
];
329 if ((idpName
->nameType
!= certName
->nameType
) ||
330 (!tpCompareCssmData(&idpName
->name
, &certName
->name
))) {
334 if (nDex
==idpNames
->numNames
) {
335 /* All the names matched. */
341 forCert
->freeField(&CSSMOID_CrlDistributionPoints
, certDistPoints
);
342 return CSSMERR_TP_UNKNOWN_FORMAT
;
346 break; /* out of loop over crlDistribtionPoints in cert. */
349 forCert
->freeField(&CSSMOID_CrlDistributionPoints
, certDistPoints
);
350 if(sameType
&& !found
) {
351 return CSSMERR_APPLETP_IDP_FAIL
;
353 } /* distPointName check */
355 } /* have target cert */
362 * The heavyweight "perform full verification of this CRL" op.
363 * Must verify to an anchor cert in tpVerifyContext or via
364 * Trust Settings if so enabled.
365 * Intermediate certs can come from signerCerts or dBList.
367 CSSM_RETURN
TPCrlInfo::verifyWithContext(
368 TPVerifyContext
&tpVerifyContext
,
369 TPCertInfo
*forCert
, // optional
373 * Step 1: this CRL must be current. Caller might have re-evaluated
374 * expired/notValidYet since our construction via calculateCurrent().
377 return CSSMERR_APPLETP_CRL_EXPIRED
;
379 if(isNotValidYet()) {
380 return CSSMERR_APPLETP_CRL_NOT_VALID_YET
;
383 /* subsequent verify state is cached */
384 switch(mVerifyState
) {
392 tpErrorLog("verifyWithContext: bad verifyState\n");
393 return CSSMERR_TP_INTERNAL_ERROR
;
397 * Step 2: parse & understand all critical CRL extensions.
401 crtn
= parseExtensions(tpVerifyContext
,
404 mX509Crl
->tbsCertList
.extensions
,
408 mVerifyState
= CVS_Bad
;
409 if(!forCert
|| forCert
->addStatusCode(crtn
)) {
414 CSSM_X509_REVOKED_CERT_LIST_PTR revoked
=
415 mX509Crl
->tbsCertList
.revokedCertificates
;
416 if(revoked
!= NULL
) {
417 for(uint32 dex
=0; dex
<revoked
->numberOfRevokedCertEntries
; dex
++) {
418 bool dummyIsIndirect
; // can't be set here
419 crtn
= parseExtensions(tpVerifyContext
,
422 revoked
->revokedCertEntry
[dex
].extensions
,
426 if(!forCert
|| forCert
->addStatusCode(crtn
)) {
427 mVerifyState
= CVS_Bad
;
435 * Step 3: obtain a fully verified cert chain which verifies this CRL.
437 CSSM_BOOL verifiedToRoot
;
438 CSSM_BOOL verifiedToAnchor
;
439 CSSM_BOOL verifiedViaTrustSetting
;
441 TPCertGroup
outCertGroup(tpVerifyContext
.alloc
,
442 TGO_Caller
); // CRLs owned by inCertGroup
444 /* set up for disposal of TPCertInfos created by
445 * CertGroupConstructPriv */
446 TPCertGroup
certsToBeFreed(tpVerifyContext
.alloc
, TGO_Group
);
448 if(tpVerifyContext
.signerCerts
) {
449 /* start from scratch with this group */
450 tpVerifyContext
.signerCerts
->setAllUnused();
452 crtn
= outCertGroup
.buildCertGroup(
453 *this, // subject item
454 tpVerifyContext
.signerCerts
, // inCertGroup, optional
455 tpVerifyContext
.dbList
, // optional
456 tpVerifyContext
.clHand
,
457 tpVerifyContext
.cspHand
,
458 tpVerifyContext
.verifyTime
,
459 tpVerifyContext
.numAnchorCerts
,
460 tpVerifyContext
.anchorCerts
,
462 &tpVerifyContext
.gatheredCerts
,
463 CSSM_FALSE
, // subjectIsInGroup
464 tpVerifyContext
.actionFlags
,
465 tpVerifyContext
.policyOid
,
466 tpVerifyContext
.policyStr
,
467 tpVerifyContext
.policyStrLen
,
468 kSecTrustSettingsKeyUseSignRevocation
,
471 verifiedViaTrustSetting
);
472 /* subsequent errors to errOut: */
475 tpCrlDebug("TPCrlInfo::verifyWithContext buildCertGroup failure "
476 "index %u", index());
477 if(!forCert
|| forCert
->addStatusCode(crtn
)) {
481 if (verifiedToRoot
&& (tpVerifyContext
.actionFlags
& CSSM_TP_ACTION_IMPLICIT_ANCHORS
))
482 verifiedToAnchor
= CSSM_TRUE
;
483 if(!verifiedToAnchor
&& !verifiedViaTrustSetting
) {
486 /* verified to root which is not an anchor */
487 tpCrlDebug("TPCrlInfo::verifyWithContext root, no anchor, "
488 "index %u", index());
489 crtn
= CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT
;
492 /* partial chain, no root, not verifiable by anchor */
493 tpCrlDebug("TPCrlInfo::verifyWithContext no root, no anchor, "
494 "index %u", index());
495 crtn
= CSSMERR_APPLETP_CRL_NOT_TRUSTED
;
497 if(!forCert
|| forCert
->addStatusCode(crtn
)) {
498 mVerifyState
= CVS_Bad
;
504 * Step 4: policy verification on the returned cert group
505 * We need to (temporarily) assert the "leaf cert is a CA" flag
508 outCertGroup
.certAtIndex(0)->isLeaf(true);
509 crtn
= tp_policyVerify(kCrlPolicy
,
510 tpVerifyContext
.alloc
,
511 tpVerifyContext
.clHand
,
512 tpVerifyContext
.cspHand
,
515 verifiedViaTrustSetting
,
516 tpVerifyContext
.actionFlags
| CSSM_TP_ACTION_LEAF_IS_CA
,
518 NULL
); // policyOpts, not currently used
520 tpCrlDebug(" ...verifyWithContext policy FAILURE CRL %u",
522 if(!forCert
|| forCert
->addStatusCode(CSSMERR_APPLETP_CRL_POLICY_FAIL
)) {
523 mVerifyState
= CVS_Bad
;
529 * Step 5: recursively perform CRL verification on the certs
530 * gathered to verify this CRL.
531 * Only performed if this CRL is an indirect CRL or the caller
532 * explicitly told us to do this (i.e., caller is verifying a
533 * CRL, not a cert chain).
535 if(isIndirectCrl
|| doCrlVerify
) {
536 tpCrlDebug("verifyWithContext recursing to "
537 "tpVerifyCertGroupWithCrls");
538 crtn
= tpVerifyCertGroupWithCrls(tpVerifyContext
,
541 tpCrlDebug(" ...verifyWithContext CRL reverify FAILURE CRL %u",
543 if(!forCert
|| forCert
->addStatusCode(crtn
)) {
544 mVerifyState
= CVS_Bad
;
550 tpCrlDebug(" ...verifyWithContext CRL %u SUCCESS", index());
551 mVerifyState
= CVS_Good
;
553 /* we own these, we free the DB records */
554 certsToBeFreed
.freeDbRecords();
559 * Wrapper for verifyWithContext for use when evaluating a CRL
560 * "now" instead of at the time in TPVerifyContext.verifyTime.
561 * In this case, on entry, TPVerifyContext.verifyTime is the
562 * time at which a cert is being evaluated.
564 CSSM_RETURN
TPCrlInfo::verifyWithContextNow(
565 TPVerifyContext
&tpVerifyContext
,
566 TPCertInfo
*forCert
, // optional
569 CSSM_TIMESTRING ctxTime
= tpVerifyContext
.verifyTime
;
570 CSSM_RETURN crtn
= verifyWithContext(tpVerifyContext
, forCert
, doCrlVerify
);
571 tpVerifyContext
.verifyTime
= ctxTime
;
576 * Do I have the same issuer as the specified subject cert? Returns
579 bool TPCrlInfo::hasSameIssuer(
580 const TPCertInfo
&subject
)
582 assert(subject
.issuerName() != NULL
);
583 if(tpCompareCssmData(issuerName(), subject
.issuerName())) {
592 * Determine if specified cert has been revoked as of the
593 * provided time; a NULL timestring indicates "now".
595 * Assumes current CRL is verified good and that issuer names of
596 * the cert and CRL match.
598 * This duplicates similar logic in the CL, but to avoid re-parsing
599 * the subject cert (which we have parsed and cached), we just do it
602 * Possible errors are
603 * CSSMERR_TP_CERT_REVOKED
604 * CSSMERR_TP_CERT_SUSPENDED
607 * Error status is added to subjectCert.
609 CSSM_RETURN
TPCrlInfo::isCertRevoked(
610 TPCertInfo
&subjectCert
,
611 CSSM_TIMESTRING verifyTime
)
613 assert(mVerifyState
== CVS_Good
);
614 CSSM_X509_TBS_CERTLIST_PTR tbs
= &mX509Crl
->tbsCertList
;
616 /* trivial case - empty CRL */
617 if((tbs
->revokedCertificates
== NULL
) ||
618 (tbs
->revokedCertificates
->numberOfRevokedCertEntries
== 0)) {
619 tpCrlDebug(" isCertRevoked: empty CRL at index %u", index());
623 /* is subject cert's serial number in this CRL? */
624 CSSM_DATA_PTR subjSerial
= NULL
;
626 crtn
= subjectCert
.fetchField(&CSSMOID_X509V1SerialNumber
, &subjSerial
);
628 /* should never happen */
629 tpErrorLog("TPCrlInfo:isCertRevoked: error fetching serial number\n");
630 if(subjectCert
.addStatusCode(crtn
)) {
634 /* allowed error - can't proceed; punt with success */
638 /* subsequent errors to errOut: */
640 uint32 numEntries
= tbs
->revokedCertificates
->numberOfRevokedCertEntries
;
641 CSSM_X509_REVOKED_CERT_ENTRY_PTR entries
=
642 tbs
->revokedCertificates
->revokedCertEntry
;
644 CFDateRef cfRevokedTime
= NULL
;
645 CFDateRef cfVerifyTime
= NULL
;
647 for(uint32 dex
=0; dex
<numEntries
; dex
++) {
648 CSSM_X509_REVOKED_CERT_ENTRY_PTR entry
= &entries
[dex
];
649 if(tpCompareCssmData(subjSerial
, &entry
->certificateSerialNumber
)) {
651 * It's in there. Compare revocation time in the CRL to
652 * our caller-specified verifyTime.
654 CSSM_X509_TIME_PTR xTime
= &entry
->revocationDate
;
656 rtn
= timeStringToCfDate((char *)xTime
->time
.Data
, (unsigned)xTime
->time
.Length
,
659 tpErrorLog("fetchNotBeforeAfter: malformed revocationDate\n");
662 if(verifyTime
!= NULL
) {
663 rtn
= timeStringToCfDate((char *)verifyTime
, (unsigned)strlen(verifyTime
),
667 /* verify right now */
668 cfVerifyTime
= CFDateCreate(NULL
, CFAbsoluteTimeGetCurrent());
670 if((rtn
== 0) && cfVerifyTime
!= NULL
) {
671 CFComparisonResult res
= CFDateCompare(cfVerifyTime
, cfRevokedTime
, NULL
);
672 if(res
== kCFCompareLessThan
) {
673 /* cfVerifyTime < cfRevokedTime; I guess this one's OK */
674 tpCrlDebug(" isCertRevoked: cert %u NOT YET REVOKED by CRL %u",
675 subjectCert
.index(), index());
682 * REQUIRED TBD: parse the entry's extensions, specifically to
683 * get a reason. This will entail a bunch of new TP/cert specific
685 * For now, just flag it revoked.
687 crtn
= CSSMERR_TP_CERT_REVOKED
;
688 subjectCert
.crlReason(1);
689 tpCrlDebug(" isCertRevoked: cert %u REVOKED by CRL %u",
690 subjectCert
.index(), index());
695 subjectCert
.freeField(&CSSMOID_X509V1SerialNumber
, subjSerial
);
696 if(crtn
&& !subjectCert
.addStatusCode(crtn
)) {
700 CFRelease(cfRevokedTime
);
703 CFRelease(cfVerifyTime
);
712 /* build empty group */
713 TPCrlGroup::TPCrlGroup(
715 TPGroupOwner whoOwns
) :
722 /* nothing for now */
726 * Construct from unordered, untrusted CSSM_CRLGROUP. Resulting
727 * TPCrlInfos are more or less in the same order as the incoming
728 * CRLs, though incoming CRLs are discarded if they don't parse.
729 * No verification of any sort is performed.
731 TPCrlGroup::TPCrlGroup(
732 const CSSM_CRLGROUP
*cssmCrlGroup
, // optional
733 CSSM_CL_HANDLE clHand
,
734 CSSM_CSP_HANDLE cspHand
,
736 const char *verifyTime
, // may be NULL
737 TPGroupOwner whoOwns
) :
744 /* verify input args */
745 if((cssmCrlGroup
== NULL
) || (cssmCrlGroup
->NumberOfCrls
== 0)) {
748 if(cspHand
== CSSM_INVALID_HANDLE
) {
749 CssmError::throwMe(CSSMERR_TP_INVALID_CSP_HANDLE
);
751 if(clHand
== CSSM_INVALID_HANDLE
) {
752 CssmError::throwMe(CSSMERR_TP_INVALID_CL_HANDLE
);
754 if(cssmCrlGroup
->CrlGroupType
!= CSSM_CRLGROUP_DATA
) {
755 CssmError::throwMe(CSSMERR_TP_INVALID_CERTGROUP
);
757 switch(cssmCrlGroup
->CrlType
) {
758 case CSSM_CRL_TYPE_X_509v1
:
759 case CSSM_CRL_TYPE_X_509v2
:
762 CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT
);
764 switch(cssmCrlGroup
->CrlEncoding
) {
765 case CSSM_CRL_ENCODING_BER
:
766 case CSSM_CRL_ENCODING_DER
:
769 CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT
);
773 * Add remaining input certs to mCrlInfo.
775 TPCrlInfo
*crlInfo
= NULL
;
776 for(unsigned crlDex
=0; crlDex
<cssmCrlGroup
->NumberOfCrls
; crlDex
++) {
778 crlInfo
= new TPCrlInfo(clHand
,
780 &cssmCrlGroup
->GroupCrlList
.CrlList
[crlDex
],
781 TIC_NoCopy
, // don't copy data
785 /* just ignore this CRL */
788 crlInfo
->index(crlDex
);
794 * Deletes all TPCrlInfo's if appropriate.
796 TPCrlGroup::~TPCrlGroup()
798 if(mWhoOwns
== TGO_Group
) {
800 for(i
=0; i
<mNumCrls
; i
++) {
804 mAlloc
.free(mCrlInfo
);
807 /* add/remove/access TPTCrlInfo's. */
809 * NOTE: I am aware that most folks would just use an array<> here, but
810 * gdb is so lame that it doesn't even let one examine the contents
811 * of an array<> (or just about anything else in the STL). I prefer
812 * debuggability over saving a few lines of trivial code.
814 void TPCrlGroup::appendCrl(
817 if(mNumCrls
== mSizeofCrlInfo
) {
818 if(mSizeofCrlInfo
== 0) {
819 /* appending to empty array */
825 mCrlInfo
= (TPCrlInfo
**)mAlloc
.realloc(mCrlInfo
,
826 mSizeofCrlInfo
* sizeof(TPCrlInfo
*));
828 mCrlInfo
[mNumCrls
++] = &crlInfo
;
831 TPCrlInfo
*TPCrlGroup::crlAtIndex(
834 if(index
> (mNumCrls
- 1)) {
835 CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR
);
837 return mCrlInfo
[index
];
840 TPCrlInfo
&TPCrlGroup::removeCrlAtIndex(
841 unsigned index
) // doesn't delete the cert, just
842 // removes it from our list
844 if(index
> (mNumCrls
- 1)) {
845 CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR
);
847 TPCrlInfo
&rtn
= *mCrlInfo
[index
];
849 /* removed requested element and compact remaining array */
851 for(i
=index
; i
<(mNumCrls
- 1); i
++) {
852 mCrlInfo
[i
] = mCrlInfo
[i
+1];
858 void TPCrlGroup::removeCrl(
861 for(unsigned dex
=0; dex
<mNumCrls
; dex
++) {
862 if(mCrlInfo
[dex
] == &crlInfo
) {
863 removeCrlAtIndex(dex
);
867 tpErrorLog("TPCrlGroup::removeCrl: CRL NOT FOUND\n");
871 TPCrlInfo
*TPCrlGroup::firstCrl()
874 /* the caller really should not do this... */
875 CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR
);
882 TPCrlInfo
*TPCrlGroup::lastCrl()
885 /* the caller really should not do this... */
886 CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR
);
889 return mCrlInfo
[mNumCrls
- 1];
894 * Find a CRL whose issuer matches specified subject cert.
895 * Returned CRL has not necessarily been verified.
897 TPCrlInfo
*TPCrlGroup::findCrlForCert(
900 for(unsigned dex
=0; dex
<mNumCrls
; dex
++) {
901 TPCrlInfo
*crl
= mCrlInfo
[dex
];
902 if(crl
->hasSameIssuer(subject
)) {