]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/threadTest/cgVerifyThr.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / threadTest / cgVerifyThr.cpp
1 /* cgVerifyThr.cpp - simple version CertGroupVerify test */
2
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>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <time.h>
13 #include <string.h>
14 #include <Security/oidsalg.h>
15
16 /* for memory leak debug only, with only one thread running */
17 #define DO_PAUSE 0
18
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
23 #define LOOPS_DEF 10
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 */
26
27 #define CERT_IN_DB 0
28
29 /*
30 * How we define the "expected result".
31 */
32 typedef enum {
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
37 } ExpectResult;
38
39 static int testError()
40 {
41 char resp;
42
43 printf("Attach via debugger for more info.\n");
44 printf("a to abort, c to continue: ");
45 resp = getchar();
46 return (resp == 'a');
47 }
48
49 static int doTest(
50 CSSM_TP_HANDLE tpHand,
51 CSSM_CL_HANDLE clHand,
52 CSSM_CSP_HANDLE cspHand,
53 CSSM_DL_DB_HANDLE dlDb,
54 CSSM_DATA_PTR certs,
55 unsigned numCerts,
56 CSSM_BOOL useDb,
57 ExpectResult expectResult,
58 CSSM_BOOL verbose)
59 {
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()
70 int rtn = 0;
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;
76 CSSM_RETURN crtn;
77
78 memset(&vfyResult, 0, sizeof(CSSM_TP_VERIFY_CONTEXT_RESULT));
79
80 if(useDb) {
81 dlDbPtr = &dlDb;
82 dbList.NumHandles = 1;
83 dbList.DLDBHandle = &dlDb;
84 dbListPtr = &dbList;
85 }
86 else {
87 /* not yet */
88 dlDbPtr = NULL;
89 dbListPtr = NULL;
90 }
91
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)";
102 break;
103
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;
109 expErr = CSSM_OK;
110 expEvidenceSize = numCerts;
111 expResStr = "Good (root in certGroup AND in anchors)";
112 break;
113
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;
121 expErr = CSSM_OK;
122 /* size = # certs in certGroupFrag, plus one anchor */
123 expEvidenceSize = die + 2;
124 expResStr = "Good (root ONLY in anchors)";
125 break;
126
127 case ER_NoRoot:
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)";
139 break;
140 }
141
142 if(verbose) {
143 printf(" ...expectResult = %s\n", expResStr);
144 }
145
146 /* cook up two cert groups */
147 if(verbose) {
148 printf(" ...building certGroupFrag from certs[0..%d]\n",
149 cgEnd);
150 }
151 if(tpMakeRandCertGroup(clHand,
152 dbListPtr,
153 certs, // certGroupFrag always starts at 0
154 cgEnd+1, // # of certs
155 &certGroupFrag,
156 CSSM_TRUE, // firstCertIsSubject
157 verbose,
158 CSSM_FALSE, // allInDbs
159 CSSM_FALSE)) { // skipFirstDb
160 printf("\nError in tpMakeRandCertGroup\n");
161 return 1;
162 }
163
164 if(anchorStart > anchorEnd) {
165 /* legal for ER_NoRoot */
166 if((expectResult != ER_NoRoot) || (anchorStart != numCerts)) {
167 printf("Try again, pal.\n");
168 exit(1);
169 }
170 }
171 if(verbose) {
172 printf(" ...building anchorCerts from certs[%d..%d]\n",
173 anchorStart, anchorEnd);
174 }
175 if(anchorEnd > (numCerts - 1)) {
176 printf("anchorEnd overflow\n");
177 exit(1);
178 }
179 /* anchors do not go in DB */
180 if(tpMakeRandCertGroup(clHand,
181 NULL,
182 certs + anchorStart,
183 anchorEnd - anchorStart + 1, // # of certs
184 &anchorCerts,
185 CSSM_FALSE, // firstCertIsSubject
186 verbose,
187 CSSM_FALSE, // allInDbs
188 CSSM_FALSE)) { // skipFirstDb
189 printf("\nError in tpMakeRandCertGroup\n");
190 return 1;
191 }
192
193 crtn = tpCertGroupVerify(
194 tpHand,
195 clHand,
196 cspHand,
197 dbListPtr,
198 &CSSMOID_APPLE_X509_BASIC, // Policy
199 NULL, // fieldOpts
200 NULL, // actionData
201 NULL, // policyOpts
202 &certGroupFrag,
203 anchorCerts.GroupList.CertList, // passed as CSSM_DATA_PTR, not CERTGROUP....
204 anchorCerts.NumCerts,
205 CSSM_TP_STOP_ON_POLICY,
206 NULL, // cssmTimeStr
207 &vfyResult);
208
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");
219 return 1;
220 }
221 if((vfyResult.Evidence != NULL) && (vfyResult.Evidence[1].Evidence != NULL)) {
222 outGrp = (CSSM_CERTGROUP_PTR)vfyResult.Evidence[1].Evidence;
223 evidenceSize = outGrp->NumCerts;
224 }
225 else {
226 /* in case no evidence returned */
227 evidenceSize = 0;
228 }
229
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
236 */
237 if ((evidenceSize > 1) && (evidenceSize < expEvidenceSize) &&
238 (crtn == CSSM_OK || crtn == CSSMERR_TP_CERTIFICATE_CANT_OPERATE)) {
239 /* ignore, for now */
240 expErr = crtn;
241 expEvidenceSize = evidenceSize;
242 }
243
244 if((crtn != expErr) ||
245 (evidenceSize != expEvidenceSize)) {
246 printf("\n***cgVerify: Error on tpCertGroupVerify expectResult %s\n",
247 expResStr);
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);
254 rtn = testError();
255 }
256 else {
257 rtn = 0;
258 }
259
260 /* free resources */
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);
268 if(useDb) {
269 clDeleteAllCerts(dlDb);
270 }
271 return rtn;
272 }
273
274 /*** end of code directly copied from ../cgVerify/cgVerify.cpp ***/
275
276 /*
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).
279 */
280 int comparePubKeys(
281 unsigned numKeys,
282 const CSSM_KEY *pubKeys)
283 {
284 unsigned i,j;
285
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");
290 return testError();
291 }
292 }
293 }
294 return 0;
295 }
296
297
298 /*
299 * key pairs - created in cgConstructInit, stored in testParams->perThread
300 */
301 typedef struct {
302 CSSM_KEY_PTR pubKeys;
303 CSSM_KEY_PTR privKeys;
304 unsigned numKeys;
305 char *notBeforeStr; // to use thread-safe tpGenCerts()
306 char *notAfterStr; // to use thread-safe tpGenCerts()
307 } TT_KeyPairs;
308
309
310 int cgVerifyInit(TestParams *testParams)
311 {
312 unsigned numKeys = NUM_CERTS_MIN + testParams->threadNum;
313 TT_KeyPairs *keyPairs;
314
315 if(testParams->verbose) {
316 printf("cgVerify thread %d: generating keys...\n",
317 testParams->threadNum);
318 }
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,
325 dlDbHand,
326 numKeys,
327 KEYGEN_ALG_DEF,
328 CG_KEY_SIZE_DEFAULT,
329 "cgVerify", // keyLabelBase
330 keyPairs->pubKeys,
331 keyPairs->privKeys)) {
332 goto abort;
333 }
334 if(comparePubKeys(numKeys, keyPairs->pubKeys)) {
335 return 1;
336 }
337 keyPairs->notBeforeStr = genTimeAtNowPlus(0);
338 keyPairs->notAfterStr = genTimeAtNowPlus(SECONDS_TO_LIVE);
339
340 testParams->perThread = keyPairs;
341 return 0;
342
343 abort:
344 printf("Error generating keys; aborting\n");
345 CSSM_FREE(keyPairs->pubKeys);
346 CSSM_FREE(keyPairs->privKeys);
347 CSSM_FREE(keyPairs);
348 return 1;
349 }
350
351 int cgVerify(TestParams *testParams)
352 {
353 unsigned loopNum;
354 int status = -1; // exit status
355 unsigned dex;
356
357 TT_KeyPairs *keyPairs = (TT_KeyPairs *)testParams->perThread;
358
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;
363
364 unsigned numCerts = keyPairs->numKeys;
365 uint32 sigAlg = SIG_ALG_DEF;
366 ExpectResult expectResult;
367 #if CERT_IN_DB
368 CSSM_BOOL useDb = CSSM_TRUE;
369 #else
370 CSSM_BOOL useDb = CSSM_FALSE;
371 #endif
372 CSSM_DL_DB_HANDLE dlDbHand = {0, 0};
373
374 /* malloc empty certs */
375 certs = (CSSM_DATA_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_DATA));
376 if(certs == NULL) {
377 printf("not enough memory for %u certs.\n", numCerts);
378 goto abort;
379 }
380 memset(certs, 0, numCerts * sizeof(CSSM_DATA));
381
382 for(loopNum=0; loopNum<testParams->numLoops; loopNum++) {
383 /* generate certs */
384 if(testParams->verbose) {
385 printf("generating certs...\n");
386 }
387 else if(!testParams->quiet) {
388 printChar(testParams->progressChar);
389 }
390 if(tpGenCerts(testParams->cspHand,
391 testParams->clHand,
392 numCerts,
393 sigAlg,
394 "cgConstruct", // nameBase
395 pubKeys,
396 privKeys,
397 certs,
398 keyPairs->notBeforeStr,
399 keyPairs->notAfterStr)) {
400 goto abort;
401 }
402
403 /* cycle thru test scenarios */
404 switch(loopNum % 4) {
405 case 0:
406 expectResult = ER_InvalidAnchor;
407 break;
408 case 1:
409 expectResult = ER_RootInCertGroup;
410 break;
411 case 2:
412 expectResult = ER_AnchorVerify;
413 break;
414 case 3:
415 expectResult = ER_NoRoot;
416 break;
417 }
418 status = doTest(testParams->tpHand,
419 testParams->clHand,
420 testParams->cspHand,
421 dlDbHand,
422 certs,
423 numCerts,
424 useDb,
425 expectResult,
426 testParams->verbose);
427 if(status) {
428 break;
429 }
430 /* free certs */
431 for(dex=0; dex<numCerts; dex++) {
432 CSSM_FREE(certs[dex].Data);
433 }
434 memset(certs, 0, numCerts * sizeof(CSSM_DATA));
435 #if DO_PAUSE
436 fpurge(stdin);
437 printf("Hit CR to proceed: ");
438 getchar();
439 #endif
440 }
441 abort:
442 /* free resources */
443 for(dex=0; dex<numCerts; dex++) {
444 if(certs[dex].Data) {
445 CSSM_FREE(certs[dex].Data);
446 }
447 }
448 CSSM_FREE(keyPairs->pubKeys);
449 CSSM_FREE(keyPairs->privKeys);
450 CSSM_FREE(keyPairs);
451 return status;
452 }
453