]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/vfyCertChain/vfyCertChain.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / vfyCertChain / vfyCertChain.cpp
1 /*
2 * Gather up user-specified raw cert files, attempt to verify as a
3 * cert chain
4 */
5
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>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <time.h>
21 #include <string.h>
22
23 static void usage(char **argv)
24 {
25 printf("Usage: %s [options] certFile ..., leaf first\n", argv[0]);
26 printf("Options:\n");
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");
34 exit(1);
35 }
36
37 static void printResult(
38 CSSM_RETURN crtn)
39 {
40 switch(crtn) {
41 case CSSM_OK:
42 printf(" ...successful verification\n");
43 break;
44 case CSSMERR_TP_INVALID_CERTIFICATE:
45 printf(" ...invalid leaf cert\n");
46 break;
47 case CSSMERR_TP_INVALID_ANCHOR_CERT:
48 printf(" ...cert chain valid (unknown root)\n");
49 break;
50 case CSSMERR_TP_NOT_TRUSTED:
51 printf(" ...no root cert found\n");
52 break;
53 case CSSMERR_TP_VERIFICATION_FAILURE:
54 printf(" ...bad root cert\n");
55 break;
56 case CSSMERR_TP_VERIFY_ACTION_FAILED:
57 printf(" ...policy verification failed\n");
58 break;
59 case CSSMERR_TP_CERT_EXPIRED:
60 printf(" ...expired cert in chain\n");
61 break;
62 case CSSMERR_TP_CERT_NOT_VALID_YET:
63 printf(" ...not-yet-valid cert in chain\n");
64 break;
65 default:
66 printError("tpCertGroupVerify", crtn);
67 break;
68 }
69
70 }
71 int main(int argc, char **argv)
72 {
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
78 unsigned i;
79 CSSM_CERTGROUP cgrp;
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;
84 int fileArg;
85 CSSM_RETURN crtn;
86 CSSM_BOOL allowExpiredCert = CSSM_FALSE;
87 bool allowExpiredRoot = false;
88 bool useSecTrust = false;
89 int arg;
90 CSSM_APPLE_TP_SSL_OPTIONS sslOpts;
91 CSSM_APPLE_TP_ACTION_DATA tpAction;
92 char *serverName = NULL;
93 bool verbose = false;
94 unsigned numEvidences = 0;
95 CSSM_DATA fieldOpts;
96 CSSM_DATA_PTR fieldOptsPtr = NULL;
97 CSSM_DATA actionData;
98 CSSM_DATA_PTR actionDataPtr = NULL;
99 char *cssmTimeStr = NULL;
100 SecTrustRef theTrust = NULL;
101
102 if(argc < 2) {
103 usage(argv);
104 }
105 for(arg=1; arg<argc; arg++) {
106 if(argv[arg][0] != '-') {
107 fileArg = arg;
108 break;
109 }
110 switch(argv[arg][1]) {
111 case 's':
112 policyId = &CSSMOID_APPLE_TP_SSL;
113 break;
114 case 'e':
115 allowExpiredCert = true;
116 break;
117 case 'E':
118 allowExpiredRoot = true;
119 break;
120 case 'v':
121 verbose = true;
122 break;
123 case 'S':
124 if(arg == (argc - 1)) {
125 usage(argv);
126 }
127 serverName = argv[++arg];
128 break;
129 case 't':
130 if(arg == (argc - 1)) {
131 usage(argv);
132 }
133 cssmTimeStr = argv[++arg];
134 break;
135 case 'T':
136 useSecTrust = true;
137 break;
138 default:
139 usage(argv);
140 }
141 }
142
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;
147 if(serverName) {
148 sslOpts.ServerNameLen = strlen(serverName) + 1;
149 }
150 else {
151 sslOpts.ServerNameLen = 0;
152 }
153 fieldOpts.Data = (uint8 *)&sslOpts;
154 fieldOpts.Length = sizeof(sslOpts);
155 fieldOptsPtr = &fieldOpts;
156 }
157 else if(serverName) {
158 printf("***Server name option only valid for SSL policy.\n");
159 usage(argv);
160 }
161
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;
167 }
168 if(allowExpiredRoot) {
169 tpAction.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT;
170 }
171 actionData.Data = (uint8 *)&tpAction;
172 actionData.Length = sizeof(tpAction);
173 actionDataPtr = &actionData;
174 }
175 /* else actionDataPtr NULL */
176
177
178 numCerts = argc - fileArg;
179 if(numCerts == 0) {
180 usage(argv);
181 }
182
183 rawCerts = (CSSM_DATA_PTR)CSSM_MALLOC(numCerts * sizeof(CSSM_DATA));
184 if(rawCerts == NULL) {
185 printf("malloc error\n");
186 goto abort;
187 }
188
189 /* gather cert data */
190 for(i=0; i<numCerts; i++) {
191 CSSM_DATA_PTR c = &rawCerts[i];
192 unsigned len;
193 if(readFile(argv[fileArg], &c->Data, &len)) {
194 printf("Error reading %s=n", argv[fileArg]);
195 exit(1);
196 }
197 c->Length = len;
198 fileArg++;
199 }
200
201 if(useSecTrust) {
202 SecPolicyRef policy = NULL;
203 SecPolicySearchRef policySearch = NULL;
204 SecCertificateRef cert; // only lives in CFArrayRefs
205 SecTrustResultType secTrustResult;
206 OSStatus ortn;
207 const char *evalResStr = NULL;
208 CSSM_TP_APPLE_EVIDENCE_INFO *evidence = NULL;
209
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);
216 if(cert == NULL) {
217 printf("SecCertificateCreateFromData returned %s\n",
218 sslGetSSLErrString(ortn));
219 exit(1);
220 }
221 CFArrayAppendValue(certGroup, cert);
222 }
223
224 /* get a SecPolicySearchRef */
225 ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
226 policyId, NULL, &policySearch);
227 if(ortn) {
228 printf("SecPolicySearchCreate returned %s\n",
229 sslGetSSLErrString(ortn));
230 exit(1);
231 }
232 ortn = SecPolicySearchCopyNext(policySearch, &policy);
233 if(ortn) {
234 printf("SecPolicySearchCopyNext returned %s\n",
235 sslGetSSLErrString(ortn));
236 exit(1);
237 }
238
239 /* options only for SSL */
240 if(fieldOptsPtr != NULL) {
241 ortn = SecPolicySetValue(policy, fieldOptsPtr);
242 if(ortn) {
243 printf("SecPolicySetValue returned %s\n",
244 sslGetSSLErrString(ortn));
245 exit(1);
246 }
247 }
248
249 /* now a SecTrustRef */
250 ortn = SecTrustCreateWithCertificates(certGroup, policy, &theTrust);
251 if(ortn) {
252 printf("SecTrustCreateWithCertificates returned %s\n",
253 sslGetSSLErrString(ortn));
254 exit(1);
255 }
256
257 if(actionDataPtr) {
258 CFDataRef actionData =
259 CFDataCreate(NULL, actionDataPtr->Data, actionDataPtr->Length);
260
261 ortn = SecTrustSetParameters(theTrust, CSSM_TP_ACTION_DEFAULT,
262 actionData);
263 if(ortn) {
264 printf("SecTrustSetParameters returned %s\n", sslGetSSLErrString(ortn));
265 exit(1);
266 }
267 CFRelease(actionData);
268 }
269
270 /*
271 * Here we go; hand it over to SecTrust/TP.
272 */
273 ortn = SecTrustEvaluate(theTrust, &secTrustResult);
274 if(ortn) {
275 printf("SecTrustEvaluate returned %s\n", sslGetSSLErrString(ortn));
276 exit(1);
277 }
278 crtn = CSSM_OK;
279 switch(secTrustResult) {
280 case kSecTrustResultInvalid:
281 /* should never happen */
282 evalResStr = "kSecTrustResultInvalid";
283 break;
284 case kSecTrustResultProceed:
285 /* cert chain valid AND user explicitly trusts this */
286 evalResStr = "kSecTrustResultProceed";
287 break;
288 case kSecTrustResultConfirm:
289 /*
290 * Cert chain may well have verified OK, but user has flagged
291 * one of these certs as untrustable.
292 */
293 evalResStr = "kSecTrustResultConfirm";
294 break;
295 case kSecTrustResultDeny:
296 /*
297 * Cert chain may well have verified OK, but user has flagged
298 * one of these certs as untrustable.
299 */
300 evalResStr = "kSecTrustResultDeny";
301 break;
302 case kSecTrustResultUnspecified:
303 /* cert chain valid, no special UserTrust assignments */
304 evalResStr = "kSecTrustResultUnspecified";
305 break;
306 case kSecTrustResultRecoverableTrustFailure:
307 /* ? */
308 evalResStr = "kSecTrustResultRecoverableTrustFailure";
309 break;
310 case kSecTrustResultFatalTrustFailure:
311 /* ? */
312 evalResStr = "kSecTrustResultFatalTrustFailure";
313 break;
314 case kSecTrustResultOtherError:
315 /* ? */
316 evalResStr = "kSecTrustResultOtherError";
317 break;
318 default:
319 break;
320 }
321 printf("...SecTrustEvaluate result : ");
322 if(evalResStr != NULL) {
323 printf("%s\n", evalResStr);
324 }
325 else {
326 printf("UNKNOWN (%d)\n", (int)secTrustResult);
327 }
328 /* get low-level TP return code */
329 OSStatus ocrtn;
330 ortn = SecTrustGetCssmResultCode(theTrust, &ocrtn);
331 if(ortn) {
332 printf("SecTrustGetCssmResultCode returned %s\n", sslGetSSLErrString(ortn));
333 /*...keep going */
334 }
335 else {
336 printResult(ocrtn);
337 }
338 CFArrayRef dummy;
339 ortn = SecTrustGetResult(theTrust, &secTrustResult, &dummy,
340 &evidence);
341 if(ortn) {
342 printf("SecTrustGetResult returned %s\n", sslGetSSLErrString(ortn));
343 /*...keep going */
344 }
345 else {
346 unsigned numEvidences = CFArrayGetCount(dummy);
347 if(numEvidences && verbose) {
348 printCertInfo(numEvidences, evidence);
349 }
350 }
351 }
352 else {
353 /* connect to CL, TP, and CSP */
354 cspHand = cspStartup();
355 if(cspHand == 0) {
356 exit(1);
357 }
358 /* subsequent errors to abort: */
359 clHand = clStartup();
360 if(clHand == 0) {
361 goto abort;
362 }
363 tpHand = tpStartup();
364 if(tpHand == 0) {
365 goto abort;
366 }
367
368 /*
369 * Cook up a cert group - TP wants leaf first
370 */
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;
377
378 crtn = tpCertGroupVerify(
379 tpHand,
380 clHand,
381 cspHand,
382 NULL, // dbListPtr
383 policyId,
384 fieldOptsPtr,
385 actionDataPtr,
386 NULL, // policyOpts
387 &cgrp,
388 NULL, // anchorCerts
389 0, // NumAnchorCerts
390 CSSM_TP_STOP_ON_POLICY,
391 cssmTimeStr,
392 &vfyResult); // verify result
393 printResult(crtn);
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;
400 }
401 else {
402 printf("***Expected numEvidences 3, got %u\n", numEvidences);
403 evidenceSize = 0;
404 }
405 }
406 printf(" num input certs %d; evidenceSize %u\n",
407 numCerts, (unsigned)evidenceSize);
408 if((numEvidences > 0) && verbose) {
409 dumpVfyResult(&vfyResult);
410 }
411 freeVfyResult(&vfyResult);
412 }
413
414 abort:
415 if(rawCerts != NULL) {
416 /* mallocd by readFile() */
417 for(i=0; i<numCerts; i++) {
418 free(rawCerts[i].Data);
419 }
420 CSSM_FREE(rawCerts);
421 }
422 if(theTrust != NULL) {
423 CFRelease(theTrust);
424 }
425 return 0;
426 }