2  * Copyright (c) 2001-2003,2011-2012,2014 Apple Inc. All Rights Reserved. 
   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. 
  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. 
  22         Description: common CDSA access utilities 
  27 #include "cuCdsaUtils.h" 
  30 #include <Security/SecCertificate.h> 
  31 #include <Security/cssmapple.h>                         /* for cssmPerror() */ 
  32 #include <Security/oidsalg.h> 
  33 #include <Security/TrustSettingsSchema.h> 
  36 static CSSM_VERSION vers 
= {2, 0}; 
  37 static const CSSM_GUID testGuid 
= { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; 
  40  * Standard app-level memory functions required by CDSA. 
  42 void * cuAppMalloc (CSSM_SIZE size
, void *allocRef
) { 
  43         return( malloc(size
) ); 
  46 void cuAppFree (void *mem_ptr
, void *allocRef
) { 
  51 void * cuAppRealloc (void *ptr
, CSSM_SIZE size
, void *allocRef
) { 
  52         return( realloc( ptr
, size 
) ); 
  55 void * cuAppCalloc (uint32 num
, CSSM_SIZE size
, void *allocRef
) { 
  56         return( calloc( num
, size 
) ); 
  59 static CSSM_API_MEMORY_FUNCS memFuncs 
= { 
  67 CSSM_BOOL 
cuCompareCssmData(const CSSM_DATA 
*d1
, 
  70         if(d1
->Length 
!= d2
->Length
) { 
  73         if(memcmp(d1
->Data
, d2
->Data
, d1
->Length
)) { 
  80  * Init CSSM; returns CSSM_FALSE on error. Reusable. 
  82 static CSSM_BOOL cssmInitd 
= CSSM_FALSE
; 
  84 CSSM_BOOL 
cuCssmStartup() 
  87     CSSM_PVC_MODE pvcPolicy 
= CSSM_PVC_NONE
; 
  92         crtn 
= CSSM_Init (&vers
,  
  93                 CSSM_PRIVILEGE_SCOPE_NONE
, 
  95                 CSSM_KEY_HIERARCHY_NONE
, 
 100                 cuPrintError("CSSM_Init", crtn
); 
 104                 cssmInitd 
= CSSM_TRUE
; 
 110  * Attach to CSP. Returns zero on error. 
 112 CSSM_CSP_HANDLE 
cuCspStartup( 
 113         CSSM_BOOL bareCsp
)              // true ==> CSP, false ==> CSP/DL 
 115         CSSM_CSP_HANDLE cspHand
; 
 117         const CSSM_GUID 
*guid
; 
 119         /* common CSSM init */ 
 120         if(cuCssmStartup() == CSSM_FALSE
) { 
 124                 guid 
= &gGuidAppleCSP
; 
 127                 guid 
= &gGuidAppleCSPDL
; 
 129         crtn 
= CSSM_ModuleLoad(guid
, 
 130                 CSSM_KEY_HIERARCHY_NONE
, 
 131                 NULL
,                   // eventHandler 
 132                 NULL
);                  // AppNotifyCallbackCtx 
 134                 cuPrintError("CSSM_ModuleLoad()", crtn
); 
 137         crtn 
= CSSM_ModuleAttach (guid
, 
 139                 &memFuncs
,                      // memFuncs 
 143                 CSSM_KEY_HIERARCHY_NONE
, 
 144                 NULL
,                           // FunctionTable 
 149                 cuPrintError("CSSM_ModuleAttach()", crtn
); 
 155 /* Attach to DL side of CSPDL */ 
 156 CSSM_DL_HANDLE 
cuDlStartup() 
 158         CSSM_DL_HANDLE  dlHand 
= 0; 
 161         if(cuCssmStartup() == CSSM_FALSE
) { 
 164         crtn 
= CSSM_ModuleLoad(&gGuidAppleCSPDL
, 
 165                 CSSM_KEY_HIERARCHY_NONE
, 
 166                 NULL
,                   // eventHandler 
 167                 NULL
);                  // AppNotifyCallbackCtx 
 169                 cuPrintError("CSSM_ModuleLoad(Apple CSPDL)", crtn
); 
 172         crtn 
= CSSM_ModuleAttach (&gGuidAppleCSPDL
, 
 174                 &memFuncs
,                      // memFuncs 
 178                 CSSM_KEY_HIERARCHY_NONE
, 
 179                 NULL
,                           // FunctionTable 
 184                 cuPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn
); 
 190 CSSM_CL_HANDLE 
cuClStartup() 
 192         CSSM_CL_HANDLE clHand
; 
 195         if(cuCssmStartup() == CSSM_FALSE
) { 
 198         crtn 
= CSSM_ModuleLoad(&gGuidAppleX509CL
, 
 199                 CSSM_KEY_HIERARCHY_NONE
, 
 200                 NULL
,                   // eventHandler 
 201                 NULL
);                  // AppNotifyCallbackCtx 
 203                 cuPrintError("CSSM_ModuleLoad(AppleCL)", crtn
); 
 206         crtn 
= CSSM_ModuleAttach (&gGuidAppleX509CL
, 
 208                 &memFuncs
,                              // memFuncs 
 210                 CSSM_SERVICE_CL
,                // SubserviceFlags - Where is this used? 
 212                 CSSM_KEY_HIERARCHY_NONE
, 
 213                 NULL
,                                   // FunctionTable 
 218                 cuPrintError("CSSM_ModuleAttach(AppleCL)", crtn
); 
 226 CSSM_TP_HANDLE 
cuTpStartup() 
 228         CSSM_TP_HANDLE tpHand
; 
 231         if(cuCssmStartup() == CSSM_FALSE
) { 
 234         crtn 
= CSSM_ModuleLoad(&gGuidAppleX509TP
, 
 235                 CSSM_KEY_HIERARCHY_NONE
, 
 236                 NULL
,                   // eventHandler 
 237                 NULL
);                  // AppNotifyCallbackCtx 
 239                 cuPrintError("CSSM_ModuleLoad(AppleTP)", crtn
); 
 242         crtn 
= CSSM_ModuleAttach (&gGuidAppleX509TP
, 
 244                 &memFuncs
,                              // memFuncs 
 246                 CSSM_SERVICE_TP
,                // SubserviceFlags 
 248                 CSSM_KEY_HIERARCHY_NONE
, 
 249                 NULL
,                                   // FunctionTable 
 254                 cuPrintError("CSSM_ModuleAttach(AppleTP)", crtn
); 
 262 /* detach and unload */ 
 263 CSSM_RETURN 
cuCspDetachUnload( 
 264         CSSM_CSP_HANDLE cspHand
, 
 265         CSSM_BOOL bareCsp
)                                      // true ==> CSP, false ==> CSP/DL 
 267         CSSM_RETURN crtn 
= CSSM_ModuleDetach(cspHand
); 
 271         const CSSM_GUID 
*guid
; 
 273                 guid 
= &gGuidAppleCSP
; 
 276                 guid 
= &gGuidAppleCSPDL
; 
 278         return CSSM_ModuleUnload(guid
, NULL
, NULL
); 
 281 CSSM_RETURN 
cuClDetachUnload( 
 282         CSSM_CL_HANDLE  clHand
) 
 284         CSSM_RETURN crtn 
= CSSM_ModuleDetach(clHand
); 
 288         return CSSM_ModuleUnload(&gGuidAppleX509CL
, NULL
, NULL
); 
 292 CSSM_RETURN 
cuDlDetachUnload( 
 293         CSSM_DL_HANDLE  dlHand
) 
 295         CSSM_RETURN crtn 
= CSSM_ModuleDetach(dlHand
); 
 299         return CSSM_ModuleUnload(&gGuidAppleCSPDL
, NULL
, NULL
); 
 302 CSSM_RETURN 
cuTpDetachUnload( 
 303         CSSM_TP_HANDLE  tpHand
) 
 305         CSSM_RETURN crtn 
= CSSM_ModuleDetach(tpHand
); 
 309         return CSSM_ModuleUnload(&gGuidAppleX509TP
, NULL
, NULL
); 
 314  * open a DB, ensure it's empty. 
 316 CSSM_DB_HANDLE 
cuDbStartup( 
 317         CSSM_DL_HANDLE          dlHand
,                 // from dlStartup() 
 320         CSSM_DB_HANDLE                          dbHand 
= 0; 
 324         /* first delete possible existing DB, ignore error */ 
 325         crtn 
= CSSM_DL_DbDelete(dlHand
, dbName
, NULL
, NULL
); 
 327                 /* only allowed error is "no such file" */ 
 329                 case CSSMERR_DL_DATASTORE_DOESNOT_EXIST
: 
 332                         cuPrintError("CSSM_DL_DbDelete", crtn
); 
 336         memset(&dbInfo
, 0, sizeof(CSSM_DBINFO
)); 
 339         crtn 
= CSSM_DL_DbCreate(dlHand
,  
 343                 // &Security::KeychainCore::Schema::DBInfo, 
 344                 CSSM_DB_ACCESS_PRIVILEGED
, 
 345                 NULL
,                                           // CredAndAclEntry 
 346                 NULL
,                                           // OpenParameters 
 349                 cuPrintError("CSSM_DL_DbCreate", crtn
); 
 355  * Attach to existing DB or create an empty new one. 
 357 CSSM_DB_HANDLE 
cuDbStartupByName(CSSM_DL_HANDLE dlHand
, 
 363         CSSM_DB_HANDLE  dbHand
; 
 365         /* try open existing DB in either case */ 
 367         crtn 
= CSSM_DL_DbOpen(dlHand
, 
 370                 CSSM_DB_ACCESS_READ 
| CSSM_DB_ACCESS_WRITE
, 
 371                 NULL
,                   // CSSM_ACCESS_CREDENTIALS *AccessCred 
 372                 NULL
,                   // void *OpenParameters 
 374         if(crtn 
== CSSM_OK
) { 
 379                         printf("***no such data base (%s)\n", dbName
); 
 380                         cuPrintError("CSSM_DL_DbOpen", crtn
); 
 384         /* have to create one */ 
 385         return cuDbStartup(dlHand
, dbName
); 
 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. 
 394 CSSM_RETURN 
cuAddContextAttribute(CSSM_CC_HANDLE CCHandle
, 
 395         uint32 AttributeType
, 
 396         uint32 AttributeLength
, 
 397         const void *AttributePtr
) 
 399         CSSM_CONTEXT_ATTRIBUTE          newAttr
;         
 402         newAttr
.AttributeType     
= AttributeType
; 
 403         newAttr
.AttributeLength   
= AttributeLength
; 
 404         newAttr
.Attribute
.Data    
= (CSSM_DATA_PTR
)AttributePtr
; 
 405         crtn 
= CSSM_UpdateContextAttributes(CCHandle
, 1, &newAttr
); 
 407                 cuPrintError("CSSM_UpdateContextAttributes", crtn
); 
 414  * Derive symmetric key. 
 415  * Note in the X CSP, we never return an IV.  
 417 CSSM_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 
 429         CSSM_CC_HANDLE                          ccHand
; 
 431         CSSM_DATA                                       dummyLabel
; 
 432         CSSM_PKCS5_PBKDF2_PARAMS        pbeParams
; 
 434         CSSM_ACCESS_CREDENTIALS         creds
; 
 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
, 
 449                 cuPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn
); 
 452         keyAttr 
= CSSM_KEYATTR_EXTRACTABLE 
| CSSM_KEYATTR_RETURN_REF 
|  
 453                           CSSM_KEYATTR_SENSITIVE
; 
 454         dummyLabel
.Length 
= keyLabelLen
; 
 455         dummyLabel
.Data 
= (uint8 
*)keyLabel
; 
 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
, 
 467                 NULL
,                   // cred and acl 
 470                 cuPrintError("CSSM_DeriveKey", crtn
); 
 473         crtn 
= CSSM_DeleteContext(ccHand
); 
 475                 cuPrintError("CSSM_DeleteContext", crtn
); 
 481  * Generate key pair of arbitrary algorithm.  
 484 /* CSP DL currently does not perform DSA generate params; let CSP do it implicitly */ 
 485 #define DO_DSA_GEN_PARAMS               0 
 487 CSSM_RETURN 
cuCspGenKeyPair(CSSM_CSP_HANDLE cspHand
, 
 488         CSSM_DL_DB_HANDLE 
*dlDbHand
,    // optional 
 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.  
 502         CSSM_CC_HANDLE                  ccHand
; 
 503         CSSM_DATA                               keyLabelData
; 
 505         keyLabelData
.Data        
= (uint8 
*)keyLabel
, 
 506         keyLabelData
.Length      
= keyLabelLen
; 
 507         memset(pubKey
, 0, sizeof(CSSM_KEY
)); 
 508         memset(privKey
, 0, sizeof(CSSM_KEY
)); 
 510         crtn 
= CSSM_CSP_CreateKeyGenContext(cspHand
, 
 520                 cuPrintError("CSSM_CSP_CreateKeyGenContext", crtn
); 
 524         /* post-context-create algorithm-specific stuff */ 
 526                 #if DO_DSA_GEN_PARAMS 
 529                          * extra step - generate params - this just adds some 
 530                          * info to the context 
 533                                 CSSM_DATA dummy 
= {0, NULL
}; 
 534                                 crtn 
= CSSM_GenerateAlgorithmParams(ccHand
,  
 537                                         cuPrintError("CSSM_GenerateAlgorithmParams", crtn
); 
 538                                         CSSM_DeleteContext(ccHand
); 
 541                                 cuAppFree(dummy
.Data
, NULL
); 
 544                 #endif  /* DO_DSA_GEN_PARAMS */ 
 549         /* optionally specify DL/DB storage location */ 
 551                 crtn 
= cuAddContextAttribute(ccHand
,  
 552                         CSSM_ATTRIBUTE_DL_DB_HANDLE
, 
 553                         sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE
), 
 556                         CSSM_DeleteContext(ccHand
); 
 560         ocrtn 
= CSSM_GenerateKeyPair(ccHand
, 
 567                 &keyLabelData
,                  // same labels 
 568                 NULL
,                                   // CredAndAclEntry 
 571                 cuPrintError("CSSM_GenerateKeyPair", ocrtn
); 
 573         crtn 
= CSSM_DeleteContext(ccHand
); 
 575                 cuPrintError("CSSM_DeleteContext", crtn
); 
 576                 if(ocrtn 
== CSSM_OK
) { 
 577                         /* error on CSSM_GenerateKeyPair takes precedence */ 
 586  * Add a certificate to an open Keychain. 
 588 CSSM_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
)              // ?? 
 596         SecCertificateRef certificate
; 
 598         OSStatus rslt 
= SecCertificateCreateFromData(cert
, certType
, certEncoding
, &certificate
); 
 601                 rslt 
= SecCertificateAddToKeychain(certificate
, keychain
); 
 602                 CFRelease(certificate
); 
 609  * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to an 
 612 unsigned cuDER_ToInt(const CSSM_DATA 
*DER_Data
) 
 617         while(i 
< DER_Data
->Length
) { 
 618                 rtn 
|= DER_Data
->Data
[i
]; 
 619                 if(++i 
== DER_Data
->Length
) { 
 630 void cuPrintError(const char *op
, CSSM_RETURN err
) 
 636  * Verify a CRL against system anchors and intermediate certs.  
 638 CSSM_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 
 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
; 
 651         memset(&vfyCtx
, 0, sizeof(CSSM_TP_VERIFY_CONTEXT
)); 
 652         memset(&authCtx
, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT
)); 
 654         /* CSSM_TP_CALLERAUTH_CONTEXT components */ 
 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; 
 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
; 
 677         authCtx
.Policy
.NumberOfPolicyIds 
= 1; 
 678         authCtx
.Policy
.PolicyIds 
= &policyId
; 
 679         authCtx
.Policy
.PolicyControl 
= NULL
; 
 681         authCtx
.VerifyTime 
= NULL
; 
 682         authCtx
.VerificationAbortOn 
= CSSM_TP_STOP_ON_POLICY
; 
 683         authCtx
.CallbackWithVerifiedCert 
= NULL
; 
 686         authCtx
.NumberOfAnchorCerts 
= anchorCount
; 
 687         authCtx
.AnchorCerts 
= const_cast<CSSM_DATA_PTR
>(anchors
); 
 689         /* DBList of intermediate certs, plus possible System.keychain and  
 691         CSSM_DL_DB_HANDLE handles
[3]; 
 693         CSSM_DL_HANDLE dlHand 
= 0; 
 694         if(certKeychain 
!= NULL
) { 
 695                 handles
[0] = *certKeychain
; 
 698         if(anchors 
== NULL
) { 
 699                 /* Trust Settings requires two more DBs */ 
 702                         dlHand 
= cuDlStartup(); 
 703                         handles
[numDbs
].DLHandle 
= dlHand
; 
 704                         handles
[numDbs 
+ 1].DLHandle 
= dlHand
; 
 707                         /* use the same one passed in for certKeychain */ 
 708                         handles
[numDbs
].DLHandle 
= handles
[0].DLHandle
; 
 709                         handles
[numDbs 
+ 1].DLHandle 
= handles
[0].DLHandle
; 
 711                 handles
[numDbs
].DBHandle 
= cuDbStartupByName(handles
[numDbs
].DLHandle
, 
 712                         (char*) ADMIN_CERT_STORE_PATH
, CSSM_FALSE
, CSSM_TRUE
); 
 715                 handles
[numDbs
].DBHandle 
= cuDbStartupByName(handles
[numDbs
].DLHandle
, 
 716                         (char*) SYSTEM_ROOT_STORE_PATH
, CSSM_FALSE
, CSSM_TRUE
); 
 719         CSSM_DL_DB_LIST dlDbList
; 
 720         dlDbList
.DLDBHandle 
= handles
; 
 721         dlDbList
.NumHandles 
= numDbs
; 
 723         authCtx
.DBList 
= &dlDbList
;  
 724         authCtx
.CallerCredentials 
= NULL
; 
 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
; 
 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
); 
 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
; 
 748         /* CDSA API requires a SignerCertGroup; for us, all the certs are in 
 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
; 
 757         CSSM_RETURN crtn 
= CSSM_TP_CrlVerify(tpHand
, 
 763                 NULL
);                  // RevokerVerifyResult 
 765                 cuPrintError("CSSM_TP_CrlVerify", crtn
); 
 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
]); 
 773                         cuDlDetachUnload(dlHand
);