]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/keyStoreLeak/keyStoreLeak.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / keyStoreLeak / keyStoreLeak.c
1 /* Copyright (c) 2004-2005 Apple Computer, Inc.
2 *
3 * keyStoreLeak.c - simple generate/store key, lookup, delete loop; for malloc
4 * debug testing
5 *
6 */
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <time.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <Security/cssm.h>
14 #include "cspwrap.h"
15 #include "common.h"
16 #include "cspdlTesting.h"
17
18 #define LOOPS_DEF 10
19 #define DB_NAME "keyStore.db"
20
21 static void usage(char **argv)
22 {
23 printf("usage: %s [options]\n", argv[0]);
24 printf(" Options:\n");
25 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
26 printf(" r(RSA; default = FEE)\n");
27 printf(" k=keyChainFile\n");
28 printf(" P(ause for MallocDebug)\n");
29 printf(" v(erbose)\n");
30 printf(" q(uiet)\n");
31 printf(" h(elp)\n");
32 exit(1);
33 }
34
35 #define FEE_PRIV_DATA_SIZE 20
36
37 /*
38 * Generate key pair, default size. This is like cspGenKeyPair in cspwrap.c,
39 * tweaked for this test To allow varying permanent attribute.
40 */
41 static CSSM_RETURN genKeyPair(CSSM_CSP_HANDLE cspHand,
42 CSSM_DL_HANDLE dlHand,
43 CSSM_DB_HANDLE dbHand,
44 const CSSM_DATA_PTR keyLabel,
45 CSSM_KEY_PTR pubKey, // mallocd by caller
46 uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
47 uint32 pubKeyAttr,
48 CSSM_KEY_PTR privKey, // mallocd by caller
49 uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc.
50 uint32 privKeyAttr,
51 uint32 keyGenAlg)
52 {
53 CSSM_RETURN crtn;
54 CSSM_CC_HANDLE ccHand;
55 CSSM_RETURN ocrtn = CSSM_OK;
56 uint32 keySize;
57
58 if(keyGenAlg == CSSM_ALGID_FEE) {
59 keySize = CSP_FEE_KEY_SIZE_DEFAULT;
60 }
61 else {
62 keySize = CSP_RSA_KEY_SIZE_DEFAULT;
63 }
64 memset(pubKey, 0, sizeof(CSSM_KEY));
65 memset(privKey, 0, sizeof(CSSM_KEY));
66
67 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
68 keyGenAlg,
69 keySize,
70 NULL, // Seed
71 NULL, // Salt
72 NULL, // StartDate
73 NULL, // EndDate
74 NULL, // Params
75 &ccHand);
76 if(crtn) {
77 printError("CSSM_CSP_CreateKeyGenContext", crtn);
78 ocrtn = crtn;
79 goto abort;
80 }
81
82 /* add in DL/DB to context */
83 crtn = cspAddDlDbToContext(ccHand, dlHand, dbHand);
84 if(crtn) {
85 ocrtn = crtn;
86 goto abort;
87 }
88 crtn = CSSM_GenerateKeyPair(ccHand,
89 pubKeyUsage,
90 pubKeyAttr,
91 keyLabel,
92 pubKey,
93 privKeyUsage,
94 privKeyAttr,
95 keyLabel, // same labels
96 NULL, // cred/acl
97 privKey);
98 if(crtn) {
99 printError("CSSM_GenerateKeyPair", crtn);
100 ocrtn = crtn;
101 goto abort;
102 }
103
104 /* basic checks...*/
105 if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
106 printf("privKey blob type: exp %u got %u\n",
107 CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType);
108 }
109 if(pubKeyAttr & CSSM_KEYATTR_RETURN_REF) {
110 if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
111 printf("pubKey blob type: exp %u got %u\n",
112 CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType);
113 ocrtn = -1;
114 goto abort;
115 }
116 }
117 else {
118 if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_RAW) {
119 printf("pubKey blob type: exp %u got %u\n",
120 CSSM_KEYBLOB_RAW, (unsigned)privKey->KeyHeader.BlobType);
121 ocrtn = -1;
122 goto abort;
123 }
124 }
125
126 abort:
127 if(ccHand != 0) {
128 crtn = CSSM_DeleteContext(ccHand);
129 if(crtn) {
130 printError("CSSM_DeleteContext", crtn);
131 ocrtn = crtn;
132 }
133 }
134 return ocrtn;
135 }
136
137 #define KEY_LABEL "testKey"
138
139 static int doTest(CSSM_CSP_HANDLE cspHand,
140 CSSM_DL_HANDLE dlHand,
141 CSSM_DB_HANDLE dbHand,
142 CSSM_BOOL pubIsPerm, // pub is permanent
143 CSSM_BOOL privIsPerm, // priv is permanent
144 CSSM_BOOL privIsExtractable,
145 CSSM_BOOL permKeys, // leave them in the KC
146 CSSM_BOOL verbose,
147 CSSM_BOOL quiet,
148 uint32 keyGenAlg)
149 {
150 CSSM_KEY pubKey; // from GenerateKeyPair
151 CSSM_KEY privKey;
152 CSSM_KEY_PTR lookUpPub; // from cspLookUpKeyByLabel, etc.
153 CSSM_KEY_PTR lookUpPriv;
154 CSSM_RETURN crtn;
155 CSSM_DATA labelData;
156 uint32 pubAttr;
157 uint32 privAttr;
158 labelData.Data = (uint8 *)KEY_LABEL;
159 labelData.Length = strlen(KEY_LABEL);
160
161 /* create key pair */
162 if(verbose) {
163 printf(" ...generating key pair (pubIsPerm %d privIsPerm %d privIsExtract"
164 " %d)\n", (int)pubIsPerm, (int)privIsPerm, (int)privIsExtractable);
165 }
166 pubAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF;
167 if(pubIsPerm) {
168 pubAttr |= CSSM_KEYATTR_PERMANENT;
169 }
170
171 /*
172 * To use a NULL wrap to test detection of !EXTRACTABLE, we're relying on
173 * being able to create !SENSITIVE private keys. We'll make 'em sensitive
174 * if we're not trying to null wrap them.
175 */
176 privAttr = CSSM_KEYATTR_RETURN_REF;
177 if(privIsPerm) {
178 privAttr |= CSSM_KEYATTR_PERMANENT;
179 }
180 if(privIsExtractable) {
181 privAttr |= CSSM_KEYATTR_EXTRACTABLE;
182 }
183 else {
184 privAttr |= CSSM_KEYATTR_SENSITIVE;
185 }
186 #if CSPDL_KEYATTR_PRIVATE
187 privAttr |= CSSM_KEYATTR_PRIVATE;
188 #endif
189 crtn = genKeyPair(cspHand,
190 dlHand,
191 dbHand,
192 &labelData,
193 &pubKey,
194 CSSM_KEYUSE_VERIFY, // pubKeyUsage
195 pubAttr,
196 &privKey,
197 CSSM_KEYUSE_SIGN,
198 privAttr,
199 keyGenAlg);
200 if(crtn) {
201 return testError(quiet);
202 }
203
204 /* lookUpPub = lookup pub by label; */
205 if(verbose) {
206 if(pubIsPerm) {
207 printf(" ...lookup pub by label\n");
208 }
209 else {
210 printf(" ...lookup (nonexistent) pub by label\n");
211 }
212 }
213 lookUpPub = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Public);
214 if(pubIsPerm) {
215 if(lookUpPub == NULL) {
216 printf("lookup pub by label failed\n");
217 return testError(quiet);
218 }
219 }
220 else {
221 if(lookUpPub != NULL) {
222 printf("***Unexpected success on cspLookUpKeyByLabel(pub, not perm)\n");
223 return testError(quiet);
224 }
225 }
226
227 /* lookUpPriv = lookup priv by label; ensure == privKey; */
228 if(verbose) {
229 if(privIsPerm) {
230 printf(" ...lookup priv by label\n");
231 }
232 else {
233 printf(" ...lookup (nonexistent) priv by label\n");
234 }
235 }
236 lookUpPriv = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Private);
237 if(privIsPerm) {
238 if(lookUpPriv == NULL) {
239 printf("lookup priv by label failed\n");
240 return testError(quiet);
241 }
242
243 /* free lookUpPriv from cache, but it's permanent */
244 if(verbose) {
245 printf(" ...free lookupPriv\n");
246 }
247 if(cspFreeKey(cspHand, lookUpPriv)) {
248 printf("Error on cspFreeKey(lookUpPriv)\n");
249 return testError(quiet);
250 }
251 CSSM_FREE(lookUpPriv); // mallocd during lookup
252 lookUpPriv = NULL;
253
254 if(!permKeys) {
255 /* delete priv - implies freeKey as well */
256 if(verbose) {
257 printf(" ...delete privKey\n");
258 }
259 crtn = cspDeleteKey(cspHand, dlHand, dbHand, &labelData, &privKey);
260 if(crtn) {
261 printf("Error deleting priv\n");
262 return testError(quiet);
263 }
264 }
265 }
266 else {
267 /* !privIsPerm - just free it and it's all gone */
268 if(lookUpPriv != NULL) {
269 printf("***Unexpected success on cspLookUpKeyByLabel(priv, not perm)\n");
270 return testError(quiet);
271 }
272 if(cspFreeKey(cspHand, &privKey)) {
273 printf("Error on cspFreeKey(privKey)\n");
274 return testError(quiet);
275 }
276 }
277 /* CSP, DL have no knowledge of privKey or its variations */
278
279 /* free one or both copies of pub as appropriate */
280 if(verbose) {
281 printf(" ...free pubKey\n");
282 }
283 crtn = cspFreeKey(cspHand, &pubKey);
284 if(crtn) {
285 printf("Error freeing pubKey\n");
286 return testError(quiet);
287 }
288 if(pubIsPerm) {
289 if(verbose) {
290 printf(" ...free lookUpPub\n");
291 }
292 crtn = cspFreeKey(cspHand, lookUpPub);
293 if(crtn) {
294 printf("Error freeing lookUpPub\n");
295 return testError(quiet);
296 }
297 }
298 CSSM_FREE(lookUpPub); // mallocd by lookup in any case
299
300 if(pubIsPerm) {
301 /* pub should still be there in DL */
302 /* lookUpPub = lookup pub by label; verify OK; */
303 if(verbose) {
304 printf(" ...lookup pub by label (2)\n");
305 }
306 lookUpPub = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Public);
307 if(lookUpPub == NULL) {
308 printf("lookup pub by label (2) failed\n");
309 return testError(quiet);
310 }
311
312 if(!permKeys) {
313 /* now really delete it */
314 if(verbose) {
315 printf(" ...delete lookUpPub\n");
316 }
317 crtn = cspDeleteKey(cspHand, dlHand, dbHand, &labelData, lookUpPub);
318 if(crtn) {
319 printf("Error deleting lookUpPub\n");
320 return testError(quiet);
321 }
322 CSSM_FREE(lookUpPub); // mallocd by lookup
323 }
324 }
325 /* else freeKey should have removed all trace */
326
327 if(!permKeys) {
328 /* lookUpPub = lookup pub by label; verify fail; */
329 if(verbose) {
330 printf(" ...lookup (nonexistent) pub by label\n");
331 }
332 lookUpPub = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Public);
333 if(lookUpPub != NULL) {
334 printf("Unexpected success on cspLookUpKeyByLabel(pub) (2)\n");
335 return testError(quiet);
336 }
337 }
338 return 0;
339 }
340
341 int main(int argc, char **argv)
342 {
343 int arg;
344 char *argp;
345 unsigned loop;
346 CSSM_CSP_HANDLE cspHand;
347 CSSM_DB_HANDLE dbHand;
348 CSSM_DL_HANDLE dlHand;
349 CSSM_BOOL pubIsPerm;
350 CSSM_BOOL privIsPerm;
351 CSSM_BOOL privIsExtractable;
352 uint32 keyGenAlg = CSSM_ALGID_FEE;
353 int rtn = 0;
354 CSSM_RETURN crtn;
355
356 /*
357 * User-spec'd params
358 */
359 unsigned loops = LOOPS_DEF;
360 CSSM_BOOL verbose = CSSM_FALSE;
361 CSSM_BOOL quiet = CSSM_FALSE;
362 CSSM_BOOL permKeys = CSSM_FALSE;
363 char dbName[100]; /* DB_NAME_pid */
364 CSSM_BOOL useExistDb = CSSM_FALSE;
365 CSSM_BOOL doPause = CSSM_FALSE;
366
367 dbName[0] = '\0';
368
369 for(arg=1; arg<argc; arg++) {
370 argp = argv[arg];
371 switch(argp[0]) {
372 case 'l':
373 loops = atoi(&argp[2]);
374 break;
375 case 'v':
376 verbose = CSSM_TRUE;
377 break;
378 case 'q':
379 quiet = CSSM_TRUE;
380 break;
381 case 'p':
382 permKeys = CSSM_TRUE;
383 loops = 1;
384 break;
385 case 'r':
386 keyGenAlg = CSSM_ALGID_RSA;
387 break;
388 case 'k':
389 memmove(dbName, &argp[2], strlen(&argp[2]) + 1);
390 useExistDb = CSSM_TRUE;
391 break;
392 case 'P':
393 doPause = CSSM_TRUE;
394 break;
395 case 'h':
396 default:
397 usage(argv);
398 }
399 }
400
401 if(dbName[0] == '\0') {
402 sprintf(dbName, "%s_%d", DB_NAME, (int)getpid());
403 }
404
405 testStartBanner("keyStore", argc, argv);
406
407 /* attach to CSP/DL */
408 cspHand = cspDlDbStartup(CSSM_FALSE, NULL);
409 if(cspHand == 0) {
410 exit(1);
411 }
412 dlHand = dlStartup();
413 if(dlHand == 0) {
414 exit(1);
415 }
416 if(useExistDb) {
417 /* this one may well require SecurityAgent UI */
418 crtn = dbCreateOpen(dlHand, dbName, CSSM_FALSE, CSSM_FALSE, NULL,
419 &dbHand);
420 }
421 else {
422 /* hands-free test */
423 crtn = dbCreateOpen(dlHand, dbName, CSSM_TRUE, CSSM_TRUE, dbName,
424 &dbHand);
425 }
426 if(crtn) {
427 exit(1);
428 }
429 for(loop=1; ; loop++) {
430
431 if(!quiet) {
432 printf("...loop %d\n", loop);
433 }
434
435 if(permKeys) {
436 pubIsPerm = privIsPerm = CSSM_TRUE;
437 }
438 else {
439 /* mix up pubIsPerm, privIsPerm */
440 pubIsPerm = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
441 privIsPerm = (loop & 2) ? CSSM_TRUE : CSSM_FALSE;
442 }
443 privIsExtractable = (loop & 4) ? CSSM_TRUE : CSSM_FALSE;
444 if(doTest(cspHand,
445 dlHand,
446 dbHand,
447 pubIsPerm,
448 privIsPerm,
449 privIsExtractable,
450 permKeys,
451 verbose,
452 quiet,
453 keyGenAlg)) {
454 rtn = 1;
455 break;
456 }
457 if(loops && (loop == loops)) {
458 break;
459 }
460 if(doPause) {
461 fpurge(stdin);
462 printf("CR to continue: ");
463 getchar();
464 }
465 }
466
467 cspShutdown(cspHand, CSSM_FALSE);
468 /* FIXME - DB close? DL shutdown? */
469 if((rtn == 0) && !quiet) {
470 printf("%s test complete\n", argv[0]);
471 }
472 if(rtn == 0) {
473 /* be nice: if we ran OK delete the cruft DB we created */
474 unlink(dbName);
475 }
476 return rtn;
477 }