1/*
2 * keyHash.c - simple test of CSSM_APPLECSP_KEYDIGEST passthrough
3 */
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <time.h>
8#include <string.h>
9#include <Security/cssm.h>
10#include "cspwrap.h"
11#include "common.h"
12#include "cspdlTesting.h"
13
14#define USAGE_NAME		"noUsage"
15#define USAGE_NAME_LEN	(strlen(USAGE_NAME))
16#define LOOPS_DEF			10
17
18static void usage(char **argv)
19{
20	printf("usage: %s [options]\n", argv[0]);
21	printf("Options:\n");
22	printf("  l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
23	printf("  D (CSP/DL; default = bare CSP)\n");
24	printf("  p(ause on each loop)\n");
25	printf("  q(uiet)\n");
26	printf("  v(erbose))\n");
27	exit(1);
28}
29
30static void dumpBuf(uint8 *buf,
31	unsigned len)
32{
33	unsigned i;
34
35	printf("   ");
36	for(i=0; i<len; i++) {
37		printf("%02X ", buf[i]);
38		if((i % 24) == 23) {
39			printf("\n      ");
40		}
41	}
42	printf("\n");
43}
44
45/*
46 * Given a ref key:
47 *  NULL wrap to data key;
48 *  obtain hash of both keys;
49 *  ensure hashes are equal;
50 */
51static int doTest(
52	CSSM_CSP_HANDLE		cspHand,		// raw or CSPDL
53	CSSM_CSP_HANDLE		rawCspHand,		// raw, may be same as cspHand
54	CSSM_KEY_PTR		refKey,
55	CSSM_BOOL			verbose,
56	CSSM_BOOL			quiet)
57{
58	CSSM_KEY		rawKey;
59	CSSM_RETURN		crtn;
60	CSSM_DATA_PTR	refHash;
61	CSSM_DATA_PTR	rawHash;
62
63	if(refKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
64		printf("Hey! this only works on ref keys!!\n");
65		exit(1);
66	}
67
68	/* get raw key */
69	crtn = cspWrapKey(cspHand,
70		refKey,
71		NULL,			// wrappingKey
72		CSSM_ALGID_NONE,
73		CSSM_ALGMODE_NONE,
74		CSSM_KEYBLOB_WRAPPED_FORMAT_NONE,
75		CSSM_PADDING_NONE,
76		NULL,			// iv
77		NULL,			// descData
78		&rawKey);
79	if(crtn) {
80		return testError(quiet);
81	}
82
83	/* hash of both keys */
84	crtn = cspKeyHash(cspHand, refKey, &refHash);
85	if(crtn) {
86		return testError(quiet);
87	}
88	else {
89		if(verbose) {
90			printf("      ...Ref key hash:\n       ");
91			dumpBuf(refHash->Data, refHash->Length);
92		}
93	}
94	crtn = cspKeyHash(rawCspHand, &rawKey, &rawHash);
95	if(crtn) {
96		return testError(quiet);
97	}
98	else {
99		if(verbose) {
100			printf("      ...Raw key hash:\n       ");
101			dumpBuf(rawHash->Data, rawHash->Length);
102		}
103	}
104	if(!appCompareCssmData(refHash, rawHash)) {
105		printf("***Key Hash Miscompare!\n");
106		return testError(quiet);
107	}
108	appFreeCssmData(refHash, CSSM_TRUE);
109	appFreeCssmData(rawHash, CSSM_TRUE);
110	cspFreeKey(cspHand, &rawKey);
111	return 0;
112}
113
114int main(int argc, char **argv)
115{
116	int					arg;
117	char				*argp;
118	unsigned			loop;
119	CSSM_CSP_HANDLE 	cspHand;
120	CSSM_CSP_HANDLE 	rawCspHand;
121	int					rtn = 0;
122	CSSM_KEY			pubKey;
123	CSSM_KEY			privKey;
124	CSSM_KEY_PTR		symKey;
125	int					i;
126
127	/*
128	 * User-spec'd params
129	 */
130	unsigned			loops = LOOPS_DEF;
131	CSSM_BOOL			verbose = CSSM_FALSE;
132	CSSM_BOOL			quiet = CSSM_FALSE;
133	CSSM_BOOL			bareCsp = CSSM_TRUE;
134	CSSM_BOOL			doPause = CSSM_FALSE;
135
136	for(arg=1; arg<argc; arg++) {
137		argp = argv[arg];
138		switch(argp[0]) {
139		    case 'l':
140				loops = atoi(&argp[2]);
141				break;
142			case 'D':
143				bareCsp = CSSM_FALSE;
144				break;
145		    case 'p':
146		    	doPause = CSSM_TRUE;
147				break;
148		    case 'v':
149		    	verbose = CSSM_TRUE;
150				break;
151		    case 'q':
152		    	quiet = CSSM_TRUE;
153				break;
154		    case 'h':
155		    default:
156				usage(argv);
157		}
158	}
159
160	printf("Starting keyHash; args: ");
161	for(i=1; i<argc; i++) {
162		printf("%s ", argv[i]);
163	}
164	printf("\n");
165	cspHand = cspDlDbStartup(bareCsp, NULL);
166	if(cspHand == 0) {
167		exit(1);
168	}
169	if(bareCsp) {
170		rawCspHand = cspHand;
171	}
172	else {
173		rawCspHand = cspDlDbStartup(CSSM_TRUE, NULL);
174		if(rawCspHand == 0) {
175			exit(1);
176		}
177	}
178	for(loop=1; ; loop++) {
179		if(!quiet) {
180			printf("...loop %d\n", loop);
181		}
182
183		/* first with symmetric key */
184		if(verbose) {
185			printf("   ...testing DES key\n");
186		}
187		symKey = cspGenSymKey(cspHand,
188			CSSM_ALGID_DES,
189			USAGE_NAME,
190			USAGE_NAME_LEN,
191			CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
192			64,
193			CSSM_TRUE);			// refKey
194		if(symKey == NULL) {
195			if(testError(quiet)) {
196				break;
197			}
198		}
199		if(doTest(cspHand, rawCspHand, symKey, verbose, quiet)) {
200			break;
201		}
202		CSSM_FreeKey(cspHand, NULL, symKey, CSSM_TRUE);
203		CSSM_FREE(symKey);
204
205		/* cook up an RSA key pair */
206		rtn = cspGenKeyPair(cspHand,
207				CSSM_ALGID_RSA,
208				USAGE_NAME,
209				USAGE_NAME_LEN,
210				CSP_RSA_KEY_SIZE_DEFAULT,
211				&pubKey,
212				CSSM_TRUE,			// pubIsRef
213				CSSM_KEYUSE_ENCRYPT,
214				CSSM_KEYBLOB_RAW_FORMAT_NONE,
215				&privKey,
216				CSSM_TRUE,			// privIsRef
217				CSSM_KEYUSE_DECRYPT,
218				CSSM_KEYBLOB_RAW_FORMAT_NONE,
219				CSSM_FALSE);		// genSeed
220		if(rtn) {
221			if(testError(quiet)) {
222				break;
223			}
224		}
225		if(verbose) {
226			printf("   ...testing RSA public key\n");
227		}
228		if(doTest(cspHand, rawCspHand, &pubKey, verbose, quiet)) {
229			break;
230		}
231		if(verbose) {
232			printf("   ...testing RSA private key\n");
233		}
234		if(doTest(cspHand, rawCspHand, &privKey, verbose, quiet)) {
235			break;
236		}
237		CSSM_FreeKey(cspHand, NULL, &pubKey, CSSM_TRUE);
238		CSSM_FreeKey(cspHand, NULL, &privKey, CSSM_TRUE);
239		if(loops && (loop == loops)) {
240			break;
241		}
242		if(doPause) {
243			fpurge(stdin);
244			printf("Hit CR to proceed: ");
245			getchar();
246		}
247	}
248	return 0;
249}
250