1 /* Copyright (c) 2004-2005 Apple Computer, Inc.
3 * keyStoreLeak.c - simple generate/store key, lookup, delete loop; for malloc
13 #include <Security/cssm.h>
16 #include "cspdlTesting.h"
19 #define DB_NAME "keyStore.db"
21 static void usage(char **argv
)
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");
35 #define FEE_PRIV_DATA_SIZE 20
38 * Generate key pair, default size. This is like cspGenKeyPair in cspwrap.c,
39 * tweaked for this test To allow varying permanent attribute.
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.
48 CSSM_KEY_PTR privKey
, // mallocd by caller
49 uint32 privKeyUsage
, // CSSM_KEYUSE_DECRYPT, etc.
54 CSSM_CC_HANDLE ccHand
;
55 CSSM_RETURN ocrtn
= CSSM_OK
;
58 if(keyGenAlg
== CSSM_ALGID_FEE
) {
59 keySize
= CSP_FEE_KEY_SIZE_DEFAULT
;
62 keySize
= CSP_RSA_KEY_SIZE_DEFAULT
;
64 memset(pubKey
, 0, sizeof(CSSM_KEY
));
65 memset(privKey
, 0, sizeof(CSSM_KEY
));
67 crtn
= CSSM_CSP_CreateKeyGenContext(cspHand
,
77 printError("CSSM_CSP_CreateKeyGenContext", crtn
);
82 /* add in DL/DB to context */
83 crtn
= cspAddDlDbToContext(ccHand
, dlHand
, dbHand
);
88 crtn
= CSSM_GenerateKeyPair(ccHand
,
95 keyLabel
, // same labels
99 printError("CSSM_GenerateKeyPair", crtn
);
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
);
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
);
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
);
128 crtn
= CSSM_DeleteContext(ccHand
);
130 printError("CSSM_DeleteContext", crtn
);
137 #define KEY_LABEL "testKey"
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
150 CSSM_KEY pubKey
; // from GenerateKeyPair
152 CSSM_KEY_PTR lookUpPub
; // from cspLookUpKeyByLabel, etc.
153 CSSM_KEY_PTR lookUpPriv
;
158 labelData
.Data
= (uint8
*)KEY_LABEL
;
159 labelData
.Length
= strlen(KEY_LABEL
);
161 /* create key pair */
163 printf(" ...generating key pair (pubIsPerm %d privIsPerm %d privIsExtract"
164 " %d)\n", (int)pubIsPerm
, (int)privIsPerm
, (int)privIsExtractable
);
166 pubAttr
= CSSM_KEYATTR_EXTRACTABLE
| CSSM_KEYATTR_RETURN_REF
;
168 pubAttr
|= CSSM_KEYATTR_PERMANENT
;
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.
176 privAttr
= CSSM_KEYATTR_RETURN_REF
;
178 privAttr
|= CSSM_KEYATTR_PERMANENT
;
180 if(privIsExtractable
) {
181 privAttr
|= CSSM_KEYATTR_EXTRACTABLE
;
184 privAttr
|= CSSM_KEYATTR_SENSITIVE
;
186 #if CSPDL_KEYATTR_PRIVATE
187 privAttr
|= CSSM_KEYATTR_PRIVATE
;
189 crtn
= genKeyPair(cspHand
,
194 CSSM_KEYUSE_VERIFY
, // pubKeyUsage
201 return testError(quiet
);
204 /* lookUpPub = lookup pub by label; */
207 printf(" ...lookup pub by label\n");
210 printf(" ...lookup (nonexistent) pub by label\n");
213 lookUpPub
= cspLookUpKeyByLabel(dlHand
, dbHand
, &labelData
, CKT_Public
);
215 if(lookUpPub
== NULL
) {
216 printf("lookup pub by label failed\n");
217 return testError(quiet
);
221 if(lookUpPub
!= NULL
) {
222 printf("***Unexpected success on cspLookUpKeyByLabel(pub, not perm)\n");
223 return testError(quiet
);
227 /* lookUpPriv = lookup priv by label; ensure == privKey; */
230 printf(" ...lookup priv by label\n");
233 printf(" ...lookup (nonexistent) priv by label\n");
236 lookUpPriv
= cspLookUpKeyByLabel(dlHand
, dbHand
, &labelData
, CKT_Private
);
238 if(lookUpPriv
== NULL
) {
239 printf("lookup priv by label failed\n");
240 return testError(quiet
);
243 /* free lookUpPriv from cache, but it's permanent */
245 printf(" ...free lookupPriv\n");
247 if(cspFreeKey(cspHand
, lookUpPriv
)) {
248 printf("Error on cspFreeKey(lookUpPriv)\n");
249 return testError(quiet
);
251 CSSM_FREE(lookUpPriv
); // mallocd during lookup
255 /* delete priv - implies freeKey as well */
257 printf(" ...delete privKey\n");
259 crtn
= cspDeleteKey(cspHand
, dlHand
, dbHand
, &labelData
, &privKey
);
261 printf("Error deleting priv\n");
262 return testError(quiet
);
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
);
272 if(cspFreeKey(cspHand
, &privKey
)) {
273 printf("Error on cspFreeKey(privKey)\n");
274 return testError(quiet
);
277 /* CSP, DL have no knowledge of privKey or its variations */
279 /* free one or both copies of pub as appropriate */
281 printf(" ...free pubKey\n");
283 crtn
= cspFreeKey(cspHand
, &pubKey
);
285 printf("Error freeing pubKey\n");
286 return testError(quiet
);
290 printf(" ...free lookUpPub\n");
292 crtn
= cspFreeKey(cspHand
, lookUpPub
);
294 printf("Error freeing lookUpPub\n");
295 return testError(quiet
);
298 CSSM_FREE(lookUpPub
); // mallocd by lookup in any case
301 /* pub should still be there in DL */
302 /* lookUpPub = lookup pub by label; verify OK; */
304 printf(" ...lookup pub by label (2)\n");
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
);
313 /* now really delete it */
315 printf(" ...delete lookUpPub\n");
317 crtn
= cspDeleteKey(cspHand
, dlHand
, dbHand
, &labelData
, lookUpPub
);
319 printf("Error deleting lookUpPub\n");
320 return testError(quiet
);
322 CSSM_FREE(lookUpPub
); // mallocd by lookup
325 /* else freeKey should have removed all trace */
328 /* lookUpPub = lookup pub by label; verify fail; */
330 printf(" ...lookup (nonexistent) pub by label\n");
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
);
341 int main(int argc
, char **argv
)
346 CSSM_CSP_HANDLE cspHand
;
347 CSSM_DB_HANDLE dbHand
;
348 CSSM_DL_HANDLE dlHand
;
350 CSSM_BOOL privIsPerm
;
351 CSSM_BOOL privIsExtractable
;
352 uint32 keyGenAlg
= CSSM_ALGID_FEE
;
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
;
369 for(arg
=1; arg
<argc
; arg
++) {
373 loops
= atoi(&argp
[2]);
382 permKeys
= CSSM_TRUE
;
386 keyGenAlg
= CSSM_ALGID_RSA
;
389 memmove(dbName
, &argp
[2], strlen(&argp
[2]) + 1);
390 useExistDb
= CSSM_TRUE
;
401 if(dbName
[0] == '\0') {
402 sprintf(dbName
, "%s_%d", DB_NAME
, (int)getpid());
405 testStartBanner("keyStore", argc
, argv
);
407 /* attach to CSP/DL */
408 cspHand
= cspDlDbStartup(CSSM_FALSE
, NULL
);
412 dlHand
= dlStartup();
417 /* this one may well require SecurityAgent UI */
418 crtn
= dbCreateOpen(dlHand
, dbName
, CSSM_FALSE
, CSSM_FALSE
, NULL
,
422 /* hands-free test */
423 crtn
= dbCreateOpen(dlHand
, dbName
, CSSM_TRUE
, CSSM_TRUE
, dbName
,
429 for(loop
=1; ; loop
++) {
432 printf("...loop %d\n", loop
);
436 pubIsPerm
= privIsPerm
= CSSM_TRUE
;
439 /* mix up pubIsPerm, privIsPerm */
440 pubIsPerm
= (loop
& 1) ? CSSM_TRUE
: CSSM_FALSE
;
441 privIsPerm
= (loop
& 2) ? CSSM_TRUE
: CSSM_FALSE
;
443 privIsExtractable
= (loop
& 4) ? CSSM_TRUE
: CSSM_FALSE
;
457 if(loops
&& (loop
== loops
)) {
462 printf("CR to continue: ");
467 cspShutdown(cspHand
, CSSM_FALSE
);
468 /* FIXME - DB close? DL shutdown? */
469 if((rtn
== 0) && !quiet
) {
470 printf("%s test complete\n", argv
[0]);
473 /* be nice: if we ran OK delete the cruft DB we created */