]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/kcTime/kcTime.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / kcTime / kcTime.cpp
1 /*
2 * kcTime.cpp - measure performance of keychain ops
3 */
4
5 #include <Security/Security.h>
6 #include <security_cdsa_utils/cuFileIo.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <CoreFoundation/CoreFoundation.h>
12 #include <utilLib/common.h>
13 #include <utilLib/cputime.h>
14 #include <Security/SecImportExport.h>
15
16 /* Hard coded test params */
17
18 /*
19 * Number of keychains to create/search
20 */
21 #define KT_NUM_KEYCHAINS 10
22
23 /*
24 * Certs and P12 blobs to add to keychain
25 */
26 #define KT_CERT0_NAME "amazon_v3.100.cer"
27 #define KT_CERT1_NAME "SecureServer.509.cer"
28 #define KT_P12_PFX "test1.p12"
29 #define KT_P12_PASSWORD "password"
30
31 /*
32 * Base name of keychains we create. We delete them before we start.
33 * They're in the user's home directory to faciliate testing NFS vs. local.
34 */
35 #define KT_KC_NAME "kcTime_test_"
36
37 static void usage(char **argv)
38 {
39 printf("Usage: %s [option ...]\n", argv[0]);
40 printf("Options:\n");
41 printf(" v verbose\n");
42 printf(" h help\n");
43 exit(1);
44 }
45
46 static void printAllTimes(
47 bool verbose,
48 double *delta,
49 unsigned numSamples)
50 {
51 if(!verbose) {
52 return;
53 }
54 for(unsigned dex=0; dex<numSamples; dex++) {
55 printf(" sample[%u] %8.4f\n", dex, delta[dex]);
56 }
57 }
58
59 static void printSecErr(
60 const char *op,
61 OSStatus ortn)
62 {
63 cssmPerror(op, ortn);
64 }
65
66 int main(int argc, char **argv)
67 {
68 SecKeychainRef kcRefs[KT_NUM_KEYCHAINS];
69 OSStatus ortn;
70 int arg;
71 char *argp;
72 char kcName[KT_NUM_KEYCHAINS][80];
73 unsigned dex;
74 unsigned char *cert0Data;
75 unsigned cert0Len;
76 unsigned char *cert1Data;
77 unsigned cert1Len;
78 SecCertificateRef certRef0[KT_NUM_KEYCHAINS];
79 SecCertificateRef certRef1[KT_NUM_KEYCHAINS];
80 CFArrayRef savedSearchList;
81 CFMutableArrayRef ourSearchList;
82 int irtn;
83 CPUTime startTime, endTime;
84 double deltaMs[KT_NUM_KEYCHAINS * 2];
85 double deltaMs2[KT_NUM_KEYCHAINS];
86 double deltaMs3[KT_NUM_KEYCHAINS];
87 SecKeychainSearchRef srchRef;
88 CFStringRef p12Pwd;
89 CFDataRef p12Data;
90 bool verbose = false;
91
92 memset(kcRefs, 0, sizeof(SecKeychainRef) * KT_NUM_KEYCHAINS);
93
94 for(arg=1; arg<argc; arg++) {
95 argp = argv[arg];
96 switch(argp[0]) {
97 case 'v':
98 verbose = true;
99 break;
100 default:
101 usage(argv);
102 }
103 }
104
105 printf("Starting kcTime test using %d keychains\n", KT_NUM_KEYCHAINS);
106
107 /* generate keychain names */
108 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
109 sprintf(kcName[dex], "%s%d", KT_KC_NAME, dex);
110 }
111
112 /* delete existing keychains we created in the past */
113 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
114 /*
115 * It may or may not exist, and may or may not be in the search
116 * list. Brute force and ignore errors.
117 */
118 SecKeychainRef kc;
119 ortn = SecKeychainOpen(kcName[dex], &kc);
120 if(ortn == noErr) {
121 SecKeychainDelete(kc);
122 }
123
124 /* brute force UNIX file delete too */
125 char *userHome = getenv("HOME");
126 char fullPath[1024];
127 if(userHome == NULL) {
128 userHome = (char *)"";
129 }
130 sprintf(fullPath, "%s/Library/Keychains/%s",
131 userHome, kcName[dex]);
132 unlink(fullPath);
133 }
134
135 /* read in certificate data */
136 irtn = readFile(KT_CERT0_NAME, &cert0Data, &cert0Len);
137 if(irtn) {
138 printf("I cannot find file %s in cwd.\n", KT_CERT0_NAME);
139 exit(1);
140 }
141 irtn = readFile(KT_CERT1_NAME, &cert1Data, &cert1Len);
142 if(irtn) {
143 printf("I cannot find file %s in cwd.\n", KT_CERT1_NAME);
144 exit(1);
145 }
146
147 /* save KC search list; we'll restore it at end */
148 ortn = SecKeychainCopySearchList(&savedSearchList);
149 if(ortn) {
150 printSecErr("SecKeychainCopySearchList", ortn);
151 return 1;
152 }
153 /* subsequent errors to errOut: to restore searchList! */
154
155 /* TIME: create n keychains */
156 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
157 unsigned pwdLen = strlen(kcName[dex]);
158 startTime = CPUTimeRead();
159 ortn = SecKeychainCreate(kcName[dex],
160 pwdLen,
161 kcName[dex],
162 false, // promptUser,
163 nil, // initialAccess
164 &kcRefs[dex]);
165 endTime = CPUTimeRead();
166 if(ortn) {
167 printSecErr("SecKeychainCreate", ortn);
168 goto errOut;
169 }
170 deltaMs[dex] = CPUTimeDeltaMs(startTime, endTime);
171 }
172 printf("Create : %7.3f ms per op\n",
173 CPUTimeAvg(deltaMs, KT_NUM_KEYCHAINS));
174 printAllTimes(verbose, deltaMs, KT_NUM_KEYCHAINS);
175
176 /* set KC search list to only the ones we just created */
177 ourSearchList = CFArrayCreateMutable(NULL, KT_NUM_KEYCHAINS, NULL);
178 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
179 CFArrayInsertValueAtIndex(ourSearchList, dex, kcRefs[dex]);
180 }
181 ortn = SecKeychainSetSearchList(ourSearchList);
182 if(ortn) {
183 printSecErr("SecKeychainSetSearchList", ortn);
184 goto errOut;
185 }
186 CFRelease(ourSearchList);
187
188 /* TIME: close all of them */
189 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
190 startTime = CPUTimeRead();
191 CFRelease(kcRefs[dex]);
192 endTime = CPUTimeRead();
193 deltaMs[dex] = CPUTimeDeltaMs(startTime, endTime);
194 }
195 printf("Close : %7.3f ms per op\n",
196 CPUTimeAvg(deltaMs, KT_NUM_KEYCHAINS));
197 printAllTimes(verbose, deltaMs, KT_NUM_KEYCHAINS);
198
199 /* TIME: open all of them */
200 /* This is so fast that we just measure the total time */
201 startTime = CPUTimeRead();
202 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
203 ortn = SecKeychainOpen(kcName[dex], &kcRefs[dex]);
204 if(ortn) {
205 printSecErr("SecKeychainOpen", ortn);
206 goto errOut;
207 }
208 }
209 endTime = CPUTimeRead();
210 deltaMs[0] = CPUTimeDeltaMs(startTime, endTime);
211 printf("Open : %7.3f ms per op\n",
212 deltaMs[0] / KT_NUM_KEYCHAINS);
213 if(verbose) {
214 printf(" total time %7.3f ms\n", deltaMs[0]);
215 }
216
217 /* TIME: get status on all of them */
218 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
219 SecKeychainStatus status;
220 startTime = CPUTimeRead();
221 ortn = SecKeychainGetStatus(kcRefs[dex], &status);
222 endTime = CPUTimeRead();
223 if(ortn) {
224 printSecErr("SecKeychainGetStatus", ortn);
225 goto errOut;
226 }
227 deltaMs[dex] = CPUTimeDeltaMs(startTime, endTime);
228 }
229 printf("Get Status : %7.3f ms per op\n",
230 CPUTimeAvg(deltaMs, KT_NUM_KEYCHAINS));
231 printAllTimes(verbose, deltaMs, KT_NUM_KEYCHAINS);
232
233 /* TIME: unlock each keychain */
234 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
235 unsigned pwdLen = strlen(kcName[dex]);
236 startTime = CPUTimeRead();
237 ortn = SecKeychainUnlock(kcRefs[dex],
238 pwdLen, kcName[dex], true);
239 endTime = CPUTimeRead();
240 if(ortn) {
241 printSecErr("SecKeychainUnlock", ortn);
242 goto errOut;
243 }
244 deltaMs[dex] = CPUTimeDeltaMs(startTime, endTime);
245 }
246 printf("Unlock : %7.3f ms per op\n",
247 CPUTimeAvg(deltaMs, KT_NUM_KEYCHAINS));
248 printAllTimes(verbose, deltaMs, KT_NUM_KEYCHAINS);
249
250 /* TIME: create two SecCertificateRefs for each KC */
251 /* this is fast, just measure total time */
252 startTime = CPUTimeRead();
253 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
254 CSSM_DATA cdata = {cert0Len, cert0Data};
255 ortn = SecCertificateCreateFromData(&cdata,
256 CSSM_CERT_X_509v3,
257 CSSM_CERT_ENCODING_DER,
258 &certRef0[dex]);
259 if(ortn) {
260 printSecErr("SecCertificateCreateFromData", ortn);
261 goto errOut;
262 }
263 cdata.Length = cert1Len;
264 cdata.Data = cert1Data;
265 ortn = SecCertificateCreateFromData(&cdata,
266 CSSM_CERT_X_509v3,
267 CSSM_CERT_ENCODING_DER,
268 &certRef1[dex]);
269 if(ortn) {
270 printSecErr("SecCertificateCreateFromData", ortn);
271 goto errOut;
272 }
273 }
274 endTime = CPUTimeRead();
275 deltaMs[0] = CPUTimeDeltaMs(startTime, endTime);
276 /* we created KT_NUM_KEYCHAINS*2 certs in KT_NUM_KEYCHAINS samples */
277 printf("SecCertificateCreateFromData : %7.3f ms per op\n",
278 deltaMs[0] / (KT_NUM_KEYCHAINS * 2.0));
279 if(verbose) {
280 printf(" total time %7.3f ms\n", deltaMs[0]);
281 }
282 free(cert0Data);
283 free(cert1Data);
284
285 /* TIME: add two certs to each keychain */
286 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
287 startTime = CPUTimeRead();
288 ortn = SecCertificateAddToKeychain(certRef0[dex], kcRefs[dex]);
289 if(ortn) {
290 printSecErr("SecCertificateAddToKeychain", ortn);
291 goto errOut;
292 }
293 ortn = SecCertificateAddToKeychain(certRef1[dex], kcRefs[dex]);
294 endTime = CPUTimeRead();
295 if(ortn) {
296 printSecErr("SecCertificateAddToKeychain", ortn);
297 goto errOut;
298 }
299 deltaMs[dex] = CPUTimeDeltaMs(startTime, endTime);
300 }
301 /* we added KT_NUM_KEYCHAINS*2 certs in KT_NUM_KEYCHAINS samples */
302 printf("SecCertificateAddToKeychain : %7.3f ms per op\n",
303 CPUTimeAvg(deltaMs, KT_NUM_KEYCHAINS) / 2.0);
304 printAllTimes(verbose, deltaMs, KT_NUM_KEYCHAINS);
305
306 /* free the certRefs */
307 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
308 CFRelease(certRef0[dex]);
309 CFRelease(certRef1[dex]);
310 }
311
312 /*
313 Ê* Three TIMES:
314 * -- search for the first cert
315 * -- search for the next one
316 * -- search once more to end (not found)
317 */
318 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
319 SecKeychainItemRef certRef = NULL;
320
321 /* step 1. set up search, get first item */
322 startTime = CPUTimeRead();
323 ortn = SecKeychainSearchCreateFromAttributes(kcRefs[dex],
324 kSecCertificateItemClass,
325 NULL, // no attrs
326 &srchRef);
327 if(ortn) {
328 printSecErr("SecKeychainSearchCreateFromAttributes", ortn);
329 goto errOut;
330 }
331 ortn = SecKeychainSearchCopyNext(srchRef, &certRef);
332 /* might be necessary to actually bring in the cert */
333 if(SecCertificateGetTypeID() != CFGetTypeID(certRef)) {
334 printf("***Unexpected CFType on cert search\n");
335 goto errOut;
336 }
337 endTime = CPUTimeRead();
338 if(ortn) {
339 printSecErr("SecKeychainSearchCopyNext", ortn);
340 goto errOut;
341 }
342 deltaMs[dex] = CPUTimeDeltaMs(startTime, endTime);
343 CFRelease(certRef);
344
345 /* step 2. get next item */
346 startTime = CPUTimeRead();
347 ortn = SecKeychainSearchCopyNext(srchRef, &certRef);
348 if(SecCertificateGetTypeID() != CFGetTypeID(certRef)) {
349 printf("***Unexpected CFType on cert search\n");
350 goto errOut;
351 }
352 endTime = CPUTimeRead();
353 if(ortn) {
354 printSecErr("SecKeychainSearchCreateFromAttributes", ortn);
355 goto errOut;
356 }
357 deltaMs2[dex] = CPUTimeDeltaMs(startTime, endTime);
358 CFRelease(certRef);
359
360 /* step 3. one more search for nonexistent item */
361 startTime = CPUTimeRead();
362 ortn = SecKeychainSearchCopyNext(srchRef, &certRef);
363 endTime = CPUTimeRead();
364 if(ortn != errSecItemNotFound) {
365 if(ortn == noErr) {
366 printf("***SecKeychainSearchCopyNext got noErr, "
367 "expected notFound\n");
368 }
369 else {
370 printSecErr("SecKeychainSearchCopyNext", ortn);
371 }
372 goto errOut;
373 }
374 deltaMs3[dex] = CPUTimeDeltaMs(startTime, endTime);
375 CFRelease(srchRef);
376 }
377 printf("SecKeychainSearch first item : %7.3f ms per op\n",
378 CPUTimeAvg(deltaMs, KT_NUM_KEYCHAINS));
379 printAllTimes(verbose, deltaMs, KT_NUM_KEYCHAINS);
380 printf("SecKeychainSearch next item : %7.3f ms per op\n",
381 CPUTimeAvg(deltaMs2, KT_NUM_KEYCHAINS));
382 printAllTimes(verbose, deltaMs2, KT_NUM_KEYCHAINS);
383 printf("SecKeychainSearch end of list : %7.3f ms per op\n",
384 CPUTimeAvg(deltaMs3, KT_NUM_KEYCHAINS));
385 printAllTimes(verbose, deltaMs3, KT_NUM_KEYCHAINS);
386
387 /*
388 * TIME: search all certs in all keychains
389 * This search create is outside the loop....
390 */
391 ortn = SecKeychainSearchCreateFromAttributes(NULL,
392 kSecCertificateItemClass,
393 NULL, // no attrs
394 &srchRef);
395 if(ortn) {
396 printSecErr("SecKeychainSearchCreateFromAttributes", ortn);
397 goto errOut;
398 }
399 /* we have 2 certs per keychain, search all of them */
400 for(dex=0; dex<KT_NUM_KEYCHAINS*2; dex++) {
401 SecKeychainItemRef certRef = NULL;
402
403 startTime = CPUTimeRead();
404 ortn = SecKeychainSearchCopyNext(srchRef, &certRef);
405 /* might be necessary to actually bring in the cert */
406 if(SecCertificateGetTypeID() != CFGetTypeID(certRef)) {
407 printf("***Unexpected CFType on cert search\n");
408 goto errOut;
409 }
410 endTime = CPUTimeRead();
411 deltaMs[dex] = CPUTimeDeltaMs(startTime, endTime);
412 CFRelease(certRef);
413 }
414 printf("SecKeychainSearch all KCs : %7.3f ms per op\n",
415 CPUTimeAvg(deltaMs, KT_NUM_KEYCHAINS * 2));
416 printAllTimes(verbose, deltaMs, KT_NUM_KEYCHAINS * 2);
417
418 /*
419 * TIME: import a p12 identity into each keychain
420 *
421 * First, read the file
422 */
423 irtn = readFile(KT_P12_PFX, &cert0Data, &cert0Len);
424 if(irtn) {
425 printf("I cannot find file %s in cwd.\n", KT_P12_PFX);
426 exit(1);
427 }
428 p12Data = CFDataCreate(NULL, cert0Data, cert0Len);
429 p12Pwd = CFStringCreateWithCString(NULL, KT_P12_PASSWORD,
430 kCFStringEncodingASCII);
431
432 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
433 SecExternalFormat format = kSecFormatPKCS12;
434 SecExternalItemType itemType = kSecItemTypeAggregate;
435 SecKeyImportExportParameters keyParams;
436 memset(&keyParams, 0, sizeof(keyParams));
437 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
438 keyParams.flags = kSecKeyNoAccessControl;
439 keyParams.passphrase = p12Pwd;
440
441 keyParams.keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE |
442 CSSM_KEYATTR_EXTRACTABLE;
443
444 startTime = CPUTimeRead();
445 ortn = SecKeychainItemImport(p12Data,
446 NULL, // fileNameOrExtension
447 &format, &itemType,
448 0, // flags
449 &keyParams,
450 kcRefs[dex],
451 NULL); // outItems
452 if(ortn) {
453 printSecErr("SecKeychainItemImport(p12)", ortn);
454 goto errOut;
455 }
456 endTime = CPUTimeRead();
457 deltaMs[dex] = CPUTimeDeltaMs(startTime, endTime);
458 }
459 CFRelease(p12Data);
460 CFRelease(p12Pwd);
461 printf("P12 Import : %7.3f ms per op\n",
462 CPUTimeAvg(deltaMs, KT_NUM_KEYCHAINS));
463 printAllTimes(verbose, deltaMs, KT_NUM_KEYCHAINS);
464
465 /* TIME: identity search in each keychain */
466 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
467 SecIdentitySearchRef idSrch;
468 SecIdentityRef idRef;
469 startTime = CPUTimeRead();
470 ortn = SecIdentitySearchCreate(kcRefs[dex], 0, &idSrch);
471 if(ortn) {
472 printSecErr("SecIdentitySearchCreate", ortn);
473 goto errOut;
474 }
475 ortn = SecIdentitySearchCopyNext(idSrch, &idRef);
476 endTime = CPUTimeRead();
477 if(ortn) {
478 printSecErr("SecIdentitySearchCopyNext", ortn);
479 goto errOut;
480 }
481 deltaMs[dex] = CPUTimeDeltaMs(startTime, endTime);
482 CFRelease(idSrch);
483 CFRelease(idRef);
484 }
485 printf("SecIdentity search : %7.3f ms per op\n",
486 CPUTimeAvg(deltaMs, KT_NUM_KEYCHAINS));
487 printAllTimes(verbose, deltaMs, KT_NUM_KEYCHAINS);
488
489 errOut:
490 ortn = SecKeychainSetSearchList(savedSearchList);
491 if(ortn) {
492 printSecErr("SecKeychainSetSearchList", ortn);
493 }
494
495 /* delete all the keychains we created */
496 for(dex=0; dex<KT_NUM_KEYCHAINS; dex++) {
497 if(kcRefs[dex] != NULL) {
498 SecKeychainDelete(kcRefs[dex]);
499 }
500 }
501
502 /* other cleanup if anyone cares */
503 return 0;
504 }