2 * Copyright (c) 2000-2001 Apple Computer, 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 policies.cpp - TP module policy implementation
22 Created 10/9/2000 by Doug Mitchell.
25 #include <Security/cssmtype.h>
26 #include <Security/cssmapi.h>
27 #include "tpPolicies.h"
28 #include <Security/oidsattr.h>
29 #include <Security/cssmerr.h>
30 #include "tpdebugging.h"
31 #include "rootCerts.h"
32 #include "certGroupUtils.h"
33 #include <Security/x509defs.h>
34 #include <Security/oidscert.h>
35 #include <Security/certextensions.h>
36 #include <Security/cssmapple.h>
40 * Our private per-extension info. One of these per (understood) extension per
46 CE_Data
*extnData
; // mallocd by CL
47 CSSM_DATA
*valToFree
; // the data we pass to freeField()
51 * Struct to keep track of info pertinent to one cert.
55 /* extensions pertinent to iSign */
56 iSignExtenInfo authorityId
;
57 iSignExtenInfo subjectId
;
58 iSignExtenInfo keyUsage
;
59 iSignExtenInfo extendKeyUsage
;
60 iSignExtenInfo basicConstraints
;
61 iSignExtenInfo netscapeCertType
;
63 /* flag indicating presence of a critical extension we don't understand */
64 CSSM_BOOL foundUnknownCritical
;
70 * Setup a single iSignExtenInfo. Called once per known extension
73 static CSSM_RETURN
tpSetupExtension(
76 iSignExtenInfo
*extnInfo
) // which component of certInfo
78 if(extnData
->Length
!= sizeof(CSSM_X509_EXTENSION
)) {
79 errorLog0("tpSetupExtension: malformed CSSM_FIELD\n");
80 return CSSMERR_TP_UNKNOWN_FORMAT
;
82 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)extnData
->Data
;
83 extnInfo
->present
= CSSM_TRUE
;
84 extnInfo
->critical
= cssmExt
->critical
;
85 extnInfo
->extnData
= (CE_Data
*)cssmExt
->value
.parsedValue
;
86 extnInfo
->valToFree
= extnData
;
91 * Fetch a known extension, set up associated iSignExtenInfo if present.
93 static CSSM_RETURN
iSignFetchExtension(
96 const CSSM_OID
*fieldOid
, // which extension to fetch
97 iSignExtenInfo
*extnInfo
) // where the info goes
99 CSSM_DATA_PTR fieldValue
; // mallocd by CL
102 crtn
= tpCert
->fetchField(fieldOid
, &fieldValue
);
106 case CSSMERR_CL_NO_FIELD_VALUES
:
107 /* field not present, OK */
112 return tpSetupExtension(alloc
,
118 * Search for al unknown extensions. If we find one which is flagged critical,
119 * flag certInfo->foundUnknownCritical. Only returns error on gross errors.
121 static CSSM_RETURN
iSignSearchUnknownExtensions(
123 iSignCertInfo
*certInfo
)
126 CSSM_DATA_PTR fieldValue
= NULL
;
127 CSSM_HANDLE searchHand
= CSSM_INVALID_HANDLE
;
128 uint32 numFields
= 0;
130 crtn
= CSSM_CL_CertGetFirstCachedFieldValue(tpCert
->clHand(),
132 &CSSMOID_X509V3CertificateExtensionCStruct
,
138 /* found one, proceed */
140 case CSSMERR_CL_NO_FIELD_VALUES
:
141 /* no unknown extensions present, OK */
147 if(fieldValue
->Length
!= sizeof(CSSM_X509_EXTENSION
)) {
148 errorLog0("iSignSearchUnknownExtensions: malformed CSSM_FIELD\n");
149 return CSSMERR_TP_UNKNOWN_FORMAT
;
151 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)fieldValue
->Data
;
152 if(cssmExt
->critical
) {
153 /* BRRZAPP! Found an unknown extension marked critical */
154 certInfo
->foundUnknownCritical
= CSSM_TRUE
;
157 CSSM_CL_FreeFieldValue(tpCert
->clHand(),
158 &CSSMOID_X509V3CertificateExtensionCStruct
,
162 /* process remaining unknown extensions */
163 for(unsigned i
=1; i
<numFields
; i
++) {
164 crtn
= CSSM_CL_CertGetNextCachedFieldValue(tpCert
->clHand(),
168 /* should never happen */
169 errorLog0("searchUnknownExtensions: GetNextCachedFieldValue error\n");
172 if(fieldValue
->Length
!= sizeof(CSSM_X509_EXTENSION
)) {
173 errorLog0("iSignSearchUnknownExtensions: malformed CSSM_FIELD\n");
174 crtn
= CSSMERR_TP_UNKNOWN_FORMAT
;
177 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)fieldValue
->Data
;
178 if(cssmExt
->critical
) {
179 /* BRRZAPP! Found an unknown extension marked critical */
180 certInfo
->foundUnknownCritical
= CSSM_TRUE
;
183 CSSM_CL_FreeFieldValue(tpCert
->clHand(),
184 &CSSMOID_X509V3CertificateExtensionCStruct
,
187 } /* for additional fields */
191 CSSM_CL_FreeFieldValue(tpCert
->clHand(),
192 &CSSMOID_X509V3CertificateExtensionCStruct
,
195 if(searchHand
!= CSSM_INVALID_HANDLE
) {
196 CSSM_CL_CertAbortQuery(tpCert
->clHand(), searchHand
);
201 * Given a TPCertInfo, fetch the associated iSignCertInfo fields.
202 * Returns CSSM_FAIL on error.
204 static CSSM_RETURN
iSignGetCertInfo(
205 CssmAllocator
&alloc
,
207 iSignCertInfo
*certInfo
)
211 /* first grind thru the extensions we're interested in */
212 crtn
= iSignFetchExtension(alloc
,
214 &CSSMOID_AuthorityKeyIdentifier
,
215 &certInfo
->authorityId
);
219 crtn
= iSignFetchExtension(alloc
,
221 &CSSMOID_SubjectKeyIdentifier
,
222 &certInfo
->subjectId
);
226 crtn
= iSignFetchExtension(alloc
,
229 &certInfo
->keyUsage
);
233 crtn
= iSignFetchExtension(alloc
,
235 &CSSMOID_ExtendedKeyUsage
,
236 &certInfo
->extendKeyUsage
);
240 crtn
= iSignFetchExtension(alloc
,
242 &CSSMOID_BasicConstraints
,
243 &certInfo
->basicConstraints
);
247 crtn
= iSignFetchExtension(alloc
,
249 &CSSMOID_NetscapeCertType
,
250 &certInfo
->netscapeCertType
);
255 /* now look for extensions we don't understand - the only thing we're interested
256 * in is the critical flag. */
257 return iSignSearchUnknownExtensions(tpCert
, certInfo
);
261 * Free (via CL) the fields allocated in iSignGetCertInfo().
263 static void iSignFreeCertInfo(
264 CSSM_CL_HANDLE clHand
,
265 iSignCertInfo
*certInfo
)
267 if(certInfo
->authorityId
.present
) {
268 CSSM_CL_FreeFieldValue(clHand
, &CSSMOID_AuthorityKeyIdentifier
,
269 certInfo
->authorityId
.valToFree
);
271 if(certInfo
->subjectId
.present
) {
272 CSSM_CL_FreeFieldValue(clHand
, &CSSMOID_SubjectKeyIdentifier
,
273 certInfo
->subjectId
.valToFree
);
275 if(certInfo
->keyUsage
.present
) {
276 CSSM_CL_FreeFieldValue(clHand
, &CSSMOID_KeyUsage
,
277 certInfo
->keyUsage
.valToFree
);
279 if(certInfo
->extendKeyUsage
.present
) {
280 CSSM_CL_FreeFieldValue(clHand
, &CSSMOID_ExtendedKeyUsage
,
281 certInfo
->extendKeyUsage
.valToFree
);
283 if(certInfo
->basicConstraints
.present
) {
284 CSSM_CL_FreeFieldValue(clHand
, &CSSMOID_BasicConstraints
,
285 certInfo
->basicConstraints
.valToFree
);
287 if(certInfo
->netscapeCertType
.present
) {
288 CSSM_CL_FreeFieldValue(clHand
, &CSSMOID_NetscapeCertType
,
289 certInfo
->netscapeCertType
.valToFree
);
294 * Common code for comparing a root to a list of known embedded roots.
296 static CSSM_BOOL
tp_isKnownRootCert(
297 TPCertInfo
*rootCert
, // raw cert to compare
298 const tpRootCert
*knownRoots
,
299 unsigned numKnownRoots
)
301 const CSSM_DATA
*subjectName
= NULL
;
302 CSSM_DATA_PTR publicKey
= NULL
;
304 CSSM_BOOL brtn
= CSSM_FALSE
;
305 CSSM_DATA_PTR valToFree
= NULL
;
307 subjectName
= rootCert
->subjectName();
308 publicKey
= tp_CertGetPublicKey(rootCert
, &valToFree
);
309 if(publicKey
== NULL
) {
310 errorLog0("tp_isKnownRootCert: error retrieving public key info!\n");
315 * Grind thru the list of known certs, demanding perfect match of
318 for(dex
=0; dex
<numKnownRoots
; dex
++) {
319 if(!tpCompareCssmData(subjectName
,
320 knownRoots
[dex
].subjectName
)) {
323 if(!tpCompareCssmData(publicKey
,
324 knownRoots
[dex
].publicKey
)) {
327 #if ENABLE_APPLE_DEBUG_ROOT
328 if( dex
== (knownRoots
- 1) ){
330 //tpSetError(CSSM_TP_DEBUG_CERT);
338 tp_CertFreePublicKey(rootCert
->clHand(), valToFree
);
343 * See if specified root cert is a known (embedded) iSign root cert.
344 * Returns CSSM_TRUE if the cert is a known root cert.
346 static CSSM_BOOL
tp_isIsignRootCert(
347 CSSM_CL_HANDLE clHand
,
348 TPCertInfo
*rootCert
) // raw cert from cert group
350 return tp_isKnownRootCert(rootCert
, iSignRootCerts
, numiSignRootCerts
);
354 * See if specified root cert is a known (embedded) SSL root cert.
355 * Returns CSSM_TRUE if the cert is a known root cert.
357 static CSSM_BOOL
tp_isSslRootCert(
358 CSSM_CL_HANDLE clHand
,
359 TPCertInfo
*rootCert
) // raw cert from cert group
361 return tp_isKnownRootCert(rootCert
, sslRootCerts
, numSslRootCerts
);
365 * Attempt to verify specified cert (from the end of a chain) with one of
366 * our known SSL roots.
368 CSSM_BOOL
tp_verifyWithSslRoots(
369 CSSM_CL_HANDLE clHand
,
370 CSSM_CSP_HANDLE cspHand
,
371 TPCertInfo
*certToVfy
) // last in chain, not root
373 CSSM_KEY rootKey
; // pub key manufactured from tpRootCert info
374 CSSM_CC_HANDLE ccHand
; // signature context
377 const tpRootCert
*rootInfo
;
378 CSSM_BOOL brtn
= CSSM_FALSE
;
379 CSSM_KEYHEADER
*hdr
= &rootKey
.KeyHeader
;
380 CSSM_X509_ALGORITHM_IDENTIFIER_PTR algId
;
381 CSSM_DATA_PTR valToFree
= NULL
;
382 CSSM_ALGORITHMS sigAlg
;
384 memset(&rootKey
, 0, sizeof(CSSM_KEY
));
387 * Get signature algorithm from subject key
389 algId
= tp_CertGetAlgId(certToVfy
, &valToFree
);
394 /* subsequest errors to errOut: */
396 /* map to key and signature algorithm */
397 sigAlg
= tpOidToAldId(&algId
->algorithm
, &hdr
->AlgorithmId
);
398 if(sigAlg
== CSSM_ALGID_NONE
) {
399 errorLog0("tp_verifyWithSslRoots: unknown sig alg\n");
403 /* Set up other constant key fields */
404 hdr
->BlobType
= CSSM_KEYBLOB_RAW
;
405 switch(hdr
->AlgorithmId
) {
407 hdr
->Format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
410 hdr
->Format
= CSSM_KEYBLOB_RAW_FORMAT_FIPS186
;
413 hdr
->Format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
417 hdr
->Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
419 hdr
->KeyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
420 hdr
->KeyAttr
= CSSM_KEYATTR_MODIFIABLE
| CSSM_KEYATTR_EXTRACTABLE
;
421 hdr
->KeyUsage
= CSSM_KEYUSE_VERIFY
;
423 for(dex
=0; dex
<numSslRootCerts
; dex
++) {
424 /* only variation in key in the loop - raw key bits and size */
425 rootInfo
= &sslRootCerts
[dex
];
426 if(!tpIsSameName(rootInfo
->subjectName
, certToVfy
->issuerName())) {
430 rootKey
.KeyData
= *rootInfo
->publicKey
;
431 hdr
->LogicalKeySizeInBits
= rootInfo
->keySize
;
432 crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
438 errorLog0("tp_verifyWithSslRoots: CSSM_CSP_CreateSignatureContext err\n");
439 CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR
);
441 crtn
= CSSM_CL_CertVerify(clHand
,
443 certToVfy
->certData(),
444 NULL
, // no signer cert
447 CSSM_DeleteContext(ccHand
);
448 if(crtn
== CSSM_OK
) {
455 if(valToFree
!= NULL
) {
456 tp_CertFreeAlgId(clHand
, valToFree
);
462 * RFC2459 says basicConstraints must be flagged critical for
463 * CA certs, but Verisign doesn't work that way.
465 #define BASIC_CONSTRAINTS_MUST_BE_CRITICAL 0
468 * TP iSign spec says Extended Key Usage required for leaf certs,
469 * but Verisign doesn't work that way.
471 #define EXTENDED_KEY_USAGE_REQUIRED_FOR_LEAF 0
474 * TP iSign spec says Subject Alternate Name required for leaf certs,
475 * but Verisign doesn't work that way.
477 #define SUBJECT_ALT_NAME_REQUIRED_FOR_LEAF 0
480 * TP iSign spec originally required KeyUsage for all certs, but
481 * Verisign doesn't have that in their roots.
483 #define KEY_USAGE_REQUIRED_FOR_ROOT 0
486 * Public routine to perform TP verification on a constructed
488 * Returns CSSM_TRUE on success.
489 * Asumes the chain has passed basic subject/issuer verification. First cert of
490 * incoming certGroup is end-entity (leaf).
492 * Per-policy details:
493 * iSign: Assumes that last cert in incoming certGroup is a root cert.
494 * Also assumes a cert group of more than one cert.
495 * kTPx509Basic: CertGroup of length one allowed.
497 CSSM_RETURN
tp_policyVerify(
499 CssmAllocator
&alloc
,
500 CSSM_CL_HANDLE clHand
,
501 CSSM_CSP_HANDLE cspHand
,
502 TPCertGroup
*certGroup
,
503 CSSM_BOOL verifiedToRoot
) // last cert is good root
505 iSignCertInfo
*certInfo
= NULL
;
507 iSignCertInfo
*thisCertInfo
;
511 CSSM_BOOL cA
= CSSM_FALSE
;// init for compiler warning
512 CSSM_BOOL isLeaf
; // end entity
513 CSSM_BOOL isRoot
; // root cert
514 CE_ExtendedKeyUsage
*extendUsage
;
515 CE_AuthorityKeyID
*authorityId
;
516 CSSM_RETURN outErr
= CSSM_OK
;
517 TPCertInfo
*lastCert
;
519 /* First, kTPDefault is a nop here */
520 if(policy
== kTPDefault
) {
524 if(certGroup
== NULL
) {
525 return CSSMERR_TP_INVALID_CERTGROUP
;
527 numCerts
= certGroup
->numCerts();
529 return CSSMERR_TP_INVALID_CERTGROUP
;
531 if(policy
== kTPiSign
) {
532 if(!verifiedToRoot
) {
533 /* no way, this requires a root cert */
534 return CSSMERR_TP_INVALID_CERTGROUP
;
537 /* nope, not for iSign */
538 return CSSMERR_TP_INVALID_CERTGROUP
;
542 /* cook up an iSignCertInfo array */
543 certInfo
= (iSignCertInfo
*)tpCalloc(alloc
, numCerts
, sizeof(iSignCertInfo
));
544 /* subsequent errors to errOut: */
546 /* fill it with interesting info from parsed certs */
547 for(certDex
=0; certDex
<numCerts
; certDex
++) {
548 if(iSignGetCertInfo(alloc
,
549 certGroup
->certAtIndex(certDex
),
550 &certInfo
[certDex
])) {
551 outErr
= CSSMERR_TP_INVALID_CERTIFICATE
;
557 * OK, the heart of TP enforcement.
558 * First check for presence of required extensions and
559 * critical extensions we don't understand.
561 for(certDex
=0; certDex
<numCerts
; certDex
++) {
562 thisCertInfo
= &certInfo
[certDex
];
564 if(thisCertInfo
->foundUnknownCritical
) {
565 /* illegal for all policies */
566 errorLog0("tp_policyVerify: critical flag in unknown extension\n");
567 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
572 * Note it's possible for both of these to be true, for a
573 * of length one (kTPx509Basic only!)
575 isLeaf
= (certDex
== 0) ? CSSM_TRUE
: CSSM_FALSE
;
576 isRoot
= (certDex
== (numCerts
- 1)) ? CSSM_TRUE
: CSSM_FALSE
;
579 * BasicConstraints.cA
580 * iSign: required in all but leaf and root,
581 * for which it is optional (with default values of false
582 * for leaf and true for root).
584 * kTP_SSL: always optional, default of false for leaf and
586 * All: cA must be false for leaf, true for others
588 if(!thisCertInfo
->basicConstraints
.present
) {
590 /* cool, use default; note that kTPx509Basic with
591 * certGroup length of one may take this case */
595 /* cool, use default */
603 * not present, not leaf, not root, kTPx509Basic
604 * ....OK; infer as true
609 /* required for iSign in this position */
610 errorLog0("tp_policyVerify: no basicConstraints\n");
611 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
620 /* basicConstraints present */
621 #if BASIC_CONSTRAINTS_MUST_BE_CRITICAL
622 /* disabled for verisign compatibility */
623 if(!thisCertInfo
->basicConstraints
.critical
) {
625 errorLog0("tp_policyVerify: basicConstraints marked not critical\n");
626 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
629 #endif /* BASIC_CONSTRAINTS_MUST_BE_CRITICAL */
630 cA
= thisCertInfo
->basicConstraints
.extnData
->basicConstraints
.cA
;
634 /* special case to allow a chain of length 1, leaf and root
635 * both true (kTPx509Basic, kTP_SSL only) */
637 errorLog0("tp_policyVerify: cA true for leaf\n");
638 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
642 errorLog0("tp_policyVerify: cA false for non-leaf\n");
643 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
648 * Authority Key Identifier optional
649 * iSign : only allowed in !root.
650 * If present, must not be critical.
652 * kTP_SSL : ignored (though used later for chain verification)
654 if((policy
== kTPiSign
) && thisCertInfo
->authorityId
.present
) {
656 errorLog0("tp_policyVerify: authorityId in root\n");
657 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
660 if(thisCertInfo
->authorityId
.critical
) {
661 /* illegal per RFC 2459 */
662 errorLog0("tp_policyVerify: authorityId marked critical\n");
663 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
669 * Subject Key Identifier optional
670 * iSign : can't be critical.
672 * kTP_SSL : ignored (though used later for chain verification)
674 if(thisCertInfo
->subjectId
.present
) {
675 if((policy
== kTPiSign
) && thisCertInfo
->subjectId
.critical
) {
676 errorLog0("tp_policyVerify: subjectId marked critical\n");
677 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
683 * Key Usage optional except as noted required
684 * iSign : required for non-root/non-leaf
685 * Leaf cert : if present, usage = digitalSignature
686 * Exception : if leaf, and keyUsage not present,
687 * netscape-cert-type must be present, with
688 * Object Signing bit set
689 * kTPx509Basic : non-leaf : usage = keyCertSign
692 if(thisCertInfo
->keyUsage
.present
) {
694 * Leaf cert: usage = digitalSignature
695 * Others: usage = keyCertSign
696 * We only require that one bit to be set, we ignore others.
699 if(policy
== kTPiSign
) {
700 expUsage
= CE_KU_DigitalSignature
;
703 /* hack to accept whatever's there */
704 expUsage
= thisCertInfo
->keyUsage
.extnData
->keyUsage
;
708 /* this is true for all policies */
709 expUsage
= CE_KU_KeyCertSign
;
711 actUsage
= thisCertInfo
->keyUsage
.extnData
->keyUsage
;
712 if(!(actUsage
& expUsage
)) {
713 errorLog2("tp_policyVerify: bad keyUsage (leaf %s; usage 0x%x)\n",
714 (certDex
== 0) ? "TRUE" : "FALSE", actUsage
);
715 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
719 else if(policy
== kTPiSign
) {
721 * iSign requires keyUsage present for non root OR
722 * netscape-cert-type/ObjectSigning for leaf
724 if(isLeaf
&& thisCertInfo
->netscapeCertType
.present
) {
725 CE_NetscapeCertType ct
=
726 thisCertInfo
->netscapeCertType
.extnData
->netscapeCertType
;
728 if(!(ct
& CE_NCT_ObjSign
)) {
729 errorLog0("tp_policyVerify: netscape-cert-type, !ObjectSign\n");
730 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
735 errorLog0("tp_policyVerify: !isRoot, no keyUsage, !(leaf and netscapeCertType)\n");
736 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
740 } /* for certDex, checking presence of extensions */
743 * Special case checking for leaf (end entity) cert
745 * iSign only: Extended key usage, optional for leaf,
746 * value CSSMOID_ExtendedUseCodeSigning
748 if((policy
== kTPiSign
) && certInfo
[0].extendKeyUsage
.present
) {
749 extendUsage
= &certInfo
[0].extendKeyUsage
.extnData
->extendedKeyUsage
;
750 if(extendUsage
->numPurposes
!= 1) {
751 errorLog1("tp_policyVerify: bad extendUsage->numPurposes (%d)\n",
752 (int)extendUsage
->numPurposes
);
753 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
756 if(!tpCompareOids(extendUsage
->purposes
,
757 &CSSMOID_ExtendedUseCodeSigning
)) {
758 errorLog0("tp_policyVerify: bad extendKeyUsage\n");
759 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
765 * Verify authorityId-->subjectId linkage.
766 * All optional - skip if needed fields not present.
767 * Also, always skip last (root) cert.
769 for(certDex
=0; certDex
<(numCerts
-1); certDex
++) {
770 if(!certInfo
[certDex
].authorityId
.present
||
771 !certInfo
[certDex
+1].subjectId
.present
) {
774 authorityId
= &certInfo
[certDex
].authorityId
.extnData
->authorityKeyID
;
775 if(!authorityId
->keyIdentifierPresent
) {
776 /* we only know how to compare keyIdentifier */
779 if(!tpCompareCssmData(&authorityId
->keyIdentifier
,
780 &certInfo
[certDex
+1].subjectId
.extnData
->subjectKeyID
)) {
781 errorLog0("tp_policyVerify: bad key ID linkage\n");
782 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
787 /* iSign, SSL: compare root against known root certs */
788 lastCert
= certGroup
->lastCert();
789 if(policy
== kTPiSign
) {
790 bool brtn
= tp_isIsignRootCert(clHand
, lastCert
);
792 outErr
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
795 else if(verifiedToRoot
&& (policy
== kTP_SSL
)) {
796 /* note SSL doesn't require root here */
797 bool brtn
= tp_isSslRootCert(clHand
, lastCert
);
799 outErr
= CSSMERR_TP_INVALID_ANCHOR_CERT
;
807 for(certDex
=0; certDex
<numCerts
; certDex
++) {
808 thisCertInfo
= &certInfo
[certDex
];
809 iSignFreeCertInfo(clHand
, thisCertInfo
);
811 tpFree(alloc
, certInfo
);