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 21static 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 102static 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 */ 175static 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 201int 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 586unsigned 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 */ 602unsigned 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 */ 629int 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 693