]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/signerAndSubj/signerAndSubj.cpp
Security-57031.30.12.tar.gz
[apple/security.git] / SecurityTests / clxutils / signerAndSubj / signerAndSubj.cpp
1 /* Copyright (c) 1998,2003,2005-2006,2008 Apple Inc.
2 *
3 * signerAndSubj.c
4 *
5 * Create two certs - a root, and a subject cert signed by the root. Includes
6 * extension construction. Verify certs every which way, including various expected
7 * failures.
8 *
9 * Revision History
10 * ----------------
11 * 31 Aug 2000 Doug Mitchell at Apple
12 * Ported to X/CDSA2.
13 * 20 Jul 1998 Doug Mitchell at NeXT
14 * Created.
15 */
16
17 #include <utilLib/common.h>
18 #include <utilLib/cspwrap.h>
19 #include <security_cdsa_utils/cuFileIo.h>
20 #include <clAppUtils/CertBuilderApp.h>
21 #include <clAppUtils/clutils.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <Security/cssm.h>
26 #include <Security/x509defs.h>
27 #include <Security/oidsattr.h>
28 #include <Security/oidscert.h>
29 #include <Security/oidsalg.h>
30 #include <Security/certextensions.h>
31 #include <Security/cssmapple.h>
32 #include <string.h>
33
34 #define SUBJ_KEY_LABEL "subjectKey"
35 #define ROOT_KEY_LABEL "rootKey"
36 /* default key and signature algorithm */
37 #define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA
38 #define KEY_ALG_DEFAULT CSSM_ALGID_RSA
39
40 /* for write certs/components option */
41 #define ROOT_CERT_FILE_NAME "ssRootCert.der"
42 #define ROOT_TBS_FILE_NAME "ssRootTBS.der"
43 #define SUBJ_CERT_FILE_NAME "ssSubjCert.der"
44 #define SUBJ_TBS_FILE_NAME "ssSubjTBS.der"
45 #define ROOT_PRIV_KEY_FILE "ssRootPriv.der"
46 #define SUBJ_PRIV_KEY_FILE "ssSubjPriv.der"
47
48 static void usage(char **argv)
49 {
50 printf("Usage: %s [options]\n", argv[0]);
51 printf("Options:\n");
52 printf(" w[rite certs and components]\n");
53 printf(" a=alg where alg is s(RSA/SHA1), m(RSA/MD5), f(FEE/MD5), F(FEE/SHA1),\n");
54 printf(" 2(RSA/SHA224), 6(RSA/SHA256), 3(RSA/SHA384) 5=RSA/SHA512,\n");
55 printf(" e(ECDSA), E(ANSI/ECDSA), 7(ECDSA/SHA256), 8(ECDSA/SHA384), 9(ECDSA/SHA512)\n");
56 printf(" k=keySizeInBits\n");
57 exit(1);
58 }
59
60 /*
61 * RDN components for root, subject
62 */
63 CB_NameOid rootRdn[] =
64 {
65 { "Apple Computer", &CSSMOID_OrganizationName },
66 { "The Big Cheese", &CSSMOID_Title }
67 };
68 #define NUM_ROOT_NAMES (sizeof(rootRdn) / sizeof(CB_NameOid))
69
70 CB_NameOid subjRdn[] =
71 {
72 /* note extra space for normalize test */
73 { "Apple Computer", &CSSMOID_OrganizationName },
74 { "Doug Mitchell", &CSSMOID_CommonName }
75 };
76 #define NUM_SUBJ_NAMES (sizeof(subjRdn) / sizeof(CB_NameOid))
77
78 static CSSM_BOOL compareKeyData(const CSSM_KEY *key1, const CSSM_KEY *key2);
79 static CSSM_RETURN verifyCert(CSSM_CL_HANDLE clHand,
80 CSSM_CSP_HANDLE cspHand,
81 CSSM_DATA_PTR cert,
82 CSSM_DATA_PTR signerCert,
83 CSSM_KEY_PTR key,
84 CSSM_ALGORITHMS sigAlg,
85 CSSM_RETURN expectResult,
86 const char *opString);
87
88
89 int main(int argc, char **argv)
90 {
91 CSSM_CL_HANDLE clHand; // CL handle
92 CSSM_X509_NAME *subjName;
93 CSSM_X509_NAME *rootName;
94 CSSM_X509_TIME *notBefore; // UTC-style "not before" time
95 CSSM_X509_TIME *notAfter; // UTC-style "not after" time
96 CSSM_DATA_PTR rawCert; // from CSSM_CL_CertCreateTemplate
97 CSSM_DATA signedRootCert; // from CSSM_CL_CertSign
98 CSSM_DATA signedSubjCert; // from CSSM_CL_CertSign
99 CSSM_CSP_HANDLE cspHand; // CSP handle
100 CSSM_KEY subjPubKey; // subject's RSA public key blob
101 CSSM_KEY subjPrivKey; // subject's RSA private key - ref format
102 CSSM_KEY rootPubKey; // root's RSA public key blob
103 CSSM_KEY rootPrivKey; // root's RSA private key - ref format
104 CSSM_RETURN crtn;
105 CSSM_KEY_PTR extractRootKey; // from CSSM_CL_CertGetKeyInfo()
106 CSSM_KEY_PTR extractSubjKey; // ditto
107 CSSM_CC_HANDLE signContext; // for signing/verifying the cert
108 unsigned badByte;
109 int arg;
110 unsigned errorCount = 0;
111
112 /* user-spec'd variables */
113 CSSM_BOOL writeBlobs = CSSM_FALSE;
114 CSSM_ALGORITHMS keyAlg = KEY_ALG_DEFAULT;
115 CSSM_ALGORITHMS sigAlg = SIG_ALG_DEFAULT;
116 uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT;
117
118 /*
119 * Two extensions. Subject has one (KeyUsage); root has KeyUsage and
120 * BasicConstraints.
121 */
122 CSSM_X509_EXTENSION exts[2];
123 CE_KeyUsage keyUsage;
124 CE_BasicConstraints bc;
125
126 for(arg=1; arg<argc; arg++) {
127 switch(argv[arg][0]) {
128 case 'w':
129 writeBlobs = CSSM_TRUE;
130 break;
131 case 'a':
132 if((argv[arg][1] == '\0') || (argv[arg][2] == '\0')) {
133 usage(argv);
134 }
135 switch(argv[arg][2]) {
136 case 's':
137 keyAlg = CSSM_ALGID_RSA;
138 sigAlg = CSSM_ALGID_SHA1WithRSA;
139 break;
140 case 'm':
141 keyAlg = CSSM_ALGID_RSA;
142 sigAlg = CSSM_ALGID_MD5WithRSA;
143 break;
144 case 'f':
145 keyAlg = CSSM_ALGID_FEE;
146 sigAlg = CSSM_ALGID_FEE_MD5;
147 break;
148 case 'F':
149 keyAlg = CSSM_ALGID_FEE;
150 sigAlg = CSSM_ALGID_FEE_SHA1;
151 break;
152 case 'e':
153 keyAlg = CSSM_ALGID_FEE;
154 sigAlg = CSSM_ALGID_SHA1WithECDSA;
155 break;
156 case 'E':
157 keyAlg = CSSM_ALGID_ECDSA;
158 sigAlg = CSSM_ALGID_SHA1WithECDSA;
159 break;
160 case '7':
161 keyAlg = CSSM_ALGID_ECDSA;
162 sigAlg = CSSM_ALGID_SHA256WithECDSA;
163 break;
164 case '8':
165 keyAlg = CSSM_ALGID_ECDSA;
166 sigAlg = CSSM_ALGID_SHA384WithECDSA;
167 break;
168 case '9':
169 keyAlg = CSSM_ALGID_ECDSA;
170 sigAlg = CSSM_ALGID_SHA512WithECDSA;
171 break;
172 case '2':
173 keyAlg = CSSM_ALGID_RSA;
174 sigAlg = CSSM_ALGID_SHA224WithRSA;
175 break;
176 case '6':
177 keyAlg = CSSM_ALGID_RSA;
178 sigAlg = CSSM_ALGID_SHA256WithRSA;
179 break;
180 case '3':
181 keyAlg = CSSM_ALGID_RSA;
182 sigAlg = CSSM_ALGID_SHA384WithRSA;
183 break;
184 case '5':
185 keyAlg = CSSM_ALGID_RSA;
186 sigAlg = CSSM_ALGID_SHA512WithRSA;
187 break;
188 default:
189 usage(argv);
190 }
191 break;
192 case 'k':
193 keySizeInBits = atoi(&argv[arg][2]);
194 break;
195 default:
196 usage(argv);
197 }
198 }
199
200 /* connect to CL and CSP */
201 clHand = clStartup();
202 if(clHand == 0) {
203 return 0;
204 }
205 cspHand = cspStartup();
206 if(cspHand == 0) {
207 return 0;
208 }
209
210 /* subsequent errors to abort: to detach */
211
212 /* cook up an RSA key pair for the subject */
213 crtn = cspGenKeyPair(cspHand,
214 keyAlg,
215 SUBJ_KEY_LABEL,
216 strlen(SUBJ_KEY_LABEL),
217 keySizeInBits,
218 &subjPubKey,
219 CSSM_FALSE, // pubIsRef - should work both ways, but not yet
220 CSSM_KEYUSE_VERIFY,
221 CSSM_KEYBLOB_RAW_FORMAT_NONE,
222 &subjPrivKey,
223 CSSM_FALSE, // privIsRef
224 CSSM_KEYUSE_SIGN,
225 CSSM_KEYBLOB_RAW_FORMAT_NONE,
226 CSSM_FALSE);
227 if(crtn) {
228 errorCount++;
229 goto abort;
230 }
231 if(writeBlobs) {
232 writeFile(SUBJ_PRIV_KEY_FILE, subjPrivKey.KeyData.Data,
233 subjPrivKey.KeyData.Length);
234 printf("...wrote %lu bytes to %s\n", subjPrivKey.KeyData.Length,
235 SUBJ_PRIV_KEY_FILE);
236 }
237
238 /* and the root */
239 crtn = cspGenKeyPair(cspHand,
240 keyAlg,
241 ROOT_KEY_LABEL,
242 strlen(ROOT_KEY_LABEL),
243 keySizeInBits,
244 &rootPubKey,
245 CSSM_FALSE, // pubIsRef - should work both ways, but not yet
246 CSSM_KEYUSE_VERIFY,
247 CSSM_KEYBLOB_RAW_FORMAT_NONE,
248 &rootPrivKey,
249 CSSM_FALSE, // privIsRef
250 CSSM_KEYUSE_SIGN,
251 CSSM_KEYBLOB_RAW_FORMAT_NONE,
252 CSSM_FALSE);
253 if(crtn) {
254 errorCount++;
255 goto abort;
256 }
257 if(writeBlobs) {
258 writeFile(ROOT_PRIV_KEY_FILE, rootPrivKey.KeyData.Data,
259 rootPrivKey.KeyData.Length);
260 printf("...wrote %lu bytes to %s\n", rootPrivKey.KeyData.Length,
261 ROOT_PRIV_KEY_FILE);
262 }
263
264 if(compareKeyData(&rootPubKey, &subjPubKey)) {
265 printf("**WARNING: Identical root and subj keys!\n");
266 }
267
268 /*
269 * Cook up various cert fields.
270 * First, the RDNs for subject and issuer.
271 */
272 rootName = CB_BuildX509Name(rootRdn, NUM_ROOT_NAMES);
273 subjName = CB_BuildX509Name(subjRdn, NUM_SUBJ_NAMES);
274 if((rootName == NULL) || (subjName == NULL)) {
275 printf("CB_BuildX509Name failure");
276 errorCount++;
277 goto abort;
278 }
279
280 /* not before/after in generalized time format */
281 notBefore = CB_BuildX509Time(0);
282 notAfter = CB_BuildX509Time(10000);
283
284 /* A KeyUsage extension for both certs */
285 exts[0].extnId = CSSMOID_KeyUsage;
286 exts[0].critical = CSSM_FALSE;
287 exts[0].format = CSSM_X509_DATAFORMAT_PARSED;
288 keyUsage = CE_KU_DigitalSignature | CE_KU_KeyCertSign |
289 CE_KU_KeyEncipherment | CE_KU_DataEncipherment;
290 exts[0].value.parsedValue = &keyUsage;
291 exts[0].BERvalue.Data = NULL;
292 exts[0].BERvalue.Length = 0;
293
294 /* BasicConstraints for root only */
295 exts[1].extnId = CSSMOID_BasicConstraints;
296 exts[1].critical = CSSM_TRUE;
297 exts[1].format = CSSM_X509_DATAFORMAT_PARSED;
298 bc.cA = CSSM_TRUE;
299 bc.pathLenConstraintPresent = CSSM_TRUE;
300 bc.pathLenConstraint = 2;
301 exts[1].value.parsedValue = &bc;
302 exts[1].BERvalue.Data = NULL;
303 exts[1].BERvalue.Length = 0;
304
305 /* cook up root cert */
306 printf("Creating root cert...\n");
307 rawCert = CB_MakeCertTemplate(clHand,
308 0x12345678, // serial number
309 rootName,
310 rootName,
311 notBefore,
312 notAfter,
313 &rootPubKey,
314 sigAlg,
315 NULL, // subjUniqueId
316 NULL, // issuerUniqueId
317 exts, // extensions
318 2); // numExtensions
319
320 if(rawCert == NULL) {
321 errorCount++;
322 goto abort;
323 }
324 if(writeBlobs) {
325 writeFile(ROOT_TBS_FILE_NAME, rawCert->Data, rawCert->Length);
326 printf("...wrote %lu bytes to %s\n", rawCert->Length, ROOT_TBS_FILE_NAME);
327 }
328
329 /* Self-sign; this is a root cert */
330 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
331 sigAlg,
332 NULL, // AccessCred
333 &rootPrivKey,
334 &signContext);
335 if(crtn) {
336 printError("CSSM_CSP_CreateSignatureContext", crtn);
337 errorCount++;
338 goto abort;
339 }
340 signedRootCert.Data = NULL;
341 signedRootCert.Length = 0;
342 crtn = CSSM_CL_CertSign(clHand,
343 signContext,
344 rawCert, // CertToBeSigned
345 NULL, // SignScope
346 0, // ScopeSize,
347 &signedRootCert);
348 if(crtn) {
349 printError("CSSM_CL_CertSign", crtn);
350 errorCount++;
351 goto abort;
352 }
353 crtn = CSSM_DeleteContext(signContext);
354 if(crtn) {
355 printError("CSSM_DeleteContext", crtn);
356 errorCount++;
357 goto abort;
358 }
359 appFreeCssmData(rawCert, CSSM_TRUE);
360 if(writeBlobs) {
361 writeFile(ROOT_CERT_FILE_NAME, signedRootCert.Data, signedRootCert.Length);
362 printf("...wrote %lu bytes to %s\n", signedRootCert.Length,
363 ROOT_CERT_FILE_NAME);
364 }
365
366 /* now a subject cert signed by the root cert */
367 printf("Creating subject cert...\n");
368 rawCert = CB_MakeCertTemplate(clHand,
369 0x8765, // serial number
370 rootName,
371 subjName,
372 notBefore,
373 notAfter,
374 &subjPubKey,
375 sigAlg,
376 NULL, // subjUniqueId
377 NULL, // issuerUniqueId
378 exts, // extensions
379 1); // numExtensions
380 if(rawCert == NULL) {
381 errorCount++;
382 goto abort;
383 }
384 if(writeBlobs) {
385 writeFile(SUBJ_TBS_FILE_NAME, rawCert->Data, rawCert->Length);
386 printf("...wrote %lu bytes to %s\n", rawCert->Length, SUBJ_TBS_FILE_NAME);
387 }
388
389 /* sign by root */
390 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
391 sigAlg,
392 NULL, // AccessCred
393 &rootPrivKey,
394 &signContext);
395 if(crtn) {
396 printError("CSSM_CSP_CreateSignatureContext", crtn);
397 errorCount++;
398 goto abort;
399 }
400 signedSubjCert.Data = NULL;
401 signedSubjCert.Length = 0;
402 crtn = CSSM_CL_CertSign(clHand,
403 signContext,
404 rawCert, // CertToBeSigned
405 NULL, // SignScope
406 0, // ScopeSize,
407 &signedSubjCert);
408 if(crtn) {
409 printError("CSSM_CL_CertSign", crtn);
410 errorCount++;
411 goto abort;
412 }
413 crtn = CSSM_DeleteContext(signContext);
414 if(crtn) {
415 printError("CSSM_DeleteContext", crtn);
416 errorCount++;
417 goto abort;
418 }
419 appFreeCssmData(rawCert, CSSM_TRUE);
420 if(writeBlobs) {
421 writeFile(SUBJ_CERT_FILE_NAME, signedSubjCert.Data, signedSubjCert.Length);
422 printf("...wrote %lu bytes to %s\n", signedSubjCert.Length,
423 SUBJ_CERT_FILE_NAME);
424 }
425
426 /* Free the stuff we allocd to get here */
427 CB_FreeX509Name(rootName);
428 CB_FreeX509Name(subjName);
429 CB_FreeX509Time(notBefore);
430 CB_FreeX509Time(notAfter);
431
432 /*
433 * Extract public keys from the two certs, verify.
434 */
435 crtn = CSSM_CL_CertGetKeyInfo(clHand, &signedSubjCert, &extractSubjKey);
436 if(crtn) {
437 printError("CSSM_CL_CertGetKeyInfo", crtn);
438 }
439 else {
440 /* compare key data - header is different.
441 * Known header differences:
442 * -- CspID - CSSM_CL_CertGetKeyInfo returns a key with NULL for
443 * this field
444 * -- Format. rootPubKey : 6 (CSSM_KEYBLOB_RAW_FORMAT_BSAFE)
445 * extractRootKey : 1 (CSSM_KEYBLOB_RAW_FORMAT_PKCS1)
446 * -- KeyAttr. rootPubKey : 0x20 (CSSM_KEYATTR_EXTRACTABLE)
447 * extractRootKey : 0x0
448 */
449 if(!compareKeyData(extractSubjKey, &subjPubKey)) {
450 printf("***CSSM_CL_CertGetKeyInfo(signedSubjCert) returned bad key data\n");
451 }
452 if(extractSubjKey->KeyHeader.LogicalKeySizeInBits !=
453 subjPubKey.KeyHeader.LogicalKeySizeInBits) {
454 printf("***EffectiveKeySizeInBits mismatch: extract %u subj %u\n",
455 (unsigned)extractSubjKey->KeyHeader.LogicalKeySizeInBits,
456 (unsigned)subjPubKey.KeyHeader.LogicalKeySizeInBits);
457 }
458 }
459 crtn = CSSM_CL_CertGetKeyInfo(clHand, &signedRootCert, &extractRootKey);
460 if(crtn) {
461 printError("CSSM_CL_CertGetKeyInfo", crtn);
462 }
463 else {
464 if(!compareKeyData(extractRootKey, &rootPubKey)) {
465 printf("***CSSM_CL_CertGetKeyInfo(signedRootCert) returned bad key data\n");
466 }
467 }
468
469 /*
470 * Verify:
471 */
472 printf("Verifying certificates...\n");
473
474 /*
475 * Verify root cert by root pub key, should succeed.
476 */
477 if(verifyCert(clHand,
478 cspHand,
479 &signedRootCert,
480 NULL,
481 &rootPubKey,
482 sigAlg,
483 CSSM_OK,
484 "Verify(root by root key)")) {
485 errorCount++;
486 /* continue */
487 }
488
489 /*
490 * Verify root cert by root cert, should succeed.
491 */
492 if(verifyCert(clHand,
493 cspHand,
494 &signedRootCert,
495 &signedRootCert,
496 NULL,
497 CSSM_ALGID_NONE, // sigAlg not used here
498 CSSM_OK,
499 "Verify(root by root cert)")) {
500 errorCount++;
501 /* continue */
502 }
503
504
505 /*
506 * Verify subject cert by root pub key, should succeed.
507 */
508 if(verifyCert(clHand,
509 cspHand,
510 &signedSubjCert,
511 NULL,
512 &rootPubKey,
513 sigAlg,
514 CSSM_OK,
515 "Verify(subj by root key)")) {
516 errorCount++;
517 /* continue */
518 }
519
520 /*
521 * Verify subject cert by root cert, should succeed.
522 */
523 if(verifyCert(clHand,
524 cspHand,
525 &signedSubjCert,
526 &signedRootCert,
527 NULL,
528 CSSM_ALGID_NONE, // sigAlg not used here
529 CSSM_OK,
530 "Verify(subj by root cert)")) {
531 errorCount++;
532 /* continue */
533 }
534
535 /*
536 * Verify subject cert by root cert AND key, should succeed.
537 */
538 if(verifyCert(clHand,
539 cspHand,
540 &signedSubjCert,
541 &signedRootCert,
542 &rootPubKey,
543 sigAlg,
544 CSSM_OK,
545 "Verify(subj by root cert and key)")) {
546 errorCount++;
547 /* continue */
548 }
549
550 /*
551 * Verify subject cert by extracted root pub key, should succeed.
552 */
553 if(verifyCert(clHand,
554 cspHand,
555 &signedSubjCert,
556 NULL,
557 extractRootKey,
558 sigAlg,
559 CSSM_OK,
560 "Verify(subj by extracted root key)")) {
561 errorCount++;
562 /* continue */
563 }
564
565 /*
566 * Verify subject cert by subject pub key, should fail.
567 */
568 if(verifyCert(clHand,
569 cspHand,
570 &signedSubjCert,
571 NULL,
572 &subjPubKey,
573 sigAlg,
574 CSSMERR_CL_VERIFICATION_FAILURE,
575 "Verify(subj by subj key)")) {
576 errorCount++;
577 /* continue */
578 }
579
580 /*
581 * Verify subject cert by subject cert, should fail.
582 */
583 if(verifyCert(clHand,
584 cspHand,
585 &signedSubjCert,
586 &signedSubjCert,
587 NULL,
588 CSSM_ALGID_NONE, // sigAlg not used here
589 CSSMERR_CL_VERIFICATION_FAILURE,
590 "Verify(subj by subj cert)")) {
591 errorCount++;
592 /* continue */
593 }
594
595 /*
596 * Verify erroneous subject cert by root pub key, should fail.
597 */
598 badByte = genRand(1, signedSubjCert.Length - 1);
599 signedSubjCert.Data[badByte] ^= 0x55;
600 if(verifyCert(clHand,
601 cspHand,
602 &signedSubjCert,
603 NULL,
604 &rootPubKey,
605 sigAlg,
606 CSSMERR_CL_VERIFICATION_FAILURE,
607 "Verify(bad subj by root key)")) {
608 errorCount++;
609 /* continue */
610 }
611
612
613 /* free/delete certs and keys */
614 appFreeCssmData(&signedSubjCert, CSSM_FALSE);
615 appFreeCssmData(&signedRootCert, CSSM_FALSE);
616
617 cspFreeKey(cspHand, &rootPubKey);
618 cspFreeKey(cspHand, &subjPubKey);
619
620 /* These don't work because CSSM_CL_CertGetKeyInfo() gives keys with
621 * a bogus GUID. This may be a problem with the Apple CSP...
622 *
623 cspFreeKey(cspHand, extractRootKey);
624 cspFreeKey(cspHand, extractSubjKey);
625 *
626 * do it this way instead...*/
627 CSSM_FREE(extractRootKey->KeyData.Data);
628 CSSM_FREE(extractSubjKey->KeyData.Data);
629
630 /* need to do this regardless...*/
631 CSSM_FREE(extractRootKey);
632 CSSM_FREE(extractSubjKey);
633
634 abort:
635 if(cspHand != 0) {
636 CSSM_ModuleDetach(cspHand);
637 }
638
639 if(errorCount) {
640 printf("Signer/Subject test failed with %d errors\n", errorCount);
641 }
642 else {
643 printf("Signer/Subject test succeeded\n");
644 }
645 return 0;
646 }
647
648
649 /* compare KeyData for two keys. */
650 static CSSM_BOOL compareKeyData(const CSSM_KEY *key1, const CSSM_KEY *key2)
651 {
652 if(key1->KeyData.Length != key2->KeyData.Length) {
653 return CSSM_FALSE;
654 }
655 if(memcmp(key1->KeyData.Data,
656 key2->KeyData.Data,
657 key1->KeyData.Length)) {
658 return CSSM_FALSE;
659 }
660 return CSSM_TRUE;
661 }
662
663 /* verify a cert using specified key and/or signerCert */
664 static CSSM_RETURN verifyCert(CSSM_CL_HANDLE clHand,
665 CSSM_CSP_HANDLE cspHand,
666 CSSM_DATA_PTR cert,
667 CSSM_DATA_PTR signerCert, // optional
668 CSSM_KEY_PTR key, // ditto, to work spec one, other, or both
669 CSSM_ALGORITHMS sigAlg, // CSSM_ALGID_SHA1WithRSA, etc.
670 CSSM_RETURN expectResult,
671 const char *opString)
672 {
673 CSSM_RETURN crtn;
674 CSSM_CC_HANDLE signContext = CSSM_INVALID_HANDLE;
675
676 if(key) {
677 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
678 sigAlg,
679 NULL, // AccessCred
680 key,
681 &signContext);
682 if(crtn) {
683 printf("Failure during %s\n", opString);
684 printError("CSSM_CSP_CreateSignatureContext", crtn);
685 return crtn;
686 }
687 }
688 crtn = CSSM_CL_CertVerify(clHand,
689 signContext,
690 cert, // CertToBeVerified
691 signerCert, // SignerCert
692 NULL, // VerifyScope
693 0); // ScopeSize
694 if(crtn != expectResult) {
695 printf("Failure during %s\n", opString);
696 if(crtn == CSSM_OK) {
697 printf("Unexpected CSSM_CL_CertVerify success\n");
698 }
699 else if(expectResult == CSSM_OK) {
700 printError("CSSM_CL_CertVerify", crtn);
701 }
702 else {
703 printError("CSSM_CL_CertVerify: expected", expectResult);
704 printError("CSSM_CL_CertVerify: got ", crtn);
705 }
706 return CSSMERR_CL_VERIFICATION_FAILURE;
707 }
708 if(signContext != CSSM_INVALID_HANDLE) {
709 crtn = CSSM_DeleteContext(signContext);
710 if(crtn) {
711 printf("Failure during %s\n", opString);
712 printError("CSSM_DeleteContext", crtn);
713 return crtn;
714 }
715 }
716 return CSSM_OK;
717 }