1/* 2 * secTrustTime.cpp - measure performance of SecTrust and TP cert verify 3 */ 4 5#include <stdlib.h> 6#include <strings.h> 7#include <stdio.h> 8#include <unistd.h> 9#include <CoreFoundation/CoreFoundation.h> 10#include <Security/Security.h> 11#include <Security/TrustSettingsSchema.h> 12#include <security_cdsa_utils/cuFileIo.h> 13#include <utilLib/common.h> 14#include <clAppUtils/clutils.h> 15#include <clAppUtils/tpUtils.h> 16 17#define LOOPS_DEF 100 18 19const char *certFiles[] = { 20 "keybank_v3.100.cer", "keybank_v3.101.cer", "keybank_v3.102.cer" 21}; 22 23#define NUM_CERTS (sizeof(certFiles) / sizeof(certFiles[0])) 24 25static void usage(char **argv) 26{ 27 printf("usage: %s [options]\n", argv[0]); 28 printf("Options:\n"); 29 printf(" -l loops -- loops; default %d; 0=forever\n", LOOPS_DEF); 30 printf(" -k -- open and hold keychains\n"); 31 printf(" -t -- TP, not SecTrust\n"); 32 printf(" -T -- TP, no Trust Settings\n"); 33 printf(" -n -- don't include root in cert chain\n"); 34 printf(" -K -- set empty KC list\n"); 35 /* etc. */ 36 exit(1); 37} 38 39static SecCertificateRef readCertFile( 40 const char *fileName) 41{ 42 unsigned char *cp = NULL; 43 unsigned len = 0; 44 CSSM_DATA certData; 45 OSStatus ortn; 46 47 if(readFile(fileName, &cp, &len)) { 48 printf("***Error reading file %s\n", fileName); 49 return NULL; 50 } 51 certData.Length = len; 52 certData.Data = cp; 53 SecCertificateRef certRef; 54 55 ortn = SecCertificateCreateFromData(&certData, 56 CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certRef); 57 if(ortn) { 58 cssmPerror("SecCertificateCreateFromData", ortn); 59 return NULL; 60 } 61 free(cp); 62 return certRef; 63} 64 65/* perfrom one cert chain evaluation using SecTrust */ 66static OSStatus doEval( 67 CFArrayRef certArray, 68 SecPolicyRef policyRef, 69 CFArrayRef kcList) 70{ 71 OSStatus ortn; 72 SecTrustRef trustRef; 73 74 ortn = SecTrustCreateWithCertificates(certArray, policyRef, &trustRef); 75 if(ortn) { 76 cssmPerror("SecTrustCreateWithCertificates", ortn); 77 return ortn; 78 } 79 if(kcList) { 80 ortn = SecTrustSetKeychains(trustRef, kcList); 81 if(ortn) { 82 cssmPerror("SecTrustCreateWithCertificates", ortn); 83 return ortn; 84 } 85 } 86 SecTrustResultType secTrustResult; 87 ortn = SecTrustEvaluate(trustRef, &secTrustResult); 88 if(ortn) { 89 cssmPerror("SecTrustEvaluate", ortn); 90 return ortn; 91 } 92 switch(secTrustResult) { 93 case kSecTrustResultProceed: 94 case kSecTrustResultUnspecified: 95 break; 96 default: 97 printf("***Unexpected SecTrustResultType (%d)\n", (int)secTrustResult); 98 ortn = -1; 99 } 100 CFRelease(trustRef); 101 return ortn; 102} 103 104/* cached CSSM anchors - simulate old SecTrustGetCSSMAnchorCertificates() */ 105static CFArrayRef cachedRootArray = NULL; 106static CSSM_DATA *cachedAnchors = NULL; 107static unsigned cachedNumAnchors = 0; 108 109static OSStatus getAnchors( 110 CSSM_DATA **anchors, /* RETURNED */ 111 unsigned *numAnchors) /* RETURNED */ 112{ 113 if(cachedRootArray == NULL) { 114 /* fetch, once */ 115 OSStatus ortn = getSystemAnchors(&cachedRootArray, &cachedAnchors, 116 &cachedNumAnchors); 117 if(ortn) { 118 return ortn; 119 } 120 } 121 *anchors = cachedAnchors; 122 *numAnchors = cachedNumAnchors; 123 return noErr; 124} 125 126/* perfrom one cert chain evaluation using CSSM_TP_CertGroupVerify */ 127static CSSM_RETURN doTpEval( 128 CSSM_TP_HANDLE tpHand, 129 CSSM_CL_HANDLE clHand, 130 CSSM_CSP_HANDLE cspHand, 131 CSSM_DATA_PTR certs, 132 uint32 numCerts, 133 bool useTrustSettings) 134{ 135 CSSM_FIELD policyId; 136 137 policyId.FieldOid = CSSMOID_APPLE_X509_BASIC; 138 policyId.FieldValue.Data = NULL; 139 policyId.FieldValue.Length = 0; 140 141 CSSM_TP_CALLERAUTH_CONTEXT authCtx; 142 memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT)); 143 authCtx.Policy.NumberOfPolicyIds = 1; 144 authCtx.Policy.PolicyIds = &policyId; 145 authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY; 146 if(!useTrustSettings) { 147 OSStatus ortn = getAnchors(&authCtx.AnchorCerts, 148 &authCtx.NumberOfAnchorCerts); 149 if(ortn) { 150 return ortn; 151 } 152 } 153 CSSM_APPLE_TP_ACTION_DATA tpAction; 154 tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION; 155 if(useTrustSettings) { 156 tpAction.ActionFlags = CSSM_TP_ACTION_TRUST_SETTINGS; 157 } 158 else { 159 tpAction.ActionFlags = 0; 160 } 161 162 CSSM_TP_VERIFY_CONTEXT vfyCtx; 163 memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT)); 164 vfyCtx.ActionData.Data = (uint8 *)&tpAction; 165 vfyCtx.ActionData.Length = sizeof(tpAction); 166 vfyCtx.Action = CSSM_TP_ACTION_DEFAULT; 167 vfyCtx.Cred = &authCtx; 168 169 CSSM_CERTGROUP cssmCerts; 170 cssmCerts.CertType = CSSM_CERT_X_509v3; 171 cssmCerts.CertEncoding = CSSM_CERT_ENCODING_DER; 172 cssmCerts.NumCerts = numCerts; 173 cssmCerts.GroupList.CertList = certs; 174 cssmCerts.CertGroupType = CSSM_CERTGROUP_DATA; 175 176 CSSM_RETURN crtn = CSSM_TP_CertGroupVerify(tpHand, clHand, cspHand, 177 &cssmCerts, 178 &vfyCtx, 179 NULL); /* no results */ 180 if(crtn) { 181 cssmPerror("CSSM_TP_CertGroupVerify", crtn); 182 } 183 return crtn; 184} 185 186int main(int argc, char **argv) 187{ 188 unsigned dex; 189 CSSM_RETURN crtn; 190 191 /* common SecTrust args */ 192 CFMutableArrayRef kcList = NULL; 193 CFMutableArrayRef certArray = NULL; 194 SecPolicyRef policyRef = NULL; 195 unsigned numCerts = NUM_CERTS; 196 CFArrayRef emptyKCList = NULL; 197 198 /* common TP args */ 199 CSSM_TP_HANDLE tpHand; 200 CSSM_CL_HANDLE clHand; 201 CSSM_CSP_HANDLE cspHand; 202 CSSM_DATA cssmCerts[NUM_CERTS]; 203 204 /* user-spec'd variables */ 205 unsigned loops = LOOPS_DEF; 206 bool holdKeychains = false; /* hold references to KC list during operation */ 207 bool useTp = false; /* TP, not SecTrust */ 208 bool useTrustSettings = true; /* TP w/TrustSettings; false = old school TP way */ 209 bool noRoot = false; /* don't include root in chain to be verified */ 210 bool emptyList = false; /* SecTrust only: specify empty KC list */ 211 212 extern char *optarg; 213 int arg; 214 while ((arg = getopt(argc, argv, "l:ktTnKh")) != -1) { 215 switch (arg) { 216 case 'l': 217 loops = atoi(optarg); 218 break; 219 case 'k': 220 holdKeychains = true; 221 break; 222 case 't': 223 useTp = true; 224 break; 225 case 'T': 226 useTp = true; 227 useTrustSettings = false; 228 break; 229 case 'n': 230 numCerts--; 231 noRoot = true; 232 break; 233 case 'K': 234 emptyList = true; 235 emptyKCList = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); 236 break; 237 case 'h': 238 usage(argv); 239 } 240 } 241 if(optind != argc) { 242 usage(argv); 243 } 244 245 /* gather certs to verify */ 246 certArray = CFArrayCreateMutable(NULL, 3, &kCFTypeArrayCallBacks); 247 for(dex=0; dex<numCerts; dex++) { 248 SecCertificateRef certRef = readCertFile(certFiles[dex]); 249 if(certRef == NULL) { 250 exit(1); 251 } 252 CFArrayInsertValueAtIndex(certArray, dex, certRef); 253 CFRelease(certRef); 254 } 255 256 /* prepare for one method or another */ 257 if(useTp) { 258 for(dex=0; dex<numCerts; dex++) { 259 crtn = SecCertificateGetData( 260 (SecCertificateRef)CFArrayGetValueAtIndex(certArray, dex), 261 &cssmCerts[dex]); 262 if(crtn) { 263 cssmPerror("SecCertificateGetData", crtn); 264 exit(1); 265 } 266 } 267 tpHand = tpStartup(); 268 clHand = clStartup(); 269 cspHand = cspStartup(); 270 } 271 else { 272 /* cook up reusable policy object */ 273 SecPolicySearchRef policySearch = NULL; 274 OSStatus ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, 275 &CSSMOID_APPLE_X509_BASIC, 276 NULL, // policy opts 277 &policySearch); 278 if(ortn) { 279 cssmPerror("SecPolicySearchCreate", ortn); 280 exit(1); 281 } 282 ortn = SecPolicySearchCopyNext(policySearch, &policyRef); 283 if(ortn) { 284 cssmPerror("SecPolicySearchCopyNext", ortn); 285 exit(1); 286 } 287 CFRelease(policySearch); 288 289 if(holdKeychains) { 290 /* the standard keychains */ 291 ortn = SecKeychainCopySearchList((CFArrayRef *)&kcList); 292 if(ortn) { 293 cssmPerror("SecKeychainCopySearchList", ortn); 294 exit(1); 295 } 296 297 /* plus the ones TrustSettings needs */ 298 SecKeychainRef rootKc; 299 ortn = SecKeychainOpen(SYSTEM_ROOT_STORE_PATH, &rootKc); 300 if(ortn) { 301 cssmPerror("SecKeychainOpen", ortn); 302 exit(1); 303 } 304 CFArrayAppendValue(kcList, rootKc); 305 CFRelease(rootKc); 306 } 307 } 308 309 CFAbsoluteTime startTimeFirst; 310 CFAbsoluteTime endTimeFirst; 311 CFAbsoluteTime startTimeMulti; 312 CFAbsoluteTime endTimeMulti; 313 314 /* print a banner describing current test parameters */ 315 printf("Starting test: mode = "); 316 if(useTp) { 317 if(useTrustSettings) { 318 printf("TP w/TrustSettings"); 319 } 320 else { 321 printf("TP w/o TrustSettings"); 322 } 323 } 324 else { 325 printf("SecTrust"); 326 if(holdKeychains) { 327 printf("; hold KC refs"); 328 } 329 if(emptyList) { 330 printf("; empty KC list"); 331 } 332 } 333 if(noRoot) { 334 printf("; no root in input certs\n"); 335 } 336 else { 337 printf("\n"); 338 } 339 340 /* GO */ 341 startTimeFirst = CFAbsoluteTimeGetCurrent(); 342 if(useTp) { 343 if(doTpEval(tpHand, clHand, cspHand, cssmCerts, numCerts, 344 useTrustSettings)) { 345 exit(1); 346 } 347 endTimeFirst = CFAbsoluteTimeGetCurrent(); 348 349 startTimeMulti = CFAbsoluteTimeGetCurrent(); 350 for(dex=0; dex<loops; dex++) { 351 if(doTpEval(tpHand, clHand, cspHand, cssmCerts, numCerts, 352 useTrustSettings)) { 353 exit(1); 354 } 355 } 356 } 357 else { 358 if(doEval(certArray, policyRef, emptyKCList)) { 359 exit(1); 360 } 361 endTimeFirst = CFAbsoluteTimeGetCurrent(); 362 363 startTimeMulti = CFAbsoluteTimeGetCurrent(); 364 for(dex=0; dex<loops; dex++) { 365 if(doEval(certArray, policyRef, emptyKCList)) { 366 exit(1); 367 } 368 } 369 } 370 endTimeMulti = CFAbsoluteTimeGetCurrent(); 371 CFTimeInterval elapsed = endTimeMulti - startTimeMulti; 372 373 printf("First eval = %4.1f ms\n", (endTimeFirst - startTimeFirst) * 1000.0); 374 printf("Next evals = %4.2f ms/op (%f s total for %u loops)\n", 375 elapsed * 1000.0 / loops, elapsed, loops); 376 377 return 0; 378} 379