]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/certTime/certTime.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / SecurityTests / clxutils / certTime / certTime.cpp
1 /*
2 * certTime - measure performacne of cert parse and build.
3 */
4
5 #include <security_cdsa_utils/cuFileIo.h>
6 #include <clAppUtils/CertBuilderApp.h>
7 #include <utilLib/common.h>
8 #include <utilLib/cspwrap.h>
9 #include <clAppUtils/clutils.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <time.h>
14 #include <Security/cssm.h>
15 #include <Security/x509defs.h>
16 #include <Security/oidsattr.h>
17 #include <Security/oidscert.h>
18 #include <Security/certextensions.h>
19 #include <CoreFoundation/CoreFoundation.h>
20 #include "extenCooker.h"
21
22 #define KEYSIZE_DEF 1024
23 #define CL_KEY_VIA_GET_KEY 0
24
25 static void usage(char **argv)
26 {
27 printf("Usage: %s op loops [options]\n", argv[0]);
28 printf("Op:\n");
29 printf(" p parse\n");
30 printf(" g parse & get all fields\n");
31 #if CL_KEY_VIA_GET_KEY
32 printf(" t parse & get some fields, emulating TPCertInfo, GetKeyInfo\n");
33 #else
34 printf(" t parse & get some fields, emulating TPCertInfo, fetchField(key)\n");
35 #endif
36 printf(" c create\n");
37 printf(" s create & sign\n");
38 printf(" v verify\n");
39 printf("Options:\n");
40 printf(" b RSA blinding on\n");
41 printf(" k=keysize (default = %d)\n", KEYSIZE_DEF);
42 exit(1);
43 }
44
45 /*
46 * The certs we'll be parsing
47 */
48 static const char *certNames[] =
49 {
50 "anchor_0", // GTE CyberTrust Root, no extens
51 "anchor_9", // VeriSign, no extens
52 "anchor_34", // TrustCenter, 6 extens
53 "anchor_44", // USERTRUST, 5 extens, incl. cRLDistributionPoints
54 "anchor_76", // QuoVadis, 6 extens, incl. authorityInfoAccess
55 "anchor_80", // KMD-CA Kvalificeret3 6 extens
56 };
57
58 #define NUM_PARSED_CERTS (sizeof(certNames) / sizeof(certNames[0]))
59
60 /* dummy RDN - subject and issuer - we aren't testing this */
61 CB_NameOid dummyRdn[] =
62 {
63 { "Apple Computer", &CSSMOID_OrganizationName },
64 { "Doug Mitchell", &CSSMOID_CommonName }
65 };
66 #define NUM_DUMMY_NAMES (sizeof(dummyRdn) / sizeof(CB_NameOid))
67
68 #define KEY_ALG CSSM_ALGID_RSA
69 #define SIG_ALG CSSM_ALGID_SHA1WithRSA
70 #define SUBJ_KEY_LABEL "subjectKey"
71
72
73 /*
74 * Set of extensions we'll be creating
75 */
76 /* empty freeFcn means no extension-specific resources to free */
77 #define NO_FREE NULL
78
79 static ExtenTest extenTests[] = {
80 { kuCreate, kuCompare, NO_FREE,
81 sizeof(CE_KeyUsage), CSSMOID_KeyUsage,
82 "KeyUsage", 'k' },
83 { ekuCreate, ekuCompare, NO_FREE,
84 sizeof(CE_ExtendedKeyUsage), CSSMOID_ExtendedKeyUsage,
85 "ExtendedKeyUsage", 'x' },
86 { authKeyIdCreate, authKeyIdCompare, authKeyIdFree,
87 sizeof(CE_AuthorityKeyID), CSSMOID_AuthorityKeyIdentifier,
88 "AuthorityKeyID", 'a' },
89 { genNamesCreate, genNamesCompare, genNamesFree,
90 sizeof(CE_GeneralNames), CSSMOID_SubjectAltName,
91 "SubjectAltName", 't' },
92 };
93
94 #define MAX_EXTENSIONS (sizeof(extenTests) / sizeof(ExtenTest))
95
96 static int doParse(
97 CSSM_CL_HANDLE clHand,
98 const CSSM_DATA &cert,
99 unsigned loops)
100 {
101 CSSM_HANDLE cacheHand;
102 CSSM_RETURN crtn;
103
104 for(unsigned loop=0; loop<loops; loop++) {
105 crtn = CSSM_CL_CertCache(clHand, &cert, &cacheHand);
106 if(crtn) {
107 printError("CSSM_CL_CertCache", crtn);
108 return 1;
109 }
110 crtn = CSSM_CL_CertAbortCache(clHand, cacheHand);
111 if(crtn) {
112 printError("CSSM_CL_CrlAbortCache", crtn);
113 return 1;
114 }
115 }
116 return 0;
117 }
118
119 /* Emulate TPCertInfo constructor */
120
121 static CSSM_RETURN fetchCertField(
122 CSSM_CL_HANDLE clHand,
123 CSSM_HANDLE certHand,
124 const CSSM_OID *fieldOid,
125 CSSM_DATA_PTR *fieldData) // mallocd by CL and RETURNED
126 {
127 CSSM_RETURN crtn;
128
129 uint32 NumberOfFields = 0;
130 CSSM_HANDLE resultHand = 0;
131 *fieldData = NULL;
132 crtn = CSSM_CL_CertGetFirstCachedFieldValue(
133 clHand,
134 certHand,
135 fieldOid,
136 &resultHand,
137 &NumberOfFields,
138 fieldData);
139 if(crtn) {
140 printError("fetchCertField", crtn);
141 return crtn;
142 }
143 if(NumberOfFields != 1) {
144 printf("***fetchCertField: numFields %d, expected 1\n",
145 (int)NumberOfFields);
146 }
147 CSSM_CL_CertAbortQuery(clHand, resultHand);
148 return CSSM_OK;
149 }
150
151
152 static int doGetSomeFields(
153 CSSM_CL_HANDLE clHand,
154 const CSSM_DATA &cert,
155 unsigned loops)
156 {
157 CSSM_HANDLE cacheHand;
158 CSSM_RETURN crtn;
159
160 /* fetched by TPClItemInfo constructor */
161 CSSM_DATA_PTR issuerName;
162 CSSM_DATA_PTR sigAlg;
163 CSSM_DATA_PTR notBefore;
164 CSSM_DATA_PTR notAfter;
165 /* fetched by TPCertInfo */
166 CSSM_DATA_PTR subjectName;
167 #if CL_KEY_VIA_GET_KEY
168 CSSM_KEY_PTR subjPubKey;
169 #else
170 CSSM_DATA_PTR subjPubKeyData;
171 #endif
172
173 for(unsigned loop=0; loop<loops; loop++) {
174 /* parse and cache */
175 crtn = CSSM_CL_CertCache(clHand, &cert, &cacheHand);
176 if(crtn) {
177 printError("CSSM_CL_CertCache", crtn);
178 return 1;
179 }
180 /* fetch the fields */
181 fetchCertField(clHand, cacheHand, &CSSMOID_X509V1IssuerName, &issuerName);
182 fetchCertField(clHand, cacheHand, &CSSMOID_X509V1SignatureAlgorithmTBS,
183 &sigAlg);
184 fetchCertField(clHand, cacheHand, &CSSMOID_X509V1ValidityNotBefore,
185 &notBefore);
186 fetchCertField(clHand, cacheHand, &CSSMOID_X509V1ValidityNotAfter, &notAfter);
187 fetchCertField(clHand, cacheHand, &CSSMOID_X509V1SubjectName, &subjectName);
188 #if CL_KEY_VIA_GET_KEY
189 CSSM_CL_CertGetKeyInfo(clHand, &cert, &subjPubKey);
190 #else
191 fetchCertField(clHand, cacheHand, &CSSMOID_CSSMKeyStruct, &subjPubKeyData);
192 #endif
193
194 /* free the fields */
195 CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1IssuerName, issuerName);
196 CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SignatureAlgorithmTBS, sigAlg);
197 CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1ValidityNotBefore, notBefore);
198 CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1ValidityNotAfter, notAfter);
199 CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SubjectName, subjectName);
200 #if CL_KEY_VIA_GET_KEY
201 appFree(subjPubKey->KeyData.Data, 0);
202 appFree(subjPubKey, 0);
203 #else
204 CSSM_CL_FreeFieldValue(clHand, &CSSMOID_CSSMKeyStruct, subjPubKeyData);
205 #endif
206
207 crtn = CSSM_CL_CertAbortCache(clHand, cacheHand);
208 if(crtn) {
209 printError("CSSM_CL_CrlAbortCache", crtn);
210 return 1;
211 }
212 }
213 return 0;
214 }
215
216 static int doGetFields(
217 CSSM_CL_HANDLE clHand,
218 const CSSM_DATA &cert,
219 unsigned loops)
220 {
221 uint32 numFields;
222 CSSM_FIELD_PTR certFields;
223 CSSM_RETURN crtn;
224
225 for(unsigned loop=0; loop<loops; loop++) {
226 crtn = CSSM_CL_CertGetAllFields(clHand, &cert, &numFields,
227 &certFields);
228 if(crtn) {
229 printError("CSSM_CL_CertGetAllFields", crtn);
230 return 1;
231 }
232 crtn = CSSM_CL_FreeFields(clHand, numFields, &certFields);
233 if(crtn) {
234 printError("CSSM_CL_FreeFields", crtn);
235 return 1;
236 }
237 }
238 return 0;
239 }
240
241 static int doVerify(
242 CSSM_CL_HANDLE clHand,
243 const CSSM_DATA &cert,
244 unsigned loops)
245 {
246 CSSM_RETURN crtn;
247
248 for(unsigned loop=0; loop<loops; loop++) {
249 crtn = CSSM_CL_CertVerify(clHand,
250 CSSM_INVALID_HANDLE,
251 &cert,
252 &cert,
253 NULL, // VerifyScope
254 0); // ScopeSize
255 if(crtn) {
256 printError("CSSM_CL_CertVerify", crtn);
257 return 1;
258 }
259 }
260 return 0;
261 }
262
263 /*
264 * Stuff to be created before entering the timed cert create routine.
265 */
266 typedef struct {
267 CSSM_KEY privKey;
268 CSSM_KEY pubKey;
269 CSSM_X509_NAME *dummyName;
270 CSSM_X509_TIME *notBefore;
271 CSSM_X509_TIME *notAfter;
272 CSSM_X509_EXTENSION extens[MAX_EXTENSIONS];
273 } PresetParams;
274
275 /*
276 * One-time only setup of cert creation params.
277 */
278 static int createSetup(
279 CSSM_CL_HANDLE clHand,
280 CSSM_CSP_HANDLE cspHand,
281 unsigned keySize,
282 PresetParams &params)
283 {
284 CSSM_RETURN crtn;
285
286 crtn = cspGenKeyPair(cspHand,
287 KEY_ALG,
288 SUBJ_KEY_LABEL,
289 strlen(SUBJ_KEY_LABEL),
290 keySize,
291 &params.pubKey,
292 CSSM_FALSE, // pubIsRef
293 CSSM_KEYUSE_VERIFY,
294 CSSM_KEYBLOB_RAW_FORMAT_NONE,
295 &params.privKey,
296 CSSM_TRUE, // privIsRef - doesn't matter
297 CSSM_KEYUSE_SIGN,
298 CSSM_KEYBLOB_RAW_FORMAT_NONE,
299 CSSM_FALSE);
300 if(crtn) {
301 return 1;
302 }
303 params.dummyName = CB_BuildX509Name(dummyRdn, NUM_DUMMY_NAMES);
304 if(params.dummyName == NULL) {
305 printf("CB_BuildX509Name failure");
306 return 1;
307 }
308 params.notBefore = CB_BuildX509Time(0);
309 params.notAfter = CB_BuildX509Time(10000);
310
311 /* now some extensions */
312 for(unsigned dex=0; dex<MAX_EXTENSIONS; dex++) {
313 CSSM_X509_EXTENSION &extn = params.extens[dex];
314 ExtenTest &etest = extenTests[dex];
315
316 void *extVal = CSSM_MALLOC(etest.extenSize);
317 memset(extVal, 0, etest.extenSize);
318 etest.createFcn(extVal);
319
320 extn.extnId = etest.extenOid;
321 extn.critical = randBool();
322 extn.format = CSSM_X509_DATAFORMAT_PARSED;
323 extn.value.parsedValue = extVal;
324 extn.BERvalue.Data = NULL;
325 extn.BERvalue.Length = 0;
326 }
327 return 0;
328 }
329
330 static int doCreate(
331 CSSM_CL_HANDLE clHand,
332 CSSM_CSP_HANDLE cspHand,
333 unsigned loops,
334 PresetParams &params,
335 bool doSign,
336 bool rsaBlind)
337 {
338 for(unsigned loop=0; loop<loops; loop++) {
339 CSSM_DATA_PTR rawCert = CB_MakeCertTemplate(clHand,
340 0x12345678, // serial number
341 params.dummyName,
342 params.dummyName,
343 params.notBefore,
344 params.notAfter,
345 &params.pubKey,
346 SIG_ALG,
347 NULL, // subjUniqueId
348 NULL, // issuerUniqueId
349 params.extens, // extensions
350 /* vary numExtensions per loop */
351 loop % MAX_EXTENSIONS);
352 if(rawCert == NULL) {
353 printf("Error creating cert template.\n");
354 return 1;
355 }
356 if(doSign) {
357 CSSM_DATA signedCert = {0, NULL};
358 CSSM_CC_HANDLE sigHand;
359 CSSM_RETURN crtn = CSSM_CSP_CreateSignatureContext(cspHand,
360 SIG_ALG,
361 NULL, // no passphrase for now
362 &params.privKey,
363 &sigHand);
364 if(crtn) {
365 printError("CreateSignatureContext", crtn);
366 return 1;
367 }
368
369 if(rsaBlind) {
370 CSSM_CONTEXT_ATTRIBUTE newAttr;
371 newAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING;
372 newAttr.AttributeLength = sizeof(uint32);
373 newAttr.Attribute.Uint32 = 1;
374 crtn = CSSM_UpdateContextAttributes(sigHand, 1, &newAttr);
375 if(crtn) {
376 printError("CSSM_UpdateContextAttributes", crtn);
377 return crtn;
378 }
379 }
380
381 crtn = CSSM_CL_CertSign(clHand,
382 sigHand,
383 rawCert, // CertToBeSigned
384 NULL, // SignScope per spec
385 0, // ScopeSize per spec
386 &signedCert);
387 if(crtn) {
388 printError("CSSM_CL_CertSign", crtn);
389 return 1;
390 }
391 CSSM_DeleteContext(sigHand);
392 CSSM_FREE(signedCert.Data);
393 }
394 CSSM_FREE(rawCert->Data);
395 CSSM_FREE(rawCert);
396 }
397 return 0;
398 }
399
400 typedef enum {
401 CTO_Parse,
402 CTO_GetFields,
403 CTO_GetSomeFields,
404 CTO_Create, // sign is an option for this one
405 CTO_Verify
406 } CT_Op;
407
408 int main(int argc, char **argv)
409 {
410 CSSM_CL_HANDLE clHand;
411 CSSM_CSP_HANDLE cspHand;
412 int arg;
413 int rtn;
414 char *argp;
415 unsigned i;
416 PresetParams params;
417 CSSM_DATA certData[NUM_PARSED_CERTS];
418
419 /* user-specificied params */
420 CT_Op op;
421 unsigned loops = 0;
422 bool doSign = false;
423 const char *opStr = NULL;
424 bool rsaBlinding = false;
425 unsigned keySize = KEYSIZE_DEF;
426
427 if(argc < 3) {
428 usage(argv);
429 }
430 switch(argv[1][0]) {
431 case 'p':
432 op = CTO_Parse;
433 opStr = "Parsed";
434 break;
435 case 'g':
436 op = CTO_GetFields;
437 opStr = "Parsed with GetAllFields";
438 break;
439 case 't':
440 op = CTO_GetSomeFields;
441 #if CL_KEY_VIA_GET_KEY
442 opStr = "Parsed with some GetFields and GetKeyInfo";
443 #else
444 opStr = "Parsed with some GetFields";
445 #endif
446 break;
447 case 'c':
448 op = CTO_Create;
449 opStr = "Created";
450 break;
451 case 's':
452 op = CTO_Create;
453 opStr = "Created and Signed";
454 doSign = true;
455 break;
456 case 'v':
457 op = CTO_Verify;
458 opStr = "Verified";
459 break;
460 default:
461 usage(argv);
462 }
463
464 loops = atoi(argv[2]);
465 for(arg=3; arg<argc; arg++) {
466 argp = argv[arg];
467 switch(argp[0]) {
468 case 'b':
469 rsaBlinding = true;
470 break;
471 case 'k':
472 keySize = atoi(&argp[2]);
473 break;
474 default:
475 usage(argv);
476 }
477 }
478
479 /* common setup */
480 clHand = clStartup();
481 if(clHand == 0) {
482 return 0;
483 }
484 cspHand = cspStartup();
485 if(cspHand == 0) {
486 return 0;
487 }
488
489 /* per-test setup */
490 switch(op) {
491 unsigned dex;
492 unsigned len;
493
494 case CTO_Parse:
495 case CTO_GetFields:
496 case CTO_GetSomeFields:
497 case CTO_Verify:
498 /* read in the certs */
499 for(dex=0; dex<NUM_PARSED_CERTS; dex++) {
500 CSSM_DATA &cdata = certData[dex];
501 if(readFile(certNames[dex],
502 (unsigned char **)&cdata.Data,
503 &len)) {
504 printf("Error reading cert %s. Aborting.\n",
505 certNames[dex]);
506 exit(1);
507 }
508 cdata.Length = len;
509 }
510 break;
511 case CTO_Create:
512 /* set up keys, names */
513 if(createSetup(clHand, cspHand, keySize, params)) {
514 exit(1);
515 }
516 break;
517 }
518
519 /* one loop outside of timer to heat up test bed */
520 switch(op) {
521 case CTO_Parse:
522 rtn = doParse(clHand, certData[0], 1);
523 break;
524 case CTO_GetFields:
525 rtn = doGetFields(clHand, certData[0], 1);
526 break;
527 case CTO_GetSomeFields:
528 rtn = doGetSomeFields(clHand, certData[0], 1);
529 break;
530 case CTO_Verify:
531 rtn = doVerify(clHand, certData[0], 1);
532 break;
533 case CTO_Create:
534 rtn = doCreate(clHand, cspHand, 1, params, true, rsaBlinding);
535 break;
536 }
537 if(rtn) {
538 printf("This program needs work. Try again.\n");
539 return 1;
540 }
541
542 CFAbsoluteTime startTime, endTime;
543 startTime = CFAbsoluteTimeGetCurrent();
544
545 /* begin timed loop */
546 switch(op) {
547 case CTO_Parse:
548 for(i=0; i<NUM_PARSED_CERTS; i++) {
549 rtn = doParse(clHand, certData[i], loops);
550 if(rtn) {
551 break;
552 }
553 }
554 break;
555 case CTO_GetFields:
556 for(i=0; i<NUM_PARSED_CERTS; i++) {
557 rtn = doGetFields(clHand, certData[i], loops);
558 if(rtn) {
559 break;
560 }
561 }
562 break;
563 case CTO_GetSomeFields:
564 for(i=0; i<NUM_PARSED_CERTS; i++) {
565 rtn = doGetSomeFields(clHand, certData[i], loops);
566 if(rtn) {
567 break;
568 }
569 }
570 break;
571 case CTO_Verify:
572 for(i=0; i<NUM_PARSED_CERTS; i++) {
573 rtn = doVerify(clHand, certData[i], loops);
574 if(rtn) {
575 break;
576 }
577 }
578 break;
579 case CTO_Create:
580 rtn = doCreate(clHand, cspHand, loops, params, doSign,
581 rsaBlinding);
582 break;
583 }
584 endTime = CFAbsoluteTimeGetCurrent();
585 CFAbsoluteTime deltaTime = endTime - startTime;
586
587 if(rtn) {
588 printf("Error in main loop. Try again.\n");
589 return 1;
590 }
591
592 unsigned numCerts = loops;
593 if(op != CTO_Create) {
594 numCerts *= NUM_PARSED_CERTS;
595 }
596
597 printf("=== %u certs %s ===\n", numCerts, opStr);
598 printf("Total time %g s\n", deltaTime);
599 printf("%g ms per cert\n", (deltaTime / (double)numCerts) * 1000.0);
600
601 /* cleanup */
602 if(op == CTO_Create) {
603 CB_FreeX509Name(params.dummyName);
604 CB_FreeX509Time(params.notBefore);
605 CB_FreeX509Time(params.notAfter);
606 cspFreeKey(cspHand, &params.pubKey);
607 cspFreeKey(cspHand, &params.privKey);
608 }
609 else {
610 for(i=0; i<NUM_PARSED_CERTS; i++) {
611 free(certData[i].Data);
612 }
613 }
614 CSSM_ModuleDetach(cspHand);
615 CSSM_ModuleDetach(clHand);
616 return 0;
617 }
618