2 * Gather up user-specified raw cert files, attempt to verify as a
6 #include <Security/cssm.h>
7 #include <Security/oidsalg.h>
8 #include <Security/cssmapple.h>
9 #include <Security/Security.h>
10 #include <Security/SecTrustPriv.h>
11 #include <Security/SecPolicyPriv.h>
12 #include <security_cdsa_utils/cuFileIo.h>
13 #include <utilLib/common.h>
14 #include <utilLib/cspwrap.h>
15 #include <clAppUtils/clutils.h>
16 #include <clAppUtils/tpUtils.h>
17 #include <clAppUtils/sslAppUtils.h>
23 static void usage(char **argv
)
25 printf("Usage: %s [options] certFile ..., leaf first\n", argv
[0]);
27 printf(" -s SSL policy (default is basic)\n");
28 printf(" -e allow expired cert\n");
29 printf(" -E allow expired root\n");
30 printf(" -S serverName\n");
31 printf(" -t timeBaseString (default = now)\n");
32 printf(" -T use SecTrustEvaluate\n");
33 printf(" -v verbose\n");
37 static void printResult(
42 printf(" ...successful verification\n");
44 case CSSMERR_TP_INVALID_CERTIFICATE
:
45 printf(" ...invalid leaf cert\n");
47 case CSSMERR_TP_INVALID_ANCHOR_CERT
:
48 printf(" ...cert chain valid (unknown root)\n");
50 case CSSMERR_TP_NOT_TRUSTED
:
51 printf(" ...no root cert found\n");
53 case CSSMERR_TP_VERIFICATION_FAILURE
:
54 printf(" ...bad root cert\n");
56 case CSSMERR_TP_VERIFY_ACTION_FAILED
:
57 printf(" ...policy verification failed\n");
59 case CSSMERR_TP_CERT_EXPIRED
:
60 printf(" ...expired cert in chain\n");
62 case CSSMERR_TP_CERT_NOT_VALID_YET
:
63 printf(" ...not-yet-valid cert in chain\n");
66 printError("tpCertGroupVerify", crtn
);
71 int main(int argc
, char **argv
)
73 CSSM_CL_HANDLE clHand
; // CL handle
74 CSSM_TP_HANDLE tpHand
; // TP handle
75 CSSM_CSP_HANDLE cspHand
= 0; // CSP handle
76 CSSM_DATA_PTR rawCerts
= NULL
;
77 unsigned numCerts
; // num certs in *rawCerts
80 const CSSM_OID
*policyId
= &CSSMOID_APPLE_X509_BASIC
;
81 uint32 evidenceSize
= 0;
82 CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult
;
83 CSSM_CERTGROUP_PTR outGrp
= NULL
;
86 CSSM_BOOL allowExpiredCert
= CSSM_FALSE
;
87 bool allowExpiredRoot
= false;
88 bool useSecTrust
= false;
90 CSSM_APPLE_TP_SSL_OPTIONS sslOpts
;
91 CSSM_APPLE_TP_ACTION_DATA tpAction
;
92 char *serverName
= NULL
;
94 unsigned numEvidences
= 0;
96 CSSM_DATA_PTR fieldOptsPtr
= NULL
;
98 CSSM_DATA_PTR actionDataPtr
= NULL
;
99 char *cssmTimeStr
= NULL
;
100 SecTrustRef theTrust
= NULL
;
105 for(arg
=1; arg
<argc
; arg
++) {
106 if(argv
[arg
][0] != '-') {
110 switch(argv
[arg
][1]) {
112 policyId
= &CSSMOID_APPLE_TP_SSL
;
115 allowExpiredCert
= true;
118 allowExpiredRoot
= true;
124 if(arg
== (argc
- 1)) {
127 serverName
= argv
[++arg
];
130 if(arg
== (argc
- 1)) {
133 cssmTimeStr
= argv
[++arg
];
143 /* common setup for TP and SecTrust */
144 if(policyId
== &CSSMOID_APPLE_TP_SSL
) {
145 sslOpts
.Version
= CSSM_APPLE_TP_SSL_OPTS_VERSION
;
146 sslOpts
.ServerName
= serverName
;
148 sslOpts
.ServerNameLen
= strlen(serverName
) + 1;
151 sslOpts
.ServerNameLen
= 0;
153 fieldOpts
.Data
= (uint8
*)&sslOpts
;
154 fieldOpts
.Length
= sizeof(sslOpts
);
155 fieldOptsPtr
= &fieldOpts
;
157 else if(serverName
) {
158 printf("***Server name option only valid for SSL policy.\n");
162 if(allowExpiredCert
|| allowExpiredRoot
) {
163 tpAction
.Version
= CSSM_APPLE_TP_ACTION_VERSION
;
164 tpAction
.ActionFlags
= 0;
165 if(allowExpiredCert
) {
166 tpAction
.ActionFlags
|= CSSM_TP_ACTION_ALLOW_EXPIRED
;
168 if(allowExpiredRoot
) {
169 tpAction
.ActionFlags
|= CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT
;
171 actionData
.Data
= (uint8
*)&tpAction
;
172 actionData
.Length
= sizeof(tpAction
);
173 actionDataPtr
= &actionData
;
175 /* else actionDataPtr NULL */
178 numCerts
= argc
- fileArg
;
183 rawCerts
= (CSSM_DATA_PTR
)CSSM_MALLOC(numCerts
* sizeof(CSSM_DATA
));
184 if(rawCerts
== NULL
) {
185 printf("malloc error\n");
189 /* gather cert data */
190 for(i
=0; i
<numCerts
; i
++) {
191 CSSM_DATA_PTR c
= &rawCerts
[i
];
193 if(readFile(argv
[fileArg
], &c
->Data
, &len
)) {
194 printf("Error reading %s=n", argv
[fileArg
]);
202 SecPolicyRef policy
= NULL
;
203 SecPolicySearchRef policySearch
= NULL
;
204 SecCertificateRef cert
; // only lives in CFArrayRefs
205 SecTrustResultType secTrustResult
;
207 const char *evalResStr
= NULL
;
208 CSSM_TP_APPLE_EVIDENCE_INFO
*evidence
= NULL
;
210 /* convert raw certs to a CFArray of SecCertificateRefs */
211 CFMutableArrayRef certGroup
= CFArrayCreateMutable(NULL
, numCerts
,
212 &kCFTypeArrayCallBacks
);
213 for(i
=0; i
<numCerts
; i
++) {
214 ortn
= SecCertificateCreateFromData(&rawCerts
[i
], CSSM_CERT_X_509v3
,
215 CSSM_CERT_ENCODING_DER
, &cert
);
217 printf("SecCertificateCreateFromData returned %s\n",
218 sslGetSSLErrString(ortn
));
221 CFArrayAppendValue(certGroup
, cert
);
224 /* get a SecPolicySearchRef */
225 ortn
= SecPolicySearchCreate(CSSM_CERT_X_509v3
,
226 policyId
, NULL
, &policySearch
);
228 printf("SecPolicySearchCreate returned %s\n",
229 sslGetSSLErrString(ortn
));
232 ortn
= SecPolicySearchCopyNext(policySearch
, &policy
);
234 printf("SecPolicySearchCopyNext returned %s\n",
235 sslGetSSLErrString(ortn
));
239 /* options only for SSL */
240 if(fieldOptsPtr
!= NULL
) {
241 ortn
= SecPolicySetValue(policy
, fieldOptsPtr
);
243 printf("SecPolicySetValue returned %s\n",
244 sslGetSSLErrString(ortn
));
249 /* now a SecTrustRef */
250 ortn
= SecTrustCreateWithCertificates(certGroup
, policy
, &theTrust
);
252 printf("SecTrustCreateWithCertificates returned %s\n",
253 sslGetSSLErrString(ortn
));
258 CFDataRef actionData
=
259 CFDataCreate(NULL
, actionDataPtr
->Data
, actionDataPtr
->Length
);
261 ortn
= SecTrustSetParameters(theTrust
, CSSM_TP_ACTION_DEFAULT
,
264 printf("SecTrustSetParameters returned %s\n", sslGetSSLErrString(ortn
));
267 CFRelease(actionData
);
271 * Here we go; hand it over to SecTrust/TP.
273 ortn
= SecTrustEvaluate(theTrust
, &secTrustResult
);
275 printf("SecTrustEvaluate returned %s\n", sslGetSSLErrString(ortn
));
279 switch(secTrustResult
) {
280 case kSecTrustResultInvalid
:
281 /* should never happen */
282 evalResStr
= "kSecTrustResultInvalid";
284 case kSecTrustResultProceed
:
285 /* cert chain valid AND user explicitly trusts this */
286 evalResStr
= "kSecTrustResultProceed";
288 case kSecTrustResultConfirm
:
290 * Cert chain may well have verified OK, but user has flagged
291 * one of these certs as untrustable.
293 evalResStr
= "kSecTrustResultConfirm";
295 case kSecTrustResultDeny
:
297 * Cert chain may well have verified OK, but user has flagged
298 * one of these certs as untrustable.
300 evalResStr
= "kSecTrustResultDeny";
302 case kSecTrustResultUnspecified
:
303 /* cert chain valid, no special UserTrust assignments */
304 evalResStr
= "kSecTrustResultUnspecified";
306 case kSecTrustResultRecoverableTrustFailure
:
308 evalResStr
= "kSecTrustResultRecoverableTrustFailure";
310 case kSecTrustResultFatalTrustFailure
:
312 evalResStr
= "kSecTrustResultFatalTrustFailure";
314 case kSecTrustResultOtherError
:
316 evalResStr
= "kSecTrustResultOtherError";
321 printf("...SecTrustEvaluate result : ");
322 if(evalResStr
!= NULL
) {
323 printf("%s\n", evalResStr
);
326 printf("UNKNOWN (%d)\n", (int)secTrustResult
);
328 /* get low-level TP return code */
330 ortn
= SecTrustGetCssmResultCode(theTrust
, &ocrtn
);
332 printf("SecTrustGetCssmResultCode returned %s\n", sslGetSSLErrString(ortn
));
339 ortn
= SecTrustGetResult(theTrust
, &secTrustResult
, &dummy
,
342 printf("SecTrustGetResult returned %s\n", sslGetSSLErrString(ortn
));
346 unsigned numEvidences
= CFArrayGetCount(dummy
);
347 if(numEvidences
&& verbose
) {
348 printCertInfo(numEvidences
, evidence
);
353 /* connect to CL, TP, and CSP */
354 cspHand
= cspStartup();
358 /* subsequent errors to abort: */
359 clHand
= clStartup();
363 tpHand
= tpStartup();
369 * Cook up a cert group - TP wants leaf first
371 memset(&cgrp
, 0, sizeof(CSSM_CERTGROUP
));
372 cgrp
.NumCerts
= numCerts
;
373 cgrp
.CertGroupType
= CSSM_CERTGROUP_DATA
;
374 cgrp
.CertType
= CSSM_CERT_X_509v3
;
375 cgrp
.CertEncoding
= CSSM_CERT_ENCODING_DER
;
376 cgrp
.GroupList
.CertList
= rawCerts
;
378 crtn
= tpCertGroupVerify(
390 CSSM_TP_STOP_ON_POLICY
,
392 &vfyResult
); // verify result
394 if((vfyResult
.Evidence
!= NULL
) && (vfyResult
.Evidence
->Evidence
!= NULL
)) {
395 numEvidences
= vfyResult
.NumberOfEvidences
;
396 if(numEvidences
== 3) {
397 /* i.e., normal case */
398 outGrp
= (CSSM_CERTGROUP_PTR
)vfyResult
.Evidence
[1].Evidence
;
399 evidenceSize
= outGrp
->NumCerts
;
402 printf("***Expected numEvidences 3, got %u\n", numEvidences
);
406 printf(" num input certs %d; evidenceSize %u\n",
407 numCerts
, (unsigned)evidenceSize
);
408 if((numEvidences
> 0) && verbose
) {
409 dumpVfyResult(&vfyResult
);
411 freeVfyResult(&vfyResult
);
415 if(rawCerts
!= NULL
) {
416 /* mallocd by readFile() */
417 for(i
=0; i
<numCerts
; i
++) {
418 free(rawCerts
[i
].Data
);
422 if(theTrust
!= NULL
) {