]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/clAppUtils/certVerify.cpp
Security-57031.10.10.tar.gz
[apple/security.git] / SecurityTests / clxutils / clAppUtils / certVerify.cpp
1 /*
2 * certVerify.cpp - execute cert/CRL verify; display results
3 */
4
5 #include "certVerify.h"
6 #include "tpUtils.h"
7 #include <utilLib/common.h>
8 #include <clAppUtils/clutils.h>
9 #include <clAppUtils/tpUtils.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <Security/cssm.h>
14 #include <Security/oidsalg.h>
15 #include <Security/SecTrust.h>
16 #include <Security/SecPolicySearch.h>
17 #include <Security/cssmapplePriv.h>
18 #include <security_cdsa_utils/cuCdsaUtils.h>
19 #include <Security/TrustSettingsSchema.h>
20
21 static int vfyCertErrors(
22 const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult,
23 unsigned numCertErrors,
24 const char **certErrors, // e.g., "2:CSSMERR_TP_CERT_EXPIRED"
25 CSSM_BOOL quiet)
26 {
27 if(numCertErrors == 0) {
28 return 0;
29 }
30 if(vfyResult->NumberOfEvidences != 3) {
31 printf("***vfyCertErrors: NumberOfEvidences is %u, expect 3\n",
32 (unsigned)vfyResult->NumberOfEvidences);
33 return 1;
34 }
35
36 /* numCerts from evidence[1] */
37 const CSSM_EVIDENCE *ev = &vfyResult->Evidence[1];
38 const CSSM_CERTGROUP *grp = (const CSSM_CERTGROUP *)ev->Evidence;
39 unsigned numCerts = grp->NumCerts;
40 /* array of Apple-specific info from evidence[2] */
41 ev = &vfyResult->Evidence[2];
42 const CSSM_TP_APPLE_EVIDENCE_INFO *info =
43 (const CSSM_TP_APPLE_EVIDENCE_INFO *)ev->Evidence;
44 int ourRtn = 0;
45
46 for(unsigned dex=0; dex<numCertErrors; dex++) {
47 const char *str = certErrors[dex];
48 char buf[8];
49 unsigned i;
50
51 /*
52 * Format is certNum:errorString
53 * first get the cert number
54 */
55 for(i=0; *str != '\0'; i++, str++) {
56 if(*str == ':') {
57 break;
58 }
59 buf[i] = *str;
60 }
61 if(*str != ':') {
62 printf("***Bad certerror value, format is certNum:errorString\n");
63 return 1;
64 }
65 buf[i] = '\0';
66 unsigned certNum = atoi(buf);
67 if(certNum > (numCerts-1)) {
68 printf("***certerror specified for cert %u, but only %u certs"
69 " available\n", certNum, numCerts);
70 return 1;
71 }
72 str++; // pts to actual desired error string now
73
74 /*
75 * There may be multiple per-cert statuses in the evidence; search all
76 * looking for a match
77 */
78 const CSSM_TP_APPLE_EVIDENCE_INFO *thisInfo = &info[certNum];
79 char *found = NULL;
80 for(unsigned i=0; i<thisInfo->NumStatusCodes; i++) {
81 CSSM_RETURN actRtn = thisInfo->StatusCodes[i];
82 const char *actRtnStr = cssmErrToStr(actRtn);
83 found = strstr(actRtnStr, str);
84 if(found) {
85 break;
86 }
87 }
88 if(found) {
89 if(!quiet) {
90 printf("...%s per-cert status received as expected\n", str);
91 }
92 }
93 else {
94 printf("***Per cert status %s not found\n", str);
95 ourRtn = 1;
96 /* might as well keep going */
97 }
98 }
99 return ourRtn;
100 }
101
102 static int vfyCertStatus(
103 const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult,
104 unsigned numCertStatus,
105 const char **certStatus, // e.g., "1:0x18", leading 0x optional
106 CSSM_BOOL quiet)
107 {
108 if(numCertStatus == 0) {
109 return 0;
110 }
111 if(vfyResult->NumberOfEvidences != 3) {
112 printf("***vfyCertStatus: NumberOfEvidences is %u, expect 3\n",
113 (unsigned)vfyResult->NumberOfEvidences);
114 return 1;
115 }
116
117 /* numCerts from evidence[1] */
118 const CSSM_EVIDENCE *ev = &vfyResult->Evidence[1];
119 const CSSM_CERTGROUP *grp = (const CSSM_CERTGROUP *)ev->Evidence;
120 unsigned numCerts = grp->NumCerts;
121 /* array of Apple-specific info from evidence[2] */
122 ev = &vfyResult->Evidence[2];
123 const CSSM_TP_APPLE_EVIDENCE_INFO *info =
124 (const CSSM_TP_APPLE_EVIDENCE_INFO *)ev->Evidence;
125 int ourRtn = 0;
126
127 for(unsigned dex=0; dex<numCertStatus; dex++) {
128 const char *str = certStatus[dex];
129 char buf[8];
130 unsigned i;
131
132 /*
133 * Format is certNum:status_in_hex
134 * first get the cert number
135 */
136 for(i=0; *str != '\0'; i++, str++) {
137 if(*str == ':') {
138 break;
139 }
140 buf[i] = *str;
141 }
142 if(*str != ':') {
143 printf("***Bad certstatus value, format is certNum:status_in_hex\n");
144 return 1;
145 }
146 buf[i] = '\0';
147 unsigned certNum = atoi(buf);
148 if(certNum > (numCerts-1)) {
149 printf("***certerror specified for cert %u, but only %u certs"
150 " available\n", certNum, numCerts);
151 return 1;
152 }
153 str++; // pts to actual desired status string now
154 unsigned certStat = hexToBin(str);
155 const CSSM_TP_APPLE_EVIDENCE_INFO *thisInfo = &info[certNum];
156 if(certStat == thisInfo->StatusBits) {
157 if(!quiet) {
158 printf("...0x%x per-cert status received as expected\n", certStat);
159 }
160 }
161 else {
162 printf("***Expected per cert status 0x%x, got 0x%x\n",
163 (unsigned)certStat, (unsigned)thisInfo->StatusBits);
164 ourRtn = 1;
165 }
166 }
167 return ourRtn;
168 }
169
170 /*
171 * Ensure that the policy being evaluated is accessible via
172 * SecPolicySearch*(). Not really part of the test, but a handy place
173 * to catch this common error before checking in TP changes.
174 */
175 static int verifySecPolicy(
176 const CSSM_OID *oid)
177 {
178 SecPolicySearchRef srchRef = NULL;
179 OSStatus ortn;
180
181 ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, oid, NULL, &srchRef);
182 if(ortn) {
183 cssmPerror("SecPolicySearchCreate", ortn);
184 return -1;
185 }
186 SecPolicyRef policyRef = NULL;
187 ortn = SecPolicySearchCopyNext(srchRef, &policyRef);
188 if(ortn) {
189 cssmPerror("SecPolicySearchCopyNext", ortn);
190 printf("***The TP policy used in this test is not accessible via SecPolicySearchCopyNext().\n");
191 printf(" You probably forgot to add the policy to the theOidList table in PolicyCursor.cpp\n");
192 printf(" in the libsecurity_keychain project.\n");
193 }
194 CFRelease(srchRef);
195 if(policyRef) {
196 CFRelease(policyRef);
197 }
198 return ortn;
199 }
200
201 int certVerify(CertVerifyArgs *vfyArgs)
202 {
203 if(vfyArgs->version != CERT_VFY_ARGS_VERS) {
204 printf("***CertVerifyArgs.Version mismatch. Clean and rebuild.\n");
205 return -1;
206 }
207
208 /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */
209 CSSM_TP_VERIFY_CONTEXT vfyCtx;
210 CSSM_TP_CALLERAUTH_CONTEXT authCtx;
211 CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult;
212 CSSM_APPLE_TP_SSL_OPTIONS sslOpts;
213 CSSM_APPLE_TP_SMIME_OPTIONS smimeOpts;
214
215 memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT));
216 memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
217
218 /* CSSM_TP_CALLERAUTH_CONTEXT components */
219 /*
220 typedef struct cssm_tp_callerauth_context {
221 CSSM_TP_POLICYINFO Policy;
222 CSSM_TIMESTRING VerifyTime;
223 CSSM_TP_STOP_ON VerificationAbortOn;
224 CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert;
225 uint32 NumberOfAnchorCerts;
226 CSSM_DATA_PTR AnchorCerts;
227 CSSM_DL_DB_LIST_PTR DBList;
228 CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials;
229 } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR;
230 */
231 /* up to 3 policies */
232 CSSM_FIELD policyIds[3];
233 CSSM_FIELD *policyPtr = &policyIds[0];
234 uint32 numPolicies = 0;
235 memset(policyIds, 0, 3 * sizeof(CSSM_FIELD));
236
237 switch(vfyArgs->vfyPolicy) {
238 case CVP_SSL:
239 case CVP_IPSec:
240 if(vfyArgs->vfyPolicy == CVP_SSL) {
241 policyPtr->FieldOid = CSSMOID_APPLE_TP_SSL;
242 }
243 else {
244 policyPtr->FieldOid = CSSMOID_APPLE_TP_IP_SEC;
245 }
246 /* otherwise these policies are identical */
247 /* sslOpts is optional */
248 if((vfyArgs->sslHost != NULL) || vfyArgs->sslClient) {
249 memset(&sslOpts, 0, sizeof(sslOpts));
250 sslOpts.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION;
251 sslOpts.ServerName = vfyArgs->sslHost;
252 if(vfyArgs->sslHost != NULL) {
253 sslOpts.ServerNameLen = strlen(vfyArgs->sslHost) + 1;
254 }
255 if(vfyArgs->sslClient) {
256 sslOpts.Flags |= CSSM_APPLE_TP_SSL_CLIENT;
257 }
258 policyPtr->FieldValue.Data = (uint8 *)&sslOpts;
259 policyPtr->FieldValue.Length = sizeof(sslOpts);
260 }
261 break;
262 case CVP_SMIME:
263 case CVP_iChat:
264 if(vfyArgs->vfyPolicy == CVP_SMIME) {
265 policyPtr->FieldOid = CSSMOID_APPLE_TP_SMIME;
266 }
267 else {
268 policyPtr->FieldOid = CSSMOID_APPLE_TP_ICHAT;
269 }
270 /* otherwise these policies are identical */
271 /* smimeOpts is optional */
272 if(vfyArgs->senderEmail != NULL) {
273 smimeOpts.Version = CSSM_APPLE_TP_SMIME_OPTS_VERSION;
274 smimeOpts.IntendedUsage = vfyArgs->intendedKeyUse;
275 smimeOpts.SenderEmail = vfyArgs->senderEmail;
276 smimeOpts.SenderEmailLen = strlen(vfyArgs->senderEmail) + 1;
277 policyPtr->FieldValue.Data = (uint8 *)&smimeOpts;
278 policyPtr->FieldValue.Length = sizeof(smimeOpts);
279 }
280 break;
281 case CVP_Basic:
282 policyPtr->FieldOid = CSSMOID_APPLE_X509_BASIC;
283 break;
284 case CVP_SWUpdateSign:
285 /* no options */
286 policyPtr->FieldOid = CSSMOID_APPLE_TP_SW_UPDATE_SIGNING;
287 break;
288 case CVP_ResourceSigning:
289 /* no options */
290 policyPtr->FieldOid = CSSMOID_APPLE_TP_RESOURCE_SIGN;
291 break;
292 case CVP_PKINIT_Server:
293 /* no options */
294 policyPtr->FieldOid = CSSMOID_APPLE_TP_PKINIT_SERVER;
295 break;
296 case CVP_PKINIT_Client:
297 /* no options */
298 policyPtr->FieldOid = CSSMOID_APPLE_TP_PKINIT_CLIENT;
299 break;
300 case CVP_AppleCodeSigning:
301 /* no options */
302 policyPtr->FieldOid = CSSMOID_APPLE_TP_CODE_SIGNING;
303 break;
304 case CVP_PackageSigning:
305 /* no options */
306 policyPtr->FieldOid = CSSMOID_APPLE_TP_PACKAGE_SIGNING;
307 break;
308 default:
309 printf("***certVerify: bogus vfyPolicy\n");
310 return 1;
311 }
312 if(verifySecPolicy(&policyPtr->FieldOid)) {
313 return -1;
314 }
315 policyPtr++;
316 numPolicies++;
317
318 CSSM_APPLE_TP_CRL_OPTIONS crlOpts;
319 if((vfyArgs->revokePolicy == CRP_CRL) || (vfyArgs->revokePolicy == CRP_CRL_OCSP)) {
320 memset(&crlOpts, 0, sizeof(crlOpts));
321 policyPtr->FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL;
322
323 crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
324 crlOpts.CrlFlags = 0;
325 crlOpts.crlStore = NULL;
326 policyPtr->FieldValue.Data = (uint8 *)&crlOpts;
327 policyPtr->FieldValue.Length = sizeof(crlOpts);
328 if(vfyArgs->requireCrlForAll) {
329 crlOpts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT;
330 }
331 if(vfyArgs->crlNetFetchEnable) {
332 crlOpts.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET;
333 }
334 if(vfyArgs->requireCrlIfPresent) {
335 crlOpts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT;
336 }
337 crlOpts.crlStore = vfyArgs->crlDlDb;
338 policyPtr++;
339 numPolicies++;
340 }
341
342 CSSM_APPLE_TP_OCSP_OPTIONS ocspOpts;
343 CSSM_DATA respUriData;
344 CSSM_DATA respCertData = {vfyArgs->responderCertLen,
345 (uint8 *)vfyArgs->responderCert};
346 if((vfyArgs->revokePolicy == CRP_OCSP) || (vfyArgs->revokePolicy == CRP_CRL_OCSP)) {
347 memset(&ocspOpts, 0, sizeof(ocspOpts));
348 policyPtr->FieldOid = CSSMOID_APPLE_TP_REVOCATION_OCSP;
349
350 crlOpts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
351 policyPtr->FieldValue.Data = (uint8 *)&ocspOpts;
352 policyPtr->FieldValue.Length = sizeof(ocspOpts);
353 if(vfyArgs->requireOcspForAll) {
354 ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT;
355 }
356 if(vfyArgs->requireOcspIfPresent) {
357 ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT;
358 }
359 if(vfyArgs->disableCache) {
360 ocspOpts.Flags |= (CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE |
361 CSSM_TP_ACTION_OCSP_CACHE_WRITE_DISABLE);
362 }
363 if(vfyArgs->disableOcspNet) {
364 ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_DISABLE_NET;
365 }
366 if(vfyArgs->generateOcspNonce) {
367 ocspOpts.Flags |= CSSM_TP_OCSP_GEN_NONCE;
368 }
369 if(vfyArgs->requireOcspRespNonce) {
370 ocspOpts.Flags |= CSSM_TP_OCSP_REQUIRE_RESP_NONCE;
371 }
372 if(vfyArgs->responderURI != NULL) {
373 respUriData.Data = (uint8 *)vfyArgs->responderURI;
374 respUriData.Length = strlen(vfyArgs->responderURI);
375 ocspOpts.LocalResponder = &respUriData;
376 }
377 if(vfyArgs->responderCert != NULL) {
378 ocspOpts.LocalResponderCert = &respCertData;
379 }
380 /* other OCSP options here */
381 policyPtr++;
382 numPolicies++;
383 }
384
385 authCtx.Policy.NumberOfPolicyIds = numPolicies;
386
387 authCtx.Policy.PolicyIds = policyIds;
388 authCtx.Policy.PolicyControl = NULL;
389
390 authCtx.VerifyTime = vfyArgs->vfyTime; // may be NULL
391 authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY;
392 authCtx.CallbackWithVerifiedCert = NULL;
393
394 /*
395 * DLDBs - the caller's optional set, plus two more we open
396 * if trust settings are enabled and we're told to use system
397 * anchors. (System anchors are normally passed in via
398 * authCtx.AnchorCerts; they're passed in as DLDBs when
399 * using TrustSettings.)
400 */
401 uint32 totalNumDbs = 0;
402 uint32 numCallerDbs = 0;
403 CSSM_BOOL weOpenedDbs = CSSM_FALSE;
404 if(vfyArgs->dlDbList != NULL) {
405 totalNumDbs = numCallerDbs = vfyArgs->dlDbList->NumHandles;
406 }
407 if(vfyArgs->useTrustSettings && vfyArgs->useSystemAnchors) {
408 /* we'll cook up two more DBs and possible append them */
409 totalNumDbs += 2;
410 weOpenedDbs = CSSM_TRUE;
411 }
412 CSSM_DL_DB_HANDLE dlDbHandles[totalNumDbs];
413 CSSM_DL_DB_LIST dlDbList;
414 CSSM_DL_HANDLE dlHand = 0;
415 for(unsigned dex=0; dex<numCallerDbs; dex++) {
416 dlDbHandles[dex] = vfyArgs->dlDbList->DLDBHandle[dex];
417 }
418 if(weOpenedDbs) {
419 /* get a DL handle, somehow */
420 if(numCallerDbs == 0) {
421 /* new DL handle */
422 dlHand = cuDlStartup();
423 dlDbHandles[0].DLHandle = dlHand;
424 dlDbHandles[1].DLHandle = dlHand;
425 }
426 else {
427 /* use the same one caller passed in */
428 dlDbHandles[numCallerDbs].DLHandle = dlDbHandles[0].DLHandle;
429 dlDbHandles[numCallerDbs + 1].DLHandle = dlDbHandles[0].DLHandle;
430 }
431 /* now open two DBs */
432 dlDbHandles[numCallerDbs].DBHandle =
433 cuDbStartupByName(dlDbHandles[numCallerDbs].DLHandle,
434 (char *)ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
435 dlDbHandles[numCallerDbs + 1].DBHandle =
436 cuDbStartupByName(dlDbHandles[numCallerDbs].DLHandle,
437 (char *)SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
438 }
439 dlDbList.DLDBHandle = dlDbHandles;
440 dlDbList.NumHandles = totalNumDbs;
441 authCtx.DBList = &dlDbList;
442
443 CFArrayRef cfAnchors = NULL;
444 CSSM_DATA *cssmAnchors = NULL;
445 unsigned numAnchors = 0;
446
447 if(vfyArgs->useSystemAnchors) {
448 if(!vfyArgs->useTrustSettings) {
449 /* standard system anchors - ingore error, I'm sure the
450 * current test will eventually fail */
451 getSystemAnchors(&cfAnchors, &cssmAnchors, &numAnchors);
452 authCtx.NumberOfAnchorCerts = numAnchors;
453 authCtx.AnchorCerts = cssmAnchors;
454 }
455 }
456 else {
457 /* anchors are our caller's roots */
458 if(vfyArgs->roots) {
459 authCtx.NumberOfAnchorCerts = vfyArgs->roots->numBlobs();
460 authCtx.AnchorCerts = vfyArgs->roots->blobList();
461 }
462 }
463 authCtx.CallerCredentials = NULL;
464
465 if(vfyArgs->crls) {
466 /* cook up CRL group */
467 CSSM_CRLGROUP_PTR cssmCrls = &vfyCtx.Crls;
468 cssmCrls->CrlType = CSSM_CRL_TYPE_X_509v1;
469 cssmCrls->CrlEncoding = CSSM_CRL_ENCODING_DER;
470 cssmCrls->NumberOfCrls = vfyArgs->crls->numBlobs();
471 cssmCrls->GroupCrlList.CrlList = vfyArgs->crls->blobList();
472 cssmCrls->CrlGroupType = CSSM_CRLGROUP_DATA;
473 }
474
475 /* CSSM_APPLE_TP_ACTION_DATA */
476 CSSM_APPLE_TP_ACTION_DATA tpAction;
477 tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION;
478 tpAction.ActionFlags = 0;
479 if(vfyArgs->leafCertIsCA) {
480 tpAction.ActionFlags |= CSSM_TP_ACTION_LEAF_IS_CA;
481 }
482 if(vfyArgs->certNetFetchEnable) {
483 tpAction.ActionFlags |= CSSM_TP_ACTION_FETCH_CERT_FROM_NET;
484 }
485 if(vfyArgs->allowExpiredRoot) {
486 tpAction.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT;
487 }
488 if(!vfyArgs->allowUnverified) {
489 tpAction.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT;
490 }
491 if(vfyArgs->useTrustSettings) {
492 tpAction.ActionFlags |= CSSM_TP_ACTION_TRUST_SETTINGS;
493 }
494 if(vfyArgs->implicitAnchors) {
495 tpAction.ActionFlags |= CSSM_TP_ACTION_IMPLICIT_ANCHORS;
496 }
497
498 /* CSSM_TP_VERIFY_CONTEXT */
499 vfyCtx.ActionData.Data = (uint8 *)&tpAction;
500 vfyCtx.ActionData.Length = sizeof(tpAction);
501
502 vfyCtx.Action = CSSM_TP_ACTION_DEFAULT;
503 vfyCtx.Cred = &authCtx;
504
505 /* cook up cert group */
506 CSSM_CERTGROUP cssmCerts;
507 cssmCerts.CertType = CSSM_CERT_X_509v3;
508 cssmCerts.CertEncoding = CSSM_CERT_ENCODING_DER;
509 cssmCerts.NumCerts = vfyArgs->certs->numBlobs();
510 cssmCerts.GroupList.CertList = vfyArgs->certs->blobList();
511 cssmCerts.CertGroupType = CSSM_CERTGROUP_DATA;
512
513 int ourRtn = 0;
514 CSSM_RETURN crtn = CSSM_TP_CertGroupVerify(vfyArgs->tpHand,
515 vfyArgs->clHand,
516 vfyArgs->cspHand,
517 &cssmCerts,
518 &vfyCtx,
519 &vfyResult);
520 if(vfyArgs->expectedErrStr != NULL) {
521 const char *actRtn;
522 if(crtn == CSSM_OK) {
523 /* cssmErrorString munges this to "[ok]" */
524 actRtn = "CSSM_OK";
525 }
526 else {
527 actRtn = cssmErrToStr(crtn);
528 }
529 char *found = strstr(actRtn, vfyArgs->expectedErrStr);
530 if(found) {
531 if(!vfyArgs->quiet) {
532 printf("...%s received as expected\n", vfyArgs->expectedErrStr);
533 }
534 }
535 else {
536 printf("***CSSM_TP_CertGroupVerify error\n");
537 printf(" expected rtn : %s\n", vfyArgs->expectedErrStr);
538 printf(" actual rtn : %s\n", actRtn);
539 ourRtn = 1;
540 }
541 }
542 else {
543 if(crtn) {
544 if(!vfyArgs->quiet) {
545 printError("CSSM_TP_CertGroupVerify", crtn);
546 }
547 ourRtn = 1;
548 }
549 else if(!vfyArgs->quiet) {
550 printf("...verify successful\n");
551 }
552 }
553 if(vfyArgs->certErrors) {
554 if(vfyCertErrors(&vfyResult, vfyArgs->numCertErrors, vfyArgs->certErrors,
555 vfyArgs->quiet)) {
556 ourRtn = 1;
557 }
558 }
559 if(vfyArgs->certStatus) {
560 if(vfyCertStatus(&vfyResult, vfyArgs->numCertStatus, vfyArgs->certStatus,
561 vfyArgs->quiet)) {
562 ourRtn = 1;
563 }
564 }
565 if(vfyArgs->verbose) {
566 dumpVfyResult(&vfyResult);
567 }
568 freeVfyResult(&vfyResult);
569 if(weOpenedDbs) {
570 /* close the DBs and maybe the DL we opened */
571 CSSM_DL_DbClose(dlDbHandles[numCallerDbs]);
572 CSSM_DL_DbClose(dlDbHandles[numCallerDbs + 1]);
573 if(dlHand != 0) {
574 cuDlDetachUnload(dlHand);
575 }
576 }
577 if(cfAnchors) {
578 CFRelease(cfAnchors);
579 }
580 if(cssmAnchors) {
581 free(cssmAnchors);
582 }
583 return ourRtn;
584 }
585
586 unsigned hexDigit(char digit)
587 {
588 if((digit >= '0') && (digit <= '9')) {
589 return digit - '0';
590 }
591 if((digit >= 'a') && (digit <= 'f')) {
592 return 10 + digit - 'a';
593 }
594 if((digit >= 'A') && (digit <= 'F')) {
595 return 10 + digit - 'A';
596 }
597 printf("***BAD HEX DIGIT (%c)\n", digit);
598 return 0;
599 }
600
601 /* convert ASCII string in hex to unsigned */
602 unsigned hexToBin(const char *hex)
603 {
604 unsigned rtn = 0;
605 const char *cp = hex;
606 if((cp[0] == '0') && (cp[1] == 'x')) {
607 cp += 2;
608 }
609 if(strlen(cp) > 8) {
610 printf("***BAD HEX STRING (%s)\n", cp);
611 return 0;
612 }
613 while(*cp) {
614 rtn <<= 4;
615 rtn += hexDigit(*cp);
616 cp++;
617 }
618 return rtn;
619 }
620
621 /*
622 * A slightly simplified version of certVerify:
623 * -- no CRLs (includes allowUnverified = CSSM_FALSE)
624 * -- revokePOlicy = None
625 * -- no DlDbs
626 * -- no net fetch
627 * -- time = now.
628 */
629 int certVerifySimple(
630 CSSM_TP_HANDLE tpHand,
631 CSSM_CL_HANDLE clHand,
632 CSSM_CSP_HANDLE cspHand,
633 BlobList &certs,
634 BlobList &roots,
635 CSSM_BOOL useSystemAnchors,
636 CSSM_BOOL leafCertIsCA,
637 CSSM_BOOL allowExpiredRoot,
638 CertVerifyPolicy vfyPolicy,
639 const char *sslHost, // optional, SSL policy
640 CSSM_BOOL sslClient, // normally server side
641 const char *senderEmail, // optional, SMIME
642 CE_KeyUsage intendedKeyUse, // optional, SMIME only
643 const char *expectedErrStr,// e.g.,
644 // "CSSMERR_APPLETP_CRL_NOT_TRUSTED"
645
646 /*
647 * expected per-cert errors
648 * format is certNum:errorString
649 * e.g., "1:CSSMERR_APPLETP_CRL_NOT_TRUSTED"
650 */
651 unsigned numCertErrors,
652 const char **certErrors, // per-cert status
653
654 /*
655 * Expected per-cert status (CSSM_TP_APPLE_EVIDENCE_INFO.StatusBits)
656 * format is certNum:status_in_hex
657 * e.g., "1:0x18", leading 0x optional
658 */
659 unsigned numCertStatus,
660 const char **certStatus,
661 CSSM_BOOL useTrustSettings,
662 CSSM_BOOL quiet,
663 CSSM_BOOL verbose)
664 {
665 CertVerifyArgs vfyArgs;
666 memset(&vfyArgs, 0, sizeof(vfyArgs));
667 vfyArgs.version = CERT_VFY_ARGS_VERS;
668 vfyArgs.tpHand = tpHand;
669 vfyArgs.clHand = clHand;
670 vfyArgs.cspHand = cspHand;
671 vfyArgs.certs = &certs;
672 vfyArgs.roots = &roots;
673 vfyArgs.useSystemAnchors = useSystemAnchors;
674 vfyArgs.useTrustSettings = useTrustSettings;
675 vfyArgs.leafCertIsCA = leafCertIsCA;
676 vfyArgs.allowExpiredRoot = allowExpiredRoot;
677 vfyArgs.vfyPolicy = vfyPolicy;
678 vfyArgs.sslHost = sslHost;
679 vfyArgs.sslClient = sslClient;
680 vfyArgs.senderEmail = senderEmail;
681 vfyArgs.intendedKeyUse = intendedKeyUse;
682 vfyArgs.allowUnverified = CSSM_TRUE;
683 vfyArgs.expectedErrStr = expectedErrStr;
684 vfyArgs.numCertErrors = numCertErrors;
685 vfyArgs.certErrors = certErrors;
686 vfyArgs.numCertStatus = numCertStatus;
687 vfyArgs.certStatus = certStatus;
688 vfyArgs.quiet = quiet;
689 vfyArgs.verbose = verbose;
690 return certVerify(&vfyArgs);
691 }
692