2 * cgVerifyParsed.cpp - basic test of TP's CertGroupVerify using parsed anchors
4 * ------- THIS TEST IS OBSOLETE; WE DON'T SUPPORT PARSED ANCHORS ----------
6 * cook up array of n key pairs;
7 * cook up cert chain to go with them;
9 * numCerts = total # of incoming certs;
10 * test one of four or five "expected result" cases {
11 * case root in certGroup but not found in AnchorCerts:
12 * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1];
13 * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-2];
14 * expErr = CSSMERR_TP_INVALID_ANCHOR_CERT;
15 * expEvidenceSize = numCerts;
16 * case root in certGroup, found a copy in AnchorCerts:
17 * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1];
18 * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-1];
20 * expEvidenceSize = numCerts;
21 * case verified by an AnchorCert:
22 * n = rand(1, numCerts-2);
23 * certGroup = tpMakeRandCertGroup(certs[0..n]);
24 * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-2];
26 * expEvidenceSize = n+2;
28 * n = rand(1, numCerts-3);
29 * certGroup = tpMakeRandCertGroup(certs[0..n]);
30 * anchorCerts = tpMakeRandCertGroup[certs[n+2...numCerts-2];
31 * anchorCerts may be empty....
32 * expErr = CSSMERR_TP_NOT_TRUSTED;
33 * expEvidenceSize = n+1;
34 * case incomplete public key (DSA only):
35 * root public keys is incomplete;
36 * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1];
37 * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-1];
39 * expEvidenceSize = numCerts;
41 * result = certGroupVerify();
42 * verify expected result and getError();
43 * delete certs from DB;
47 #include <Security/cssm.h>
48 #include <utilLib/common.h>
49 #include <utilLib/cspwrap.h>
50 #include <clAppUtils/clutils.h>
51 #include <clAppUtils/tpUtils.h>
52 #include <clAppUtils/timeStr.h>
53 #include <utilLib/nssAppUtils.h>
54 #include <utilLib/fileIo.h>
59 #include <sys/types.h>
61 #include <Security/oidsalg.h>
62 #include "tpVerifyParsed.h"
64 #define NUM_CERTS_DEF 10
65 #define KEYGEN_ALG_DEF CSSM_ALGID_RSA
66 #define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA
68 #define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */
69 //#define SECONDS_TO_LIVE 5
72 #define DB_NAME "cgVerify.db"
73 #define DSA_PARAM_FILE "dsaParam512.der"
76 * How we define the "expected result".
79 ER_InvalidAnchor
, // root in certGroup, not found in AnchorCerts
80 ER_RootInCertGroup
, // root in certGroup, copy in AnchorCerts
81 ER_AnchorVerify
, // end of chain verified by an anchor
82 ER_NoRoot
, // no root, no anchor verify
83 ER_IncompleteKey
// un-completable public key (all keys are partial), DSA
87 static void usage(char **argv
)
89 printf("Usage: %s [options]\n", argv
[0]);
90 printf(" Options:\n");
91 printf(" n=numCerts; default = %d\n", NUM_CERTS_DEF
);
92 printf(" l=loops; default=%d; 0=forever\n", LOOPS_DEF
);
93 printf(" a=alg (f=FEE/MD5, F=FEE/SHA1, e=FEE/ECDSA, s=RSA/SHA1, m=RSA/MD5,\n");
94 printf(" d=DSA; 6=RSA/SHA256, 3=RSA/SHA384, 5=RSA/SHA512; default = RSA/SHA1\n");
95 printf(" k=keySizeInBits\n");
96 printf(" d(isable DB)\n");
97 printf(" P(ause on each loop)\n");
98 printf(" N (no partial pub keys)\n");
99 printf(" v(erbose)\n");
100 printf(" q(uiet)\n");
106 CSSM_TP_HANDLE tpHand
,
107 CSSM_CL_HANDLE clHand
,
108 CSSM_CSP_HANDLE cspHand
,
109 CSSM_DL_DB_HANDLE dlDb
,
112 CSSM_KEY_PTR pubKeys
, // for partial key detect
114 ExpectResult expectResult
,
118 unsigned cgEnd
; // last cert in certGroupFrag
119 unsigned anchorStart
; // first cert in anchorGroup
120 unsigned anchorEnd
; // last cert in anchorGroup
121 CSSM_CERTGROUP certGroupFrag
; // INPUT to CertGroupVerify
122 CSSM_CERTGROUP anchorCerts
; // ditto
123 unsigned die
; // random number
124 CSSM_DL_DB_LIST dbList
;
125 CSSM_DL_DB_LIST_PTR dbListPtr
;
126 CSSM_RETURN expErr
; // expected rtn from GroupVfy()
129 uint32 expEvidenceSize
; // expected evidenceSize
130 unsigned evidenceSize
; // actual evidence size
131 CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult
;
132 CSSM_CERTGROUP_PTR outGrp
= NULL
;
134 CSSM_DL_DB_HANDLE_PTR dlDbPtr
;
137 memset(&vfyResult
, 0, sizeof(CSSM_TP_VERIFY_CONTEXT_RESULT
));
141 dbList
.NumHandles
= 1;
142 dbList
.DLDBHandle
= &dlDb
;
151 /* the four test cases */
152 switch(expectResult
) {
153 case ER_InvalidAnchor
:
154 /* root in certGroup, not found in AnchorCerts */
155 cgEnd
= numCerts
- 1; // certGroupFrag is the whole pile
156 anchorStart
= 0; // anchors = all except root
157 anchorEnd
= numCerts
- 2;
158 expErr
= CSSMERR_TP_INVALID_ANCHOR_CERT
;
159 expEvidenceSize
= numCerts
;
160 expResStr
= "InvalidAnchor (root in certGroup but not in anchors)";
163 case ER_RootInCertGroup
:
164 /* root in certGroup, copy in AnchorCerts */
165 cgEnd
= numCerts
- 1; // certGroupFrag = the whole pile
166 anchorStart
= 0; // anchors = the whole pile
167 anchorEnd
= numCerts
- 1;
169 expEvidenceSize
= numCerts
;
170 expResStr
= "Good (root in certGroup AND in anchors)";
173 case ER_AnchorVerify
:
174 /* non-root end of chain verified by an anchor */
175 /* break chain at random place other than end */
176 /* die is the last cert in certGroupFrag */
177 die
= genRand(0, numCerts
-2);
178 cgEnd
= die
; // certGroupFrag up to break point
179 anchorStart
= 0; // anchors = all
180 anchorEnd
= numCerts
- 1;
181 if(pubKeys
[die
+1].KeyHeader
.KeyAttr
& CSSM_KEYATTR_PARTIAL
) {
182 /* this will fail due to an unusable anchor */
183 expErr
= CSSMERR_TP_CERTIFICATE_CANT_OPERATE
;
184 expResStr
= "Root ONLY in anchors but has partial pub key";
188 expResStr
= "Good (root ONLY in anchors)";
190 /* size = # certs in certGroupFrag, plus one anchor */
191 expEvidenceSize
= die
+ 2;
195 /* no root, no anchor verify */
196 /* break chain at random place other than end */
197 /* die is the last cert in certGroupFrag */
198 /* skip a cert, then anchors start at die + 2 */
199 die
= genRand(0, numCerts
-2);
200 cgEnd
= die
; // certGroupFrag up to break point
201 anchorStart
= die
+ 2; // anchors = n+1...numCerts-2
202 // may be empty if n == numCerts-2
203 anchorEnd
= numCerts
- 2;
204 if((die
!= 0) && // partial leaf not reported as partial!
205 (pubKeys
[die
].KeyHeader
.KeyAttr
& CSSM_KEYATTR_PARTIAL
)) {
206 /* this will fail due to an unusable cert (this one) */
207 expErr
= CSSMERR_TP_CERTIFICATE_CANT_OPERATE
;
208 expResStr
= "Not Trusted (no root, no anchor verify), partial";
211 expErr
= CSSMERR_TP_NOT_TRUSTED
;
212 expResStr
= "Not Trusted (no root, no anchor verify)";
214 expEvidenceSize
= die
+ 1;
217 case ER_IncompleteKey
:
219 * Anchor has incomplete pub key
220 * Root in certGroup, copy in AnchorCerts
221 * Avoid putting anchor in certGroupFrag because the TP will think
222 * it's NOT a root and it'll show up twice in the evidence - once
223 * from certGroupFrag (at which point the search for a root
224 * keeps going), and once from Anchors.
226 cgEnd
= numCerts
- 2; // certGroupFrag = the whole pile less the anchor
227 anchorStart
= 0; // anchors = the whole pile
228 anchorEnd
= numCerts
- 1;
229 expErr
= CSSMERR_TP_CERTIFICATE_CANT_OPERATE
;
230 expEvidenceSize
= numCerts
;
231 expResStr
= "Partial public key in anchor";
236 printf(" ...expectResult = %s\n", expResStr
);
239 /* cook up two cert groups */
241 printf(" ...building certGroupFrag from certs[0..%d]\n",
244 if(tpMakeRandCertGroup(clHand
,
246 certs
, // certGroupFrag always starts at 0
247 cgEnd
+1, // # of certs
249 CSSM_TRUE
, // firstCertIsSubject
251 CSSM_FALSE
, // allInDbs
252 CSSM_FALSE
)) { // skipFirstDb
253 printf("Error in tpMakeRandCertGroup\n");
258 printf(" ...building anchorCerts from certs[%d..%d]\n",
259 anchorStart
, anchorEnd
);
261 if(anchorEnd
> (numCerts
- 1)) {
262 printf("anchorEnd overflow\n");
265 if(anchorStart
>= anchorEnd
) {
266 /* legal in some corner cases, ==> empty enchors */
270 numAnchors
= anchorEnd
- anchorStart
+ 1;
272 /* anchors do not go in DB */
273 if(tpMakeRandCertGroup(clHand
,
276 numAnchors
, // # of certs
278 CSSM_FALSE
, // firstCertIsSubject
280 CSSM_FALSE
, // allInDbs
281 CSSM_FALSE
)) { // skipFirstDb
282 printf("Error in tpMakeRandCertGroup\n");
286 crtn
= tpCertGroupVerifyParsed(
291 &CSSMOID_APPLE_X509_BASIC
, // policy
296 anchorCerts
.GroupList
.CertList
, // passed as CSSM_DATA_PTR, not CERTGROUP....
297 anchorCerts
.NumCerts
,
298 CSSM_TP_STOP_ON_POLICY
,
302 /* first verify format of result */
303 if( (vfyResult
.NumberOfEvidences
!= 3) ||
304 (vfyResult
.Evidence
== NULL
) ||
305 (vfyResult
.Evidence
[0].EvidenceForm
!= CSSM_EVIDENCE_FORM_APPLE_HEADER
) ||
306 (vfyResult
.Evidence
[1].EvidenceForm
!= CSSM_EVIDENCE_FORM_APPLE_CERTGROUP
) ||
307 (vfyResult
.Evidence
[2].EvidenceForm
!= CSSM_EVIDENCE_FORM_APPLE_CERT_INFO
) ||
308 (vfyResult
.Evidence
[0].Evidence
== NULL
) ||
309 (vfyResult
.Evidence
[1].Evidence
== NULL
) ||
310 (vfyResult
.Evidence
[2].Evidence
== NULL
)) {
311 printf("***Malformed VerifyContextResult\n");
312 rtn
= testError(quiet
);
317 if((vfyResult
.Evidence
!= NULL
) && (vfyResult
.Evidence
[1].Evidence
!= NULL
)) {
318 outGrp
= (CSSM_CERTGROUP_PTR
)vfyResult
.Evidence
[1].Evidence
;
319 evidenceSize
= outGrp
->NumCerts
;
322 /* in case no evidence returned */
325 if((crtn
!= expErr
) ||
326 (evidenceSize
!= expEvidenceSize
)) {
327 printf("***Error on expectResult %s\n", expResStr
);
328 printf(" err %s expErr %s\n",
329 cssmErrToStr(crtn
), cssmErrToStr(expErr
));
330 printf(" evidenceSize %d expEvidenceSize %lu\n",
331 evidenceSize
, expEvidenceSize
);
332 rtn
= testError(quiet
);
339 tpFreeCertGroup(&certGroupFrag
,
340 CSSM_FALSE
, // caller malloc'd the actual certs
341 CSSM_FALSE
); // struct is on stack
342 tpFreeCertGroup(&anchorCerts
,
343 CSSM_FALSE
, // caller malloc'd the actual certs
344 CSSM_FALSE
); // struct is on stack
345 freeVfyResult(&vfyResult
);
347 clDeleteAllCerts(dlDb
);
352 int main(int argc
, char **argv
)
357 CSSM_TP_HANDLE tpHand
= 0;
358 CSSM_CL_HANDLE clHand
= 0;
359 CSSM_CSP_HANDLE cspHand
= 0;
360 CSSM_DL_DB_HANDLE dlDbHand
= {0, 0};
361 ExpectResult expectResult
;
366 CSSM_DATA_PTR paramDataP
= NULL
;
367 unsigned numTests
= 4;
369 /* all three of these are arrays with numCert elements */
370 CSSM_KEY_PTR pubKeys
= NULL
;
371 CSSM_KEY_PTR privKeys
= NULL
;
372 CSSM_DATA_PTR certs
= NULL
;
374 /* Keys do NOT go in the cert DB */
375 CSSM_DL_DB_HANDLE keyDb
= {0, 0};
376 CSSM_KEY savedRoot
; // for ER_IncompleteKey
381 unsigned loops
= LOOPS_DEF
;
382 CSSM_BOOL verbose
= CSSM_FALSE
;
383 CSSM_BOOL quiet
= CSSM_FALSE
;
384 unsigned numCerts
= NUM_CERTS_DEF
;
385 uint32 keyGenAlg
= KEYGEN_ALG_DEF
;
386 uint32 sigAlg
= SIG_ALG_DEF
;
388 CSSM_BOOL useDb
= CSSM_TRUE
;
390 CSSM_BOOL useDb
= CSSM_FALSE
;
392 CSSM_BOOL doPause
= CSSM_FALSE
;
393 uint32 keySizeInBits
= CSP_KEY_SIZE_DEFAULT
;
394 CSSM_BOOL noPartialKeys
= CSSM_FALSE
;
395 char dbName
[100]; /* DB_NAME_pid */
397 for(arg
=1; arg
<argc
; arg
++) {
401 loops
= atoi(&argp
[2]);
404 keySizeInBits
= atoi(&argp
[2]);
407 numCerts
= atoi(&argp
[2]);
418 keyGenAlg
= CSSM_ALGID_FEE
;
419 sigAlg
= CSSM_ALGID_FEE_MD5
;
422 keyGenAlg
= CSSM_ALGID_FEE
;
423 sigAlg
= CSSM_ALGID_FEE_SHA1
;
426 keyGenAlg
= CSSM_ALGID_FEE
;
427 sigAlg
= CSSM_ALGID_SHA1WithECDSA
;
430 keyGenAlg
= CSSM_ALGID_RSA
;
431 sigAlg
= CSSM_ALGID_SHA1WithRSA
;
434 keyGenAlg
= CSSM_ALGID_RSA
;
435 sigAlg
= CSSM_ALGID_MD5WithRSA
;
438 keyGenAlg
= CSSM_ALGID_DSA
;
439 sigAlg
= CSSM_ALGID_SHA1WithDSA
;
442 keyGenAlg
= CSSM_ALGID_RSA
;
443 sigAlg
= CSSM_ALGID_SHA256WithRSA
;
446 keyGenAlg
= CSSM_ALGID_RSA
;
447 sigAlg
= CSSM_ALGID_SHA512WithRSA
;
450 keyGenAlg
= CSSM_ALGID_RSA
;
451 sigAlg
= CSSM_ALGID_SHA512WithRSA
;
458 noPartialKeys
= CSSM_TRUE
;
472 sprintf(dbName
, "%s_%d", DB_NAME
, (int)getpid());
475 printf("Can't run with cert chain smaller than 2\n");
479 /* attach to all the modules we need */
480 cspHand
= cspStartup();
486 dlDbHand
.DLHandle
= dlStartup();
487 if(dlDbHand
.DLHandle
== 0) {
490 CSSM_RETURN crtn
= tpKcOpen(dlDbHand
.DLHandle
, dbName
, dbName
,
491 CSSM_TRUE
, &dlDbHand
.DBHandle
);
493 printf("Error opening keychain %s; aborting.\n", dbName
);
498 clHand
= clStartup();
502 tpHand
= tpStartup();
507 /* malloc empty keys and certs */
508 pubKeys
= (CSSM_KEY_PTR
)CSSM_CALLOC(numCerts
, sizeof(CSSM_KEY
));
509 privKeys
= (CSSM_KEY_PTR
)CSSM_CALLOC(numCerts
, sizeof(CSSM_KEY
));
510 certs
= (CSSM_DATA_PTR
)CSSM_CALLOC(numCerts
, sizeof(CSSM_DATA
));
511 if((pubKeys
== NULL
) || (privKeys
== NULL
) || (certs
== NULL
)) {
512 printf("not enough memory for %u keys pairs and certs.\n",
517 printf("Starting cgVerify; args: ");
518 for(i
=1; i
<(unsigned)argc
; i
++) {
519 printf("%s ", argv
[i
]);
523 /* generate key pairs */
525 printf("generating keys...\n");
527 if(keyGenAlg
== CSSM_ALGID_DSA
) {
529 if(!readFile(DSA_PARAM_FILE
, (unsigned char **)¶mData
.Data
, &len
)) {
531 printf("...using DSA params from %s\n", DSA_PARAM_FILE
);
533 paramData
.Length
= len
;
534 paramDataP
= ¶mData
;
537 printf("***warning: no param file. KeyGen is going to be slow!\n");
538 printf("***You might consider running this from the clxutils/cgVerify "
542 if(tpGenKeys(cspHand
,
547 "cgVerify", // keyLabelBase
553 notBeforeStr
= genTimeAtNowPlus(0);
554 notAfterStr
= genTimeAtNowPlus(SECONDS_TO_LIVE
);
557 * If DSA, insert some random partial public keys which are not
558 * fatal (i.e., root can not be partial). We include the leaf in this
559 * loop - the TP is *supposed* to ignore that situation, ane we make
562 if((keyGenAlg
== CSSM_ALGID_DSA
) && !noPartialKeys
) {
563 for(unsigned dex
=0; dex
<(numCerts
-1); dex
++) {
564 int die
= genRand(0,1);
566 /* this one gets partialized */
569 printf("...making partial DSA pub key at index %u\n", dex
);
571 CSSM_RETURN crtn
= extractDsaPartial(cspHand
, &pubKeys
[dex
], &newKey
);
573 printf("***Error converting to partial key. Aborting.\n");
576 CSSM_FREE(pubKeys
[dex
].KeyData
.Data
);
577 pubKeys
[dex
] = newKey
;
582 printf("starting %s test\n", argv
[0]);
585 if(keyGenAlg
== CSSM_ALGID_DSA
) {
588 for(loop
=1; ; loop
++) {
590 printf("...loop %d\n", loop
);
593 /* cycle thru test scenarios */
594 switch(loop
% numTests
) {
596 expectResult
= ER_InvalidAnchor
;
599 expectResult
= ER_RootInCertGroup
;
602 expectResult
= ER_AnchorVerify
;
605 expectResult
= ER_NoRoot
;
609 expectResult
= ER_IncompleteKey
;
610 savedRoot
= pubKeys
[numCerts
-1];
611 /* make anchor unusable */
612 if(extractDsaPartial(cspHand
, &savedRoot
, &pubKeys
[numCerts
-1])) {
613 printf("...error partializing anchor key; aborting\n");
618 if(tpGenCerts(cspHand
,
622 "cgConstruct", // nameBase
644 for(i
=0; i
<numCerts
; i
++) {
645 appFreeCssmData(&certs
[i
], CSSM_FALSE
);
647 if(expectResult
== ER_IncompleteKey
) {
648 CSSM_FREE(pubKeys
[numCerts
-1].KeyData
.Data
);
649 pubKeys
[numCerts
-1] = savedRoot
;
652 memset(certs
, 0, numCerts
* sizeof(CSSM_DATA
));
653 if(loops
&& (loop
== loops
)) {
657 printf("Hit CR to continue: ");
663 if(privKeys
!= NULL
) {
664 for(i
=0; i
<numCerts
; i
++) {
665 if(privKeys
[i
].KeyData
.Data
!= NULL
) {
666 cspFreeKey(cspHand
, &privKeys
[i
]);
671 if(pubKeys
!= NULL
) {
672 for(i
=0; i
<numCerts
; i
++) {
673 if(pubKeys
[i
].KeyData
.Data
!= NULL
) {
674 cspFreeKey(cspHand
, &pubKeys
[i
]);
680 for(i
=0; i
<numCerts
; i
++) {
681 appFreeCssmData(&certs
[i
], CSSM_FALSE
);
686 CSSM_ModuleDetach(cspHand
);
689 CSSM_ModuleDetach(clHand
);
692 CSSM_ModuleDetach(tpHand
);
696 printf("%s test complete\n", argv
[0]);