1/* 2 * cmsTime.cpp - measure performance of CMS decode & 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/CMSDecoder.h> 12#include <security_cdsa_utils/cuFileIo.h> 13#include <utilLib/common.h> 14 15#define LOOPS_DEF 100 16#define SIGNED_FILE "noRoot.p7" 17 18static void usage(char **argv) 19{ 20 printf("usage: %s [options]\n", argv[0]); 21 printf("Options:\n"); 22 printf(" -l loops -- loops; default %d; 0=forever\n", LOOPS_DEF); 23 printf(" -i inFile -- input file; default is %s\n", SIGNED_FILE); 24 printf(" -K -- set empty KC list\n"); 25 /* etc. */ 26 exit(1); 27} 28 29/* perform one CMS decode */ 30static OSStatus doDecode( 31 const void *cmsData, 32 size_t cmsDataLen, 33 SecPolicyRef policyRef, 34 CFArrayRef kcArray) /* optional */ 35 36{ 37 OSStatus ortn; 38 CMSDecoderRef cmsDecoder = NULL; 39 40 CMSDecoderCreate(&cmsDecoder); 41 if(kcArray) { 42 ortn = CMSDecoderSetSearchKeychain(cmsDecoder, kcArray); 43 if(ortn) { 44 cssmPerror("CMSDecoderSetSearchKeychain", ortn); 45 return ortn; 46 } 47 } 48 ortn = CMSDecoderUpdateMessage(cmsDecoder, cmsData, cmsDataLen); 49 if(ortn) { 50 cssmPerror("CMSDecoderUpdateMessage", ortn); 51 return ortn; 52 } 53 ortn = CMSDecoderFinalizeMessage(cmsDecoder); 54 if(ortn) { 55 cssmPerror("CMSDecoderFinalizeMessage", ortn); 56 return ortn; 57 } 58 59 CMSSignerStatus signerStatus; 60 ortn = CMSDecoderCopySignerStatus(cmsDecoder, 0, policyRef, true, &signerStatus, NULL, NULL); 61 if(ortn) { 62 cssmPerror("CMSDecoderCopySignerStatus", ortn); 63 return ortn; 64 } 65 if(signerStatus != kCMSSignerValid) { 66 printf("***Bad signerStatus (%d)\n", (int)signerStatus); 67 ortn = -1; 68 } 69 CFRelease(cmsDecoder); 70 return ortn; 71} 72 73int main(int argc, char **argv) 74{ 75 unsigned dex; 76 77 CFArrayRef emptyKCList = NULL; 78 unsigned char *blob = NULL; 79 unsigned blobLen; 80 SecPolicyRef policyRef = NULL; 81 82 /* user-spec'd variables */ 83 unsigned loops = LOOPS_DEF; 84 char *blobFile = SIGNED_FILE; 85 bool emptyList = false; /* specify empty KC list */ 86 87 extern char *optarg; 88 int arg; 89 while ((arg = getopt(argc, argv, "l:i:Kh")) != -1) { 90 switch (arg) { 91 case 'l': 92 loops = atoi(optarg); 93 break; 94 case 'i': 95 blobFile = optarg; 96 break; 97 case 'K': 98 emptyList = true; 99 emptyKCList = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); 100 break; 101 case 'h': 102 usage(argv); 103 } 104 } 105 if(optind != argc) { 106 usage(argv); 107 } 108 109 if(readFile(blobFile, &blob, &blobLen)) { 110 printf("***Error reading %s\n", blobFile); 111 exit(1); 112 } 113 /* cook up reusable policy object */ 114 SecPolicySearchRef policySearch = NULL; 115 OSStatus ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, 116 &CSSMOID_APPLE_X509_BASIC, 117 NULL, // policy opts 118 &policySearch); 119 if(ortn) { 120 cssmPerror("SecPolicySearchCreate", ortn); 121 exit(1); 122 } 123 ortn = SecPolicySearchCopyNext(policySearch, &policyRef); 124 if(ortn) { 125 cssmPerror("SecPolicySearchCopyNext", ortn); 126 exit(1); 127 } 128 CFRelease(policySearch); 129 130 CFAbsoluteTime startTimeFirst; 131 CFAbsoluteTime endTimeFirst; 132 CFAbsoluteTime startTimeMulti; 133 CFAbsoluteTime endTimeMulti; 134 135 /* GO */ 136 startTimeFirst = CFAbsoluteTimeGetCurrent(); 137 if(doDecode(blob, blobLen, policyRef, emptyKCList)) { 138 exit(1); 139 } 140 endTimeFirst = CFAbsoluteTimeGetCurrent(); 141 142 startTimeMulti = CFAbsoluteTimeGetCurrent(); 143 for(dex=0; dex<loops; dex++) { 144 if(doDecode(blob, blobLen, policyRef, emptyKCList)) { 145 exit(1); 146 } 147 } 148 endTimeMulti = CFAbsoluteTimeGetCurrent(); 149 CFTimeInterval elapsed = endTimeMulti - startTimeMulti; 150 151 printf("First decode = %4.1f ms\n", (endTimeFirst - startTimeFirst) * 1000.0); 152 printf("Next decodes = %4.2f ms/op (%f s total for %u loops)\n", 153 elapsed * 1000.0 / loops, elapsed, loops); 154 155 return 0; 156} 157