1 /* cgVerifyThr.cpp - simple version CertGroupVerify test */
3 #include "testParams.h"
4 #include <Security/cssm.h>
5 #include <utilLib/common.h>
6 #include <utilLib/cspwrap.h>
7 #include <clAppUtils/clutils.h>
8 #include <clAppUtils/tpUtils.h>
9 #include <clAppUtils/timeStr.h>
14 #include <Security/oidsalg.h>
16 /* for memory leak debug only, with only one thread running */
19 /*** start of code directly copied from ../cgVerify/cgVerify.cpp ***/
20 #define NUM_CERTS_MIN 4
21 #define KEYGEN_ALG_DEF CSSM_ALGID_RSA
22 #define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA
24 #define CG_KEY_SIZE_DEFAULT CSP_RSA_KEY_SIZE_DEFAULT
25 #define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */
30 * How we define the "expected result".
33 ER_InvalidAnchor
, // root in certGroup, not found in AnchorCerts
34 ER_RootInCertGroup
, // root in certGroup, copy in AnchorCerts
35 ER_AnchorVerify
, // end of chain verified by an anchor
36 ER_NoRoot
// no root, no anchor verify
39 static int testError()
43 printf("Attach via debugger for more info.\n");
44 printf("a to abort, c to continue: ");
50 CSSM_TP_HANDLE tpHand
,
51 CSSM_CL_HANDLE clHand
,
52 CSSM_CSP_HANDLE cspHand
,
53 CSSM_DL_DB_HANDLE dlDb
,
57 ExpectResult expectResult
,
60 unsigned cgEnd
; // last cert in certGroupFrag
61 unsigned anchorStart
; // first cert in anchorGroup
62 unsigned anchorEnd
; // last cert in anchorGroup
63 CSSM_CERTGROUP certGroupFrag
; // INPUT to CertGroupVerify
64 CSSM_CERTGROUP anchorCerts
; // ditto
65 unsigned die
; // random number
66 CSSM_DL_DB_LIST dbList
;
67 CSSM_DL_DB_LIST_PTR dbListPtr
;
68 CSSM_DL_DB_HANDLE_PTR dlDbPtr
;
69 CSSM_RETURN expErr
; // expected rtn from GroupVfy()
71 const char *expResStr
;
72 uint32 expEvidenceSize
; // expected evidenceSize
73 unsigned evidenceSize
; // actual evidence size
74 CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult
;
75 CSSM_CERTGROUP_PTR outGrp
= NULL
;
78 memset(&vfyResult
, 0, sizeof(CSSM_TP_VERIFY_CONTEXT_RESULT
));
82 dbList
.NumHandles
= 1;
83 dbList
.DLDBHandle
= &dlDb
;
92 /* the four test cases */
93 switch(expectResult
) {
94 case ER_InvalidAnchor
:
95 /* root in certGroup, not found in AnchorCerts */
96 cgEnd
= numCerts
- 1; // certGroupFrag is the whole pile
97 anchorStart
= 0; // anchors = all except root
98 anchorEnd
= numCerts
- 2;
99 expErr
= CSSMERR_TP_INVALID_ANCHOR_CERT
;
100 expEvidenceSize
= numCerts
;
101 expResStr
= "InvalidAnchor (root in certGroup but not in anchors)";
104 case ER_RootInCertGroup
:
105 /* root in certGroup, copy in AnchorCerts */
106 cgEnd
= numCerts
- 1; // certGroupFrag = the whole pile
107 anchorStart
= 0; // anchors = the whole pile
108 anchorEnd
= numCerts
- 1;
110 expEvidenceSize
= numCerts
;
111 expResStr
= "Good (root in certGroup AND in anchors)";
114 case ER_AnchorVerify
:
115 /* non-root end of chain verified by an anchor */
116 /* break chain at random place other than start and end-2 */
117 die
= genRand(1, numCerts
-3);
118 cgEnd
= die
; // certGroupFrag up to break point
119 anchorStart
= 0; // anchors = all
120 anchorEnd
= numCerts
- 1;
122 /* size = # certs in certGroupFrag, plus one anchor */
123 expEvidenceSize
= die
+ 2;
124 expResStr
= "Good (root ONLY in anchors)";
128 /* no root, no anchor verify */
129 /* break chain at random place other than start and end-1 */
130 die
= genRand(1, numCerts
-2);
131 cgEnd
= die
; // certGroupFrag up to break point
132 /* and skip one cert */
133 anchorStart
= die
+ 2; // anchors = n+1...numCerts-2
134 // may be empty if n == numCerts-2
135 anchorEnd
= numCerts
- 1;
136 expErr
= CSSMERR_TP_NOT_TRUSTED
;
137 expEvidenceSize
= die
+ 1;
138 expResStr
= "Not Trusted (no root, no anchor verify)";
143 printf(" ...expectResult = %s\n", expResStr
);
146 /* cook up two cert groups */
148 printf(" ...building certGroupFrag from certs[0..%d]\n",
151 if(tpMakeRandCertGroup(clHand
,
153 certs
, // certGroupFrag always starts at 0
154 cgEnd
+1, // # of certs
156 CSSM_TRUE
, // firstCertIsSubject
158 CSSM_FALSE
, // allInDbs
159 CSSM_FALSE
)) { // skipFirstDb
160 printf("\nError in tpMakeRandCertGroup\n");
164 if(anchorStart
> anchorEnd
) {
165 /* legal for ER_NoRoot */
166 if((expectResult
!= ER_NoRoot
) || (anchorStart
!= numCerts
)) {
167 printf("Try again, pal.\n");
172 printf(" ...building anchorCerts from certs[%d..%d]\n",
173 anchorStart
, anchorEnd
);
175 if(anchorEnd
> (numCerts
- 1)) {
176 printf("anchorEnd overflow\n");
179 /* anchors do not go in DB */
180 if(tpMakeRandCertGroup(clHand
,
183 anchorEnd
- anchorStart
+ 1, // # of certs
185 CSSM_FALSE
, // firstCertIsSubject
187 CSSM_FALSE
, // allInDbs
188 CSSM_FALSE
)) { // skipFirstDb
189 printf("\nError in tpMakeRandCertGroup\n");
193 crtn
= tpCertGroupVerify(
198 &CSSMOID_APPLE_X509_BASIC
, // Policy
203 anchorCerts
.GroupList
.CertList
, // passed as CSSM_DATA_PTR, not CERTGROUP....
204 anchorCerts
.NumCerts
,
205 CSSM_TP_STOP_ON_POLICY
,
209 /* first verify format of result */
210 if( (vfyResult
.NumberOfEvidences
!= 3) ||
211 (vfyResult
.Evidence
== NULL
) ||
212 (vfyResult
.Evidence
[0].EvidenceForm
!= CSSM_EVIDENCE_FORM_APPLE_HEADER
) ||
213 (vfyResult
.Evidence
[1].EvidenceForm
!= CSSM_EVIDENCE_FORM_APPLE_CERTGROUP
) ||
214 (vfyResult
.Evidence
[2].EvidenceForm
!= CSSM_EVIDENCE_FORM_APPLE_CERT_INFO
) ||
215 (vfyResult
.Evidence
[0].Evidence
== NULL
) ||
216 (vfyResult
.Evidence
[1].Evidence
== NULL
) ||
217 (vfyResult
.Evidence
[2].Evidence
== NULL
)) {
218 printf("***Malformed VerifyContextResult\n");
221 if((vfyResult
.Evidence
!= NULL
) && (vfyResult
.Evidence
[1].Evidence
!= NULL
)) {
222 outGrp
= (CSSM_CERTGROUP_PTR
)vfyResult
.Evidence
[1].Evidence
;
223 evidenceSize
= outGrp
->NumCerts
;
226 /* in case no evidence returned */
230 /* %%% since non-root anchors are permitted as of <rdar://5685316>,
231 * the test assumptions have become invalid: these tests generate
232 * an anchors list which always includes the full chain, so by
233 * definition, the evidence chain will never be longer than 2,
234 * since the leaf's issuer is always an anchor.
235 * %%% need to revisit and rewrite these tests. -kcm
237 if ((evidenceSize
> 1) && (evidenceSize
< expEvidenceSize
) &&
238 (crtn
== CSSM_OK
|| crtn
== CSSMERR_TP_CERTIFICATE_CANT_OPERATE
)) {
239 /* ignore, for now */
241 expEvidenceSize
= evidenceSize
;
244 if((crtn
!= expErr
) ||
245 (evidenceSize
!= expEvidenceSize
)) {
246 printf("\n***cgVerify: Error on tpCertGroupVerify expectResult %s\n",
248 printf(" err %s expErr %s\n",
249 cssmErrToStr(crtn
), cssmErrToStr(expErr
));
250 printf(" evidenceSize %d expEvidenceSize %u\n",
251 evidenceSize
, (unsigned)expEvidenceSize
);
252 printf(" numCerts %d cgEnd %d anchorStart %d anchorEnd %d\n",
253 numCerts
, cgEnd
, anchorStart
, anchorEnd
);
261 tpFreeCertGroup(&certGroupFrag
,
262 CSSM_FALSE
, // caller malloc'd the actual certs
263 CSSM_FALSE
); // struct is on stack
264 tpFreeCertGroup(&anchorCerts
,
265 CSSM_FALSE
, // caller malloc'd the actual certs
266 CSSM_FALSE
); // struct is on stack
267 freeVfyResult(&vfyResult
);
269 clDeleteAllCerts(dlDb
);
274 /*** end of code directly copied from ../cgVerify/cgVerify.cpp ***/
277 * For debug only - ensure that the given array of public keys are all unique
278 * Only saw this when using FEE RNG (i.e., no SecurityServer running).
282 const CSSM_KEY
*pubKeys
)
286 for(i
=0; i
<numKeys
-1; i
++) {
287 for(j
=i
+1; j
<numKeys
; j
++) {
288 if(appCompareCssmData(&pubKeys
[i
].KeyData
, &pubKeys
[j
].KeyData
)) {
289 printf("***HEY! DUPLICATE PUBLIC KEYS in cgVerify!\n");
299 * key pairs - created in cgConstructInit, stored in testParams->perThread
302 CSSM_KEY_PTR pubKeys
;
303 CSSM_KEY_PTR privKeys
;
305 char *notBeforeStr
; // to use thread-safe tpGenCerts()
306 char *notAfterStr
; // to use thread-safe tpGenCerts()
310 int cgVerifyInit(TestParams
*testParams
)
312 unsigned numKeys
= NUM_CERTS_MIN
+ testParams
->threadNum
;
313 TT_KeyPairs
*keyPairs
;
315 if(testParams
->verbose
) {
316 printf("cgVerify thread %d: generating keys...\n",
317 testParams
->threadNum
);
319 keyPairs
= (TT_KeyPairs
*)CSSM_MALLOC(sizeof(TT_KeyPairs
));
320 keyPairs
->numKeys
= numKeys
;
321 keyPairs
->pubKeys
= (CSSM_KEY_PTR
)CSSM_CALLOC(numKeys
, sizeof(CSSM_KEY
));
322 keyPairs
->privKeys
= (CSSM_KEY_PTR
)CSSM_CALLOC(numKeys
, sizeof(CSSM_KEY
));
323 CSSM_DL_DB_HANDLE dlDbHand
= {0, 0};
324 if(tpGenKeys(testParams
->cspHand
,
329 "cgVerify", // keyLabelBase
331 keyPairs
->privKeys
)) {
334 if(comparePubKeys(numKeys
, keyPairs
->pubKeys
)) {
337 keyPairs
->notBeforeStr
= genTimeAtNowPlus(0);
338 keyPairs
->notAfterStr
= genTimeAtNowPlus(SECONDS_TO_LIVE
);
340 testParams
->perThread
= keyPairs
;
344 printf("Error generating keys; aborting\n");
345 CSSM_FREE(keyPairs
->pubKeys
);
346 CSSM_FREE(keyPairs
->privKeys
);
351 int cgVerify(TestParams
*testParams
)
354 int status
= -1; // exit status
357 TT_KeyPairs
*keyPairs
= (TT_KeyPairs
*)testParams
->perThread
;
359 /* all three of these are arrays with numCert elements */
360 CSSM_KEY_PTR pubKeys
= keyPairs
->pubKeys
;
361 CSSM_KEY_PTR privKeys
= keyPairs
->privKeys
;
362 CSSM_DATA_PTR certs
= NULL
;
364 unsigned numCerts
= keyPairs
->numKeys
;
365 uint32 sigAlg
= SIG_ALG_DEF
;
366 ExpectResult expectResult
;
368 CSSM_BOOL useDb
= CSSM_TRUE
;
370 CSSM_BOOL useDb
= CSSM_FALSE
;
372 CSSM_DL_DB_HANDLE dlDbHand
= {0, 0};
374 /* malloc empty certs */
375 certs
= (CSSM_DATA_PTR
)CSSM_CALLOC(numCerts
, sizeof(CSSM_DATA
));
377 printf("not enough memory for %u certs.\n", numCerts
);
380 memset(certs
, 0, numCerts
* sizeof(CSSM_DATA
));
382 for(loopNum
=0; loopNum
<testParams
->numLoops
; loopNum
++) {
384 if(testParams
->verbose
) {
385 printf("generating certs...\n");
387 else if(!testParams
->quiet
) {
388 printChar(testParams
->progressChar
);
390 if(tpGenCerts(testParams
->cspHand
,
394 "cgConstruct", // nameBase
398 keyPairs
->notBeforeStr
,
399 keyPairs
->notAfterStr
)) {
403 /* cycle thru test scenarios */
404 switch(loopNum
% 4) {
406 expectResult
= ER_InvalidAnchor
;
409 expectResult
= ER_RootInCertGroup
;
412 expectResult
= ER_AnchorVerify
;
415 expectResult
= ER_NoRoot
;
418 status
= doTest(testParams
->tpHand
,
426 testParams
->verbose
);
431 for(dex
=0; dex
<numCerts
; dex
++) {
432 CSSM_FREE(certs
[dex
].Data
);
434 memset(certs
, 0, numCerts
* sizeof(CSSM_DATA
));
437 printf("Hit CR to proceed: ");
443 for(dex
=0; dex
<numCerts
; dex
++) {
444 if(certs
[dex
].Data
) {
445 CSSM_FREE(certs
[dex
].Data
);
448 CSSM_FREE(keyPairs
->pubKeys
);
449 CSSM_FREE(keyPairs
->privKeys
);