2 * Given a cert, produce a complete ordered cert chain back to a root.
3 * Intermediate certs can be in any user keychain.
7 #include <security_cdsa_utils/cuFileIo.h> /* private */
8 #include <security_cdsa_utils/cuPrintCert.h> /* private */
9 #include <Security/Security.h>
10 #include <Security/SecTrustPriv.h> /* private */
12 static void usage(char **argv
)
15 printf(" %s certFileName [d(isable intermediates) [f filebase] [n(o cert dump)]\n", argv
[0]);
19 int main(int argc
, char **argv
)
21 unsigned char *certData
= NULL
; // subject cert, raw data
22 unsigned certDataLen
= 0;
24 SecTrustRef secTrust
= NULL
;
25 CFMutableArrayRef subjCerts
= NULL
;
26 SecPolicyRef policy
= NULL
;
27 SecPolicySearchRef policySearch
= NULL
;
28 SecTrustResultType secTrustResult
;
29 CSSM_RETURN crtn
= CSSM_OK
;
30 CSSM_TP_APPLE_EVIDENCE_INFO
*dummyEv
; // not used
31 CFArrayRef certChain
= NULL
; // constructed chain
33 bool disableLocalIntermediates
= false;
34 char *fileBase
= NULL
;
35 bool enableCertDump
= true;
40 if(readFile(argv
[1], &certData
, &certDataLen
)) {
41 printf("***Error reading cert from %s. Aborting.\n", argv
[1]);
44 for(int arg
=2; arg
<argc
; arg
++) {
45 char *argp
= argv
[arg
];
48 disableLocalIntermediates
= true;
51 enableCertDump
= false;
65 /* SecCertificateRef form of subject cert */
66 SecCertificateRef certRef
= NULL
;
67 CSSM_DATA cdata
= {(uint32
)certDataLen
, (uint8
*)certData
};
68 ortn
= SecCertificateCreateFromData(&cdata
,
70 CSSM_CERT_ENCODING_DER
,
73 cssmPerror("SecCertificateCreateFromData", ortn
);
77 /* make a one-element array */
78 subjCerts
= CFArrayCreateMutable(NULL
, 1, &kCFTypeArrayCallBacks
);
79 CFArraySetValueAtIndex(subjCerts
, 0, certRef
);
81 /* the array owns the subject cert ref now */
84 /* Get a SecPolicyRef for generic X509 cert chain verification */
85 ortn
= SecPolicySearchCreate(CSSM_CERT_X_509v3
,
86 &CSSMOID_APPLE_X509_BASIC
,
90 cssmPerror("SecPolicySearchCreate", ortn
);
93 ortn
= SecPolicySearchCopyNext(policySearch
, &policy
);
95 cssmPerror("SecPolicySearchCopyNext", ortn
);
99 /* build a SecTrustRef for specified policy and certs */
100 ortn
= SecTrustCreateWithCertificates(subjCerts
,
103 cssmPerror("SecTrustCreateWithCertificates", ortn
);
107 if(disableLocalIntermediates
) {
109 * Avoid searching user keychains for intermediate certs
110 * by specifying an empty array of keychains
112 CFMutableArrayRef kcList
;
113 kcList
= CFArrayCreateMutable(NULL
, 0, NULL
);
115 printf("***CFArrayCreateMutable error\n");
119 ortn
= SecTrustSetKeychains(secTrust
, kcList
);
121 cssmPerror("SecTrustSetKeychains", ortn
);
128 ortn
= SecTrustEvaluate(secTrust
, &secTrustResult
);
130 cssmPerror("SecTrustEvaluate", ortn
);
133 switch(secTrustResult
) {
134 case kSecTrustResultUnspecified
:
135 /* cert chain valid, no special UserTrust assignments */
136 case kSecTrustResultProceed
:
137 /* cert chain valid AND user explicitly trusts this */
139 case kSecTrustResultDeny
:
140 case kSecTrustResultConfirm
:
142 * Cert chain may well have verified OK, but user has flagged
143 * one of these certs as untrustable.
145 printf("***User specified that a cert in this chain is untrusted.\n");
150 /* private SPI to get low-level CSSM error */
152 ortn
= SecTrustGetCssmResultCode(secTrust
, (OSStatus
*)&crtn
);
154 cssmPerror("SecTrustEvaluate", ortn
);
160 /* get some detailed error info */
162 case CSSMERR_TP_INVALID_ANCHOR_CERT
:
163 printf("***Verified to unknown anchor cert\n");
165 case CSSMERR_TP_NOT_TRUSTED
:
166 printf("***Can not verify to a root cert \n");
168 case CSSMERR_TP_CERT_EXPIRED
:
169 printf("***A cert in this chain has expired\n");
171 case CSSMERR_TP_CERT_NOT_VALID_YET
:
172 printf("***A cert in this chain is not yet valid\n");
175 printf("Other error from SecTrustEvaluate\n");
176 cssmPerror("SecTrustEvaluate", crtn
);
179 } /* SecTrustEvaluate error */
181 /* get resulting constructed cert chain */
182 ortn
= SecTrustGetResult(secTrust
, &secTrustResult
, &certChain
, &dummyEv
);
184 cssmPerror("SecTrustEvaluate", ortn
);
188 /* display the results */
189 numCerts
= CFArrayGetCount(certChain
);
190 printf("Number of certs in constructed cert chain = %d\n", (int)numCerts
);
192 for(unsigned i
=0; i
<numCerts
; i
++) {
194 certRef
= (SecCertificateRef
)CFArrayGetValueAtIndex(certChain
, i
);
195 ortn
= SecCertificateGetData(certRef
, &cd
);
197 printf("***SecCertificateGetData returned %d\n", (int)ortn
);
200 printf("\n================== Cert %d ===================\n\n", i
);
201 printCert(cd
.Data
, cd
.Length
, CSSM_FALSE
);
202 printf("\n=============== End of Cert %d ===============\n", i
);
204 if((fileBase
!= NULL
) & (i
> 0)) {
206 sprintf(fname
, "%s_%u", fileBase
, i
);
207 if(writeFile(fname
, cd
.Data
, cd
.Length
)) {
208 printf("***Error writing to %s\n", fname
);
211 printf("...write %lu bytes to %s\n", cd
.Length
, fname
);
218 /* mallocds by readFile() */
225 CFRelease(subjCerts
);
231 CFRelease(policySearch
);