1/* 2 * Copyright (c) 2001-2003,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please 7 * obtain a copy of the License at http://www.apple.com/publicsource and 8 * read it before using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 12 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 13 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 15 * Please see the License for the specific language governing rights and 16 * limitations under the License. 17 */ 18 19/* 20 File: cuCdsaUtils.cpp 21 22 Description: common CDSA access utilities 23 24 Author: dmitch 25*/ 26 27#include "cuCdsaUtils.h" 28#include <stdlib.h> 29#include <stdio.h> 30#include <Security/SecCertificate.h> 31#include <Security/cssmapple.h> /* for cssmPerror() */ 32#include <Security/oidsalg.h> 33#include <Security/TrustSettingsSchema.h> 34#include <strings.h> 35 36static CSSM_VERSION vers = {2, 0}; 37static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; 38 39/* 40 * Standard app-level memory functions required by CDSA. 41 */ 42void * cuAppMalloc (CSSM_SIZE size, void *allocRef) { 43 return( malloc(size) ); 44} 45 46void cuAppFree (void *mem_ptr, void *allocRef) { 47 free(mem_ptr); 48 return; 49} 50 51void * cuAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef) { 52 return( realloc( ptr, size ) ); 53} 54 55void * cuAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef) { 56 return( calloc( num, size ) ); 57} 58 59static CSSM_API_MEMORY_FUNCS memFuncs = { 60 cuAppMalloc, 61 cuAppFree, 62 cuAppRealloc, 63 cuAppCalloc, 64 NULL 65 }; 66 67CSSM_BOOL cuCompareCssmData(const CSSM_DATA *d1, 68 const CSSM_DATA *d2) 69{ 70 if(d1->Length != d2->Length) { 71 return CSSM_FALSE; 72 } 73 if(memcmp(d1->Data, d2->Data, d1->Length)) { 74 return CSSM_FALSE; 75 } 76 return CSSM_TRUE; 77} 78 79/* 80 * Init CSSM; returns CSSM_FALSE on error. Reusable. 81 */ 82static CSSM_BOOL cssmInitd = CSSM_FALSE; 83 84CSSM_BOOL cuCssmStartup() 85{ 86 CSSM_RETURN crtn; 87 CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; 88 89 if(cssmInitd) { 90 return CSSM_TRUE; 91 } 92 crtn = CSSM_Init (&vers, 93 CSSM_PRIVILEGE_SCOPE_NONE, 94 &testGuid, 95 CSSM_KEY_HIERARCHY_NONE, 96 &pvcPolicy, 97 NULL /* reserved */); 98 if(crtn != CSSM_OK) 99 { 100 cuPrintError("CSSM_Init", crtn); 101 return CSSM_FALSE; 102 } 103 else { 104 cssmInitd = CSSM_TRUE; 105 return CSSM_TRUE; 106 } 107} 108 109/* 110 * Attach to CSP. Returns zero on error. 111 */ 112CSSM_CSP_HANDLE cuCspStartup( 113 CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL 114{ 115 CSSM_CSP_HANDLE cspHand; 116 CSSM_RETURN crtn; 117 const CSSM_GUID *guid; 118 119 /* common CSSM init */ 120 if(cuCssmStartup() == CSSM_FALSE) { 121 return 0; 122 } 123 if(bareCsp) { 124 guid = &gGuidAppleCSP; 125 } 126 else { 127 guid = &gGuidAppleCSPDL; 128 } 129 crtn = CSSM_ModuleLoad(guid, 130 CSSM_KEY_HIERARCHY_NONE, 131 NULL, // eventHandler 132 NULL); // AppNotifyCallbackCtx 133 if(crtn) { 134 cuPrintError("CSSM_ModuleLoad()", crtn); 135 return 0; 136 } 137 crtn = CSSM_ModuleAttach (guid, 138 &vers, 139 &memFuncs, // memFuncs 140 0, // SubserviceID 141 CSSM_SERVICE_CSP, 142 0, // AttachFlags 143 CSSM_KEY_HIERARCHY_NONE, 144 NULL, // FunctionTable 145 0, // NumFuncTable 146 NULL, // reserved 147 &cspHand); 148 if(crtn) { 149 cuPrintError("CSSM_ModuleAttach()", crtn); 150 return 0; 151 } 152 return cspHand; 153} 154 155/* Attach to DL side of CSPDL */ 156CSSM_DL_HANDLE cuDlStartup() 157{ 158 CSSM_DL_HANDLE dlHand = 0; 159 CSSM_RETURN crtn; 160 161 if(cuCssmStartup() == CSSM_FALSE) { 162 return 0; 163 } 164 crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL, 165 CSSM_KEY_HIERARCHY_NONE, 166 NULL, // eventHandler 167 NULL); // AppNotifyCallbackCtx 168 if(crtn) { 169 cuPrintError("CSSM_ModuleLoad(Apple CSPDL)", crtn); 170 return 0; 171 } 172 crtn = CSSM_ModuleAttach (&gGuidAppleCSPDL, 173 &vers, 174 &memFuncs, // memFuncs 175 0, // SubserviceID 176 CSSM_SERVICE_DL, 177 0, // AttachFlags 178 CSSM_KEY_HIERARCHY_NONE, 179 NULL, // FunctionTable 180 0, // NumFuncTable 181 NULL, // reserved 182 &dlHand); 183 if(crtn) { 184 cuPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn); 185 return 0; 186 } 187 return dlHand; 188} 189 190CSSM_CL_HANDLE cuClStartup() 191{ 192 CSSM_CL_HANDLE clHand; 193 CSSM_RETURN crtn; 194 195 if(cuCssmStartup() == CSSM_FALSE) { 196 return 0; 197 } 198 crtn = CSSM_ModuleLoad(&gGuidAppleX509CL, 199 CSSM_KEY_HIERARCHY_NONE, 200 NULL, // eventHandler 201 NULL); // AppNotifyCallbackCtx 202 if(crtn) { 203 cuPrintError("CSSM_ModuleLoad(AppleCL)", crtn); 204 return 0; 205 } 206 crtn = CSSM_ModuleAttach (&gGuidAppleX509CL, 207 &vers, 208 &memFuncs, // memFuncs 209 0, // SubserviceID 210 CSSM_SERVICE_CL, // SubserviceFlags - Where is this used? 211 0, // AttachFlags 212 CSSM_KEY_HIERARCHY_NONE, 213 NULL, // FunctionTable 214 0, // NumFuncTable 215 NULL, // reserved 216 &clHand); 217 if(crtn) { 218 cuPrintError("CSSM_ModuleAttach(AppleCL)", crtn); 219 return 0; 220 } 221 else { 222 return clHand; 223 } 224} 225 226CSSM_TP_HANDLE cuTpStartup() 227{ 228 CSSM_TP_HANDLE tpHand; 229 CSSM_RETURN crtn; 230 231 if(cuCssmStartup() == CSSM_FALSE) { 232 return 0; 233 } 234 crtn = CSSM_ModuleLoad(&gGuidAppleX509TP, 235 CSSM_KEY_HIERARCHY_NONE, 236 NULL, // eventHandler 237 NULL); // AppNotifyCallbackCtx 238 if(crtn) { 239 cuPrintError("CSSM_ModuleLoad(AppleTP)", crtn); 240 return 0; 241 } 242 crtn = CSSM_ModuleAttach (&gGuidAppleX509TP, 243 &vers, 244 &memFuncs, // memFuncs 245 0, // SubserviceID 246 CSSM_SERVICE_TP, // SubserviceFlags 247 0, // AttachFlags 248 CSSM_KEY_HIERARCHY_NONE, 249 NULL, // FunctionTable 250 0, // NumFuncTable 251 NULL, // reserved 252 &tpHand); 253 if(crtn) { 254 cuPrintError("CSSM_ModuleAttach(AppleTP)", crtn); 255 return 0; 256 } 257 else { 258 return tpHand; 259 } 260} 261 262/* detach and unload */ 263CSSM_RETURN cuCspDetachUnload( 264 CSSM_CSP_HANDLE cspHand, 265 CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL 266{ 267 CSSM_RETURN crtn = CSSM_ModuleDetach(cspHand); 268 if(crtn) { 269 return crtn; 270 } 271 const CSSM_GUID *guid; 272 if(bareCsp) { 273 guid = &gGuidAppleCSP; 274 } 275 else { 276 guid = &gGuidAppleCSPDL; 277 } 278 return CSSM_ModuleUnload(guid, NULL, NULL); 279} 280 281CSSM_RETURN cuClDetachUnload( 282 CSSM_CL_HANDLE clHand) 283{ 284 CSSM_RETURN crtn = CSSM_ModuleDetach(clHand); 285 if(crtn) { 286 return crtn; 287 } 288 return CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); 289 290} 291 292CSSM_RETURN cuDlDetachUnload( 293 CSSM_DL_HANDLE dlHand) 294{ 295 CSSM_RETURN crtn = CSSM_ModuleDetach(dlHand); 296 if(crtn) { 297 return crtn; 298 } 299 return CSSM_ModuleUnload(&gGuidAppleCSPDL, NULL, NULL); 300 301} 302CSSM_RETURN cuTpDetachUnload( 303 CSSM_TP_HANDLE tpHand) 304{ 305 CSSM_RETURN crtn = CSSM_ModuleDetach(tpHand); 306 if(crtn) { 307 return crtn; 308 } 309 return CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL); 310 311} 312 313/* 314 * open a DB, ensure it's empty. 315 */ 316CSSM_DB_HANDLE cuDbStartup( 317 CSSM_DL_HANDLE dlHand, // from dlStartup() 318 const char *dbName) 319{ 320 CSSM_DB_HANDLE dbHand = 0; 321 CSSM_RETURN crtn; 322 CSSM_DBINFO dbInfo; 323 324 /* first delete possible existing DB, ignore error */ 325 crtn = CSSM_DL_DbDelete(dlHand, dbName, NULL, NULL); 326 switch(crtn) { 327 /* only allowed error is "no such file" */ 328 case CSSM_OK: 329 case CSSMERR_DL_DATASTORE_DOESNOT_EXIST: 330 break; 331 default: 332 cuPrintError("CSSM_DL_DbDelete", crtn); 333 return 0; 334 } 335 336 memset(&dbInfo, 0, sizeof(CSSM_DBINFO)); 337 338 /* now create it */ 339 crtn = CSSM_DL_DbCreate(dlHand, 340 dbName, 341 NULL, // DbLocation 342 &dbInfo, 343 // &Security::KeychainCore::Schema::DBInfo, 344 CSSM_DB_ACCESS_PRIVILEGED, 345 NULL, // CredAndAclEntry 346 NULL, // OpenParameters 347 &dbHand); 348 if(crtn) { 349 cuPrintError("CSSM_DL_DbCreate", crtn); 350 } 351 return dbHand; 352} 353 354/* 355 * Attach to existing DB or create an empty new one. 356 */ 357CSSM_DB_HANDLE cuDbStartupByName(CSSM_DL_HANDLE dlHand, 358 char *dbName, 359 CSSM_BOOL doCreate, 360 CSSM_BOOL quiet) 361{ 362 CSSM_RETURN crtn; 363 CSSM_DB_HANDLE dbHand; 364 365 /* try open existing DB in either case */ 366 367 crtn = CSSM_DL_DbOpen(dlHand, 368 dbName, 369 NULL, // DbLocation 370 CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, 371 NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred 372 NULL, // void *OpenParameters 373 &dbHand); 374 if(crtn == CSSM_OK) { 375 return dbHand; 376 } 377 if(!doCreate) { 378 if(!quiet) { 379 printf("***no such data base (%s)\n", dbName); 380 cuPrintError("CSSM_DL_DbOpen", crtn); 381 } 382 return 0; 383 } 384 /* have to create one */ 385 return cuDbStartup(dlHand, dbName); 386} 387 388/* 389 * Given a context specified via a CSSM_CC_HANDLE, add a new 390 * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, 391 * AttributeLength, and an untyped pointer. 392 */ 393static 394CSSM_RETURN cuAddContextAttribute(CSSM_CC_HANDLE CCHandle, 395 uint32 AttributeType, 396 uint32 AttributeLength, 397 const void *AttributePtr) 398{ 399 CSSM_CONTEXT_ATTRIBUTE newAttr; 400 CSSM_RETURN crtn; 401 402 newAttr.AttributeType = AttributeType; 403 newAttr.AttributeLength = AttributeLength; 404 newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; 405 crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); 406 if(crtn) { 407 cuPrintError("CSSM_UpdateContextAttributes", crtn); 408 } 409 return crtn; 410} 411 412 413/* 414 * Derive symmetric key. 415 * Note in the X CSP, we never return an IV. 416 */ 417CSSM_RETURN cuCspDeriveKey(CSSM_CSP_HANDLE cspHand, 418 uint32 keyAlg, // CSSM_ALGID_RC5, etc. 419 const char *keyLabel, 420 unsigned keyLabelLen, 421 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. 422 uint32 keySizeInBits, 423 CSSM_DATA_PTR password, // in PKCS-5 lingo 424 CSSM_DATA_PTR salt, // ditto 425 uint32 iterationCnt, // ditto 426 CSSM_KEY_PTR key) 427{ 428 CSSM_RETURN crtn; 429 CSSM_CC_HANDLE ccHand; 430 uint32 keyAttr; 431 CSSM_DATA dummyLabel; 432 CSSM_PKCS5_PBKDF2_PARAMS pbeParams; 433 CSSM_DATA pbeData; 434 CSSM_ACCESS_CREDENTIALS creds; 435 436 memset(key, 0, sizeof(CSSM_KEY)); 437 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); 438 crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, 439 CSSM_ALGID_PKCS5_PBKDF2, 440 keyAlg, 441 keySizeInBits, 442 &creds, 443 NULL, // BaseKey 444 iterationCnt, 445 salt, 446 NULL, // seed 447 &ccHand); 448 if(crtn) { 449 cuPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn); 450 return crtn; 451 } 452 keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF | 453 CSSM_KEYATTR_SENSITIVE; 454 dummyLabel.Length = keyLabelLen; 455 dummyLabel.Data = (uint8 *)keyLabel; 456 457 /* passing in password is pretty strange....*/ 458 pbeParams.Passphrase = *password; 459 pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; 460 pbeData.Data = (uint8 *)&pbeParams; 461 pbeData.Length = sizeof(pbeParams); 462 crtn = CSSM_DeriveKey(ccHand, 463 &pbeData, 464 keyUsage, 465 keyAttr, 466 &dummyLabel, 467 NULL, // cred and acl 468 key); 469 if(crtn) { 470 cuPrintError("CSSM_DeriveKey", crtn); 471 return crtn; 472 } 473 crtn = CSSM_DeleteContext(ccHand); 474 if(crtn) { 475 cuPrintError("CSSM_DeleteContext", crtn); 476 } 477 return crtn; 478} 479 480/* 481 * Generate key pair of arbitrary algorithm. 482 */ 483 484/* CSP DL currently does not perform DSA generate params; let CSP do it implicitly */ 485#define DO_DSA_GEN_PARAMS 0 486 487CSSM_RETURN cuCspGenKeyPair(CSSM_CSP_HANDLE cspHand, 488 CSSM_DL_DB_HANDLE *dlDbHand, // optional 489 uint32 algorithm, 490 const char *keyLabel, 491 unsigned keyLabelLen, 492 uint32 keySize, // in bits 493 CSSM_KEY_PTR pubKey, // mallocd by caller 494 CSSM_KEYUSE pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. 495 CSSM_KEYATTR_FLAGS pubAttrs, // CSSM_KEYATTR_EXTRACTABLE, etc. 496 CSSM_KEY_PTR privKey, // mallocd by caller 497 CSSM_KEYUSE privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. 498 CSSM_KEYATTR_FLAGS privAttrs) // CSSM_KEYATTR_EXTRACTABLE, etc. 499{ 500 CSSM_RETURN crtn; 501 CSSM_RETURN ocrtn; 502 CSSM_CC_HANDLE ccHand; 503 CSSM_DATA keyLabelData; 504 505 keyLabelData.Data = (uint8 *)keyLabel, 506 keyLabelData.Length = keyLabelLen; 507 memset(pubKey, 0, sizeof(CSSM_KEY)); 508 memset(privKey, 0, sizeof(CSSM_KEY)); 509 510 crtn = CSSM_CSP_CreateKeyGenContext(cspHand, 511 algorithm, 512 keySize, 513 NULL, // Seed 514 NULL, // Salt 515 NULL, // StartDate 516 NULL, // EndDate 517 NULL, // Params 518 &ccHand); 519 if(crtn) { 520 cuPrintError("CSSM_CSP_CreateKeyGenContext", crtn); 521 return crtn; 522 } 523 524 /* post-context-create algorithm-specific stuff */ 525 switch(algorithm) { 526 #if DO_DSA_GEN_PARAMS 527 case CSSM_ALGID_DSA: 528 /* 529 * extra step - generate params - this just adds some 530 * info to the context 531 */ 532 { 533 CSSM_DATA dummy = {0, NULL}; 534 crtn = CSSM_GenerateAlgorithmParams(ccHand, 535 keySize, &dummy); 536 if(crtn) { 537 cuPrintError("CSSM_GenerateAlgorithmParams", crtn); 538 CSSM_DeleteContext(ccHand); 539 return crtn; 540 } 541 cuAppFree(dummy.Data, NULL); 542 } 543 break; 544 #endif /* DO_DSA_GEN_PARAMS */ 545 default: 546 break; 547 } 548 549 /* optionally specify DL/DB storage location */ 550 if(dlDbHand) { 551 crtn = cuAddContextAttribute(ccHand, 552 CSSM_ATTRIBUTE_DL_DB_HANDLE, 553 sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE), 554 dlDbHand); 555 if(crtn) { 556 CSSM_DeleteContext(ccHand); 557 return crtn; 558 } 559 } 560 ocrtn = CSSM_GenerateKeyPair(ccHand, 561 pubKeyUsage, 562 pubAttrs, 563 &keyLabelData, 564 pubKey, 565 privKeyUsage, 566 privAttrs, 567 &keyLabelData, // same labels 568 NULL, // CredAndAclEntry 569 privKey); 570 if(ocrtn) { 571 cuPrintError("CSSM_GenerateKeyPair", ocrtn); 572 } 573 crtn = CSSM_DeleteContext(ccHand); 574 if(crtn) { 575 cuPrintError("CSSM_DeleteContext", crtn); 576 if(ocrtn == CSSM_OK) { 577 /* error on CSSM_GenerateKeyPair takes precedence */ 578 ocrtn = crtn; 579 } 580 } 581 return ocrtn; 582} 583 584 585/* 586 * Add a certificate to an open Keychain. 587 */ 588CSSM_RETURN cuAddCertToKC( 589 SecKeychainRef keychain, 590 const CSSM_DATA *cert, 591 CSSM_CERT_TYPE certType, 592 CSSM_CERT_ENCODING certEncoding, 593 const char *printName, // C string 594 const CSSM_DATA *keyLabel) // ?? 595{ 596 SecCertificateRef certificate; 597 598 OSStatus rslt = SecCertificateCreateFromData(cert, certType, certEncoding, &certificate); 599 if (!rslt) 600 { 601 rslt = SecCertificateAddToKeychain(certificate, keychain); 602 CFRelease(certificate); 603 } 604 605 return rslt; 606} 607 608/* 609 * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to an 610 * unsigned. 611 */ 612unsigned cuDER_ToInt(const CSSM_DATA *DER_Data) 613{ 614 uint32 rtn = 0; 615 unsigned i = 0; 616 617 while(i < DER_Data->Length) { 618 rtn |= DER_Data->Data[i]; 619 if(++i == DER_Data->Length) { 620 break; 621 } 622 rtn <<= 8; 623 } 624 return rtn; 625} 626 627/* 628 * Log CSSM error. 629 */ 630void cuPrintError(const char *op, CSSM_RETURN err) 631{ 632 cssmPerror(op, err); 633} 634 635/* 636 * Verify a CRL against system anchors and intermediate certs. 637 */ 638CSSM_RETURN cuCrlVerify( 639 CSSM_TP_HANDLE tpHand, 640 CSSM_CL_HANDLE clHand, 641 CSSM_CSP_HANDLE cspHand, 642 const CSSM_DATA *crlData, 643 CSSM_DL_DB_HANDLE_PTR certKeychain, // intermediate certs 644 const CSSM_DATA *anchors, // optional - if NULL, use Trust Settings 645 uint32 anchorCount) 646{ 647 /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */ 648 CSSM_TP_VERIFY_CONTEXT vfyCtx; 649 CSSM_TP_CALLERAUTH_CONTEXT authCtx; 650 651 memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT)); 652 memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT)); 653 654 /* CSSM_TP_CALLERAUTH_CONTEXT components */ 655 /* 656 typedef struct cssm_tp_callerauth_context { 657 CSSM_TP_POLICYINFO Policy; 658 CSSM_TIMESTRING VerifyTime; 659 CSSM_TP_STOP_ON VerificationAbortOn; 660 CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert; 661 uint32 NumberOfAnchorCerts; 662 CSSM_DATA_PTR AnchorCerts; 663 CSSM_DL_DB_LIST_PTR DBList; 664 CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials; 665 } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR; 666 */ 667 CSSM_FIELD policyId; 668 CSSM_APPLE_TP_CRL_OPTIONS crlOpts; 669 policyId.FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL; 670 policyId.FieldValue.Data = (uint8 *)&crlOpts; 671 policyId.FieldValue.Length = sizeof(crlOpts); 672 crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; 673 /* perhaps this should be user-specifiable */ 674 crlOpts.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET; 675 crlOpts.crlStore = NULL; 676 677 authCtx.Policy.NumberOfPolicyIds = 1; 678 authCtx.Policy.PolicyIds = &policyId; 679 authCtx.Policy.PolicyControl = NULL; 680 681 authCtx.VerifyTime = NULL; 682 authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY; 683 authCtx.CallbackWithVerifiedCert = NULL; 684 685 /* anchors */ 686 authCtx.NumberOfAnchorCerts = anchorCount; 687 authCtx.AnchorCerts = const_cast<CSSM_DATA_PTR>(anchors); 688 689 /* DBList of intermediate certs, plus possible System.keychain and 690 * system roots */ 691 CSSM_DL_DB_HANDLE handles[3]; 692 unsigned numDbs = 0; 693 CSSM_DL_HANDLE dlHand = 0; 694 if(certKeychain != NULL) { 695 handles[0] = *certKeychain; 696 numDbs++; 697 } 698 if(anchors == NULL) { 699 /* Trust Settings requires two more DBs */ 700 if(numDbs == 0) { 701 /* new DL handle */ 702 dlHand = cuDlStartup(); 703 handles[numDbs].DLHandle = dlHand; 704 handles[numDbs + 1].DLHandle = dlHand; 705 } 706 else { 707 /* use the same one passed in for certKeychain */ 708 handles[numDbs].DLHandle = handles[0].DLHandle; 709 handles[numDbs + 1].DLHandle = handles[0].DLHandle; 710 } 711 handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle, 712 (char*) ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); 713 numDbs++; 714 715 handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle, 716 (char*) SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); 717 numDbs++; 718 } 719 CSSM_DL_DB_LIST dlDbList; 720 dlDbList.DLDBHandle = handles; 721 dlDbList.NumHandles = numDbs; 722 723 authCtx.DBList = &dlDbList; 724 authCtx.CallerCredentials = NULL; 725 726 /* CSSM_TP_VERIFY_CONTEXT */ 727 vfyCtx.ActionData.Data = NULL; 728 vfyCtx.ActionData.Length = 0; 729 vfyCtx.Action = CSSM_TP_ACTION_DEFAULT; 730 vfyCtx.Cred = &authCtx; 731 732 /* CSSM_APPLE_TP_ACTION_DATA */ 733 CSSM_APPLE_TP_ACTION_DATA tpAction; 734 if(anchors == NULL) { 735 /* enable Trust Settings */ 736 tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION; 737 tpAction.ActionFlags = CSSM_TP_ACTION_TRUST_SETTINGS; 738 vfyCtx.ActionData.Data = (uint8 *)&tpAction; 739 vfyCtx.ActionData.Length = sizeof(tpAction); 740 } 741 742 /* cook up CSSM_ENCODED_CRL */ 743 CSSM_ENCODED_CRL encCrl; 744 encCrl.CrlType = CSSM_CRL_TYPE_X_509v2; 745 encCrl.CrlEncoding = CSSM_CRL_ENCODING_DER; 746 encCrl.CrlBlob = *crlData; 747 748 /* CDSA API requires a SignerCertGroup; for us, all the certs are in 749 * certKeyChain... */ 750 CSSM_CERTGROUP certGroup; 751 certGroup.CertType = CSSM_CERT_X_509v1; 752 certGroup.CertEncoding = CSSM_CERT_ENCODING_DER; 753 certGroup.NumCerts = 0; 754 certGroup.GroupList.CertList = NULL; 755 certGroup.CertGroupType = CSSM_CERTGROUP_DATA; 756 757 CSSM_RETURN crtn = CSSM_TP_CrlVerify(tpHand, 758 clHand, 759 cspHand, 760 &encCrl, 761 &certGroup, 762 &vfyCtx, 763 NULL); // RevokerVerifyResult 764 if(crtn) { 765 cuPrintError("CSSM_TP_CrlVerify", crtn); 766 } 767 if(anchors == NULL) { 768 /* close the DBs and maybe the DL we opened */ 769 unsigned dexToClose = (certKeychain == NULL) ? 0 : 1; 770 CSSM_DL_DbClose(handles[dexToClose++]); 771 CSSM_DL_DbClose(handles[dexToClose]); 772 if(dlHand != 0) { 773 cuDlDetachUnload(dlHand); 774 } 775 } 776 return crtn; 777} 778 779