]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/symReference/symReference.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / symReference / symReference.cpp
1 /*
2 * symReference.c - write keys and ciphertext blobs, read them back
3 * and decrypt on (possibly) a different platfrom.
4 * Intended for use in testing multiplatform
5 * compatibility (e.g. encrypt on 32 bit G4, decrypt
6 * on 64-bit G5).
7 *
8 * Created by Doug Mitchell 10/31/05.
9 */
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <time.h>
14 #include <Security/cssm.h>
15 #include <Security/cssmapple.h>
16 #include "cspwrap.h"
17 #include <security_cdsa_utils/cuFileIo.h>
18 #include "common.h"
19 #include <string.h>
20 #include "cspdlTesting.h"
21 #include <unistd.h>
22
23 /*
24 * Defaults.
25 */
26 #define LOOPS_DEF 200
27 #define PTEXT_SIZE_DEF 256
28 #define BLOCK_SIZE_MAX 32 /* bytes */
29
30 /*
31 * Enumerate algs our own way to allow iteration.
32 */
33 typedef enum {
34 ALG_ASC = 0, /* first must be 0 */
35 ALG_DES,
36 ALG_RC2,
37 ALG_RC4,
38 ALG_RC5,
39 ALG_3DES,
40 ALG_AES,
41 ALG_AES192,
42 ALG_AES256,
43 ALG_BFISH,
44 ALG_CAST
45 } SymAlg;
46
47 #define ALG_FIRST ALG_ASC
48 #define ALG_LAST ALG_CAST
49
50 static void usage(char **argv)
51 {
52 printf("usage: %s e|d dirName [options]\n", argv[0]);
53 printf(" e=encrypt, d=decrypt; blobs read/written in dirName\n");
54 printf(" Options:\n");
55 printf(" a=algorithm (d=DES; 3=3DES3; 2=RC2; 4=RC4; 5=RC5; a=AES; b=Blowfish; \n");
56 printf(" c=CAST; s=ASC, default=all)\n");
57 printf(" p=ptextSize (default=%d)\n", PTEXT_SIZE_DEF);
58 printf(" D (CSP/DL; default = bare CSP)\n");
59 printf(" v(erbose)\n");
60 printf(" q(uiet)\n");
61 printf(" h(elp)\n");
62 exit(1);
63 }
64
65 /*
66 * map SymAlg to test params
67 */
68 typedef struct {
69 SymAlg alg;
70 const char *algStr;
71 CSSM_ALGORITHMS cssmAlg;
72 CSSM_ENCRYPT_MODE mode;
73 CSSM_PADDING padding;
74 CSSM_SIZE keySizeBits;
75 CSSM_SIZE ivLen; // in bytes
76 } SymAlgParams;
77
78 static const SymAlgParams symAlgParams[] =
79 {
80 { ALG_ASC, "ASC", CSSM_ALGID_ASC, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE,
81 CSP_ASC_KEY_SIZE_DEFAULT, 0 },
82 { ALG_DES, "DES", CSSM_ALGID_DES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
83 CSP_DES_KEY_SIZE_DEFAULT, 8 },
84 { ALG_RC2, "RC2", CSSM_ALGID_RC2, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
85 CSP_RC2_KEY_SIZE_DEFAULT, 8 },
86 { ALG_RC4, "RC4", CSSM_ALGID_RC4, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE,
87 CSP_RC4_KEY_SIZE_DEFAULT, 0 },
88 { ALG_RC5, "RC5", CSSM_ALGID_RC5, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
89 CSP_RC5_KEY_SIZE_DEFAULT, 8 },
90 { ALG_3DES, "3DES", CSSM_ALGID_3DES_3KEY_EDE, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
91 CSP_DES3_KEY_SIZE_DEFAULT, 8 },
92 { ALG_AES, "AES", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
93 CSP_AES_KEY_SIZE_DEFAULT, 16 },
94 { ALG_AES192, "AES192", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
95 192, 24 },
96 { ALG_AES256, "AES256", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
97 256, 32 },
98 { ALG_BFISH, "Blowfish", CSSM_ALGID_BLOWFISH, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
99 CSP_BFISH_KEY_SIZE_DEFAULT, 8 },
100 { ALG_CAST, "CAST", CSSM_ALGID_CAST, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
101 CSP_CAST_KEY_SIZE_DEFAULT, 8 }
102 };
103
104 static void genFileNames(
105 const char *algStr,
106 char *keyFile,
107 char *ptextFile,
108 char *ctextFile,
109 char *ivFile)
110 {
111 sprintf(keyFile, "key_%s", algStr);
112 sprintf(ptextFile, "ptext_%s", algStr);
113 sprintf(ctextFile, "ctext_%s", algStr);
114 sprintf(ivFile, "iv_%s", algStr);
115 }
116
117 /* encrypt, write blobs (key, plaintext, ciphertext, optional IV) to disk */
118 static int doEncrypt(
119 CSSM_CSP_HANDLE cspHand,
120 const SymAlgParams *algParams,
121 CSSM_DATA *ptext, // mallocd, length valid, we fill data
122 CSSM_BOOL quiet,
123 CSSM_BOOL verbose)
124 {
125 CSSM_KEY_PTR symKey = NULL;
126 CSSM_KEY rawKey;
127 CSSM_RETURN crtn;
128 CSSM_DATA ctext = {0, NULL};
129 uint8 iv[BLOCK_SIZE_MAX];
130 CSSM_DATA ivd = {BLOCK_SIZE_MAX, iv};
131 CSSM_DATA *ivp = NULL;
132 uint32 blockSize = 0;
133 char keyFile[FILENAME_MAX];
134 char ptextFile[FILENAME_MAX];
135 char ctextFile[FILENAME_MAX];
136 char ivFile[FILENAME_MAX];
137
138 if(!quiet) {
139 printf("...encrypting, alg %s\n", algParams->algStr);
140 }
141
142 /* generate reference key (works with CSPDL) */
143 symKey = cspGenSymKey(cspHand, algParams->cssmAlg,
144 "noLabel", 7,
145 CSSM_KEYUSE_ANY, algParams->keySizeBits, CSSM_TRUE);
146 if(symKey == NULL) {
147 printf("***Error generating key for alg %s size %u bits\n",
148 algParams->algStr, (unsigned)algParams->keySizeBits);
149 return testError(quiet);
150 }
151
152 /* get key in raw format (to get the raw blob we write to disk) */
153 crtn = cspRefKeyToRaw(cspHand, symKey, &rawKey);
154 if(crtn) {
155 printf("***Error generating raw key for alg %s size %u bits\n",
156 algParams->algStr, (unsigned)algParams->keySizeBits);
157 return testError(quiet);
158 }
159
160 appGetRandomBytes(ptext->Data, (unsigned)ptext->Length);
161
162 /*
163 * Hack: we only need to specify block size for AES192 and AES256, which
164 * we detect by their having an ivLen of greater than 16.
165 */
166 if(algParams->ivLen > 16) {
167 blockSize = algParams->ivLen;
168 }
169 if(algParams->ivLen) {
170 appGetRandomBytes(iv, algParams->ivLen);
171 ivd.Length = algParams->ivLen;
172 ivp = &ivd;
173 }
174
175 crtn = cspStagedEncrypt(cspHand,
176 algParams->cssmAlg, algParams->mode, algParams->padding,
177 symKey, NULL,
178 0, blockSize, 0,
179 ivp, ptext,
180 &ctext,
181 CSSM_FALSE);
182 if(crtn) {
183 printf("***Error encrypting for alg %s size %u bits\n",
184 algParams->algStr, (unsigned)algParams->keySizeBits);
185 return testError(quiet);
186 }
187
188 /* write: key, IV, ptext, ctext */
189 genFileNames(algParams->algStr, keyFile, ptextFile, ctextFile, ivFile);
190 if(writeFile(keyFile, rawKey.KeyData.Data, (unsigned)rawKey.KeyData.Length) ||
191 writeFile(ptextFile, ptext->Data, (unsigned)ptext->Length) ||
192 writeFile(ctextFile, ctext.Data, (unsigned)ctext.Length)) {
193 printf("***Error writing result of alg %s size %u bits\n",
194 algParams->algStr, (unsigned)algParams->keySizeBits);
195 return testError(quiet);
196 }
197 if(ivp != NULL) {
198 if(writeFile(ivFile, ivp->Data, (unsigned)ivp->Length)) {
199 printf("***Error writing IV for alg %s size %u bits\n",
200 algParams->algStr, (unsigned)algParams->keySizeBits);
201 return testError(quiet);
202 }
203 }
204
205 /* Free resources */
206 CSSM_FreeKey(cspHand, NULL, symKey, CSSM_FALSE);
207 CSSM_FreeKey(cspHand, NULL, &rawKey, CSSM_FALSE);
208 CSSM_FREE(ctext.Data);
209 return 0;
210 }
211
212 /* read blobs (key, plaintext, ciphertext, optional IV) from disk, decrypt, compare plaintext */
213 static int doDecrypt(
214 CSSM_CSP_HANDLE cspHand,
215 const SymAlgParams *algParams,
216 CSSM_BOOL quiet,
217 CSSM_BOOL verbose)
218 {
219 CSSM_KEY symKey;
220 uint8 *symKeyBits;
221 unsigned symKeyLen; // in bytes
222 CSSM_DATA symKeyData;
223 CSSM_RETURN crtn;
224 uint8 *ctextChars;
225 unsigned ctextLen = 0;
226 CSSM_DATA ctext;
227 CSSM_DATA rptext = {0, NULL}; // recovered/decrytped
228 uint8 *refPTextChars;
229 unsigned refPtextLen;
230 CSSM_DATA refPtext = {0, NULL}; // expected
231 uint8 *iv = NULL;
232 unsigned ivLen;
233 CSSM_DATA ivd = {BLOCK_SIZE_MAX, iv};
234 CSSM_DATA *ivp = NULL;
235 uint32 blockSize = 0;
236 char keyFile[FILENAME_MAX];
237 char ptextFile[FILENAME_MAX];
238 char ctextFile[FILENAME_MAX];
239 char ivFile[FILENAME_MAX];
240
241 if(!quiet) {
242 printf("...decrypting, alg %s\n", algParams->algStr);
243 }
244
245 /*
246 * Hack: we only need to specify block size for AES192 and AES256, which
247 * we detect by their having an ivLen of greater than 16.
248 */
249 if(algParams->ivLen > 16) {
250 blockSize = algParams->ivLen;
251 }
252 if(algParams->ivLen) {
253 ivp = &ivd;
254 ivd.Length = algParams->ivLen;
255 }
256
257 /* read: key, IV, ptext, ctext */
258 genFileNames(algParams->algStr, keyFile, ptextFile, ctextFile, ivFile);
259 if(readFile(keyFile, &symKeyBits, &symKeyLen) ||
260 readFile(ptextFile, &refPTextChars, &refPtextLen) ||
261 readFile(ctextFile, &ctextChars, &ctextLen)) {
262 printf("***Error reading reference blobs for alg %s size %u bits\n",
263 algParams->algStr, (unsigned)algParams->keySizeBits);
264 return testError(quiet);
265 }
266 if(ivp != NULL) {
267 if(readFile(ivFile, &iv, &ivLen)) {
268 printf("***Error writing IV for alg %s size %u bits\n",
269 algParams->algStr, (unsigned)algParams->keySizeBits);
270 return testError(quiet);
271 }
272 if(ivLen != algParams->ivLen) {
273 printf("***Unexpected IV length: expect %u found %u\n",
274 (unsigned)algParams->ivLen, (unsigned)ivLen);
275 if(testError(quiet)) {
276 return 1;
277 }
278 }
279 ivd.Data = iv;
280 }
281 ctext.Data = ctextChars;
282 ctext.Length = ctextLen;
283 refPtext.Data = refPTextChars;
284 refPtext.Length = refPtextLen;
285
286 /* generate key */
287 symKeyData.Data = symKeyBits;
288 symKeyData.Length = symKeyLen;
289
290 crtn = cspGenSymKeyWithBits(cspHand, algParams->cssmAlg,
291 CSSM_KEYUSE_ANY, &symKeyData, symKeyLen, &symKey);
292 if(crtn) {
293 printf("***Error creating key for alg %s keySize %u\n",
294 algParams->algStr, (unsigned)algParams->keySizeBits);
295 return testError(quiet);
296 }
297
298 crtn = cspStagedDecrypt(cspHand,
299 algParams->cssmAlg, algParams->mode, algParams->padding,
300 &symKey, NULL,
301 0, blockSize, 0,
302 ivp, &ctext,
303 &rptext,
304 CSSM_FALSE);
305 if(crtn) {
306 printf("***Error decrypting for alg %s size %u bits\n",
307 algParams->algStr, (unsigned)algParams->keySizeBits);
308 return testError(quiet);
309 }
310
311 /* moment of truth */
312 if(!appCompareCssmData(&rptext, &refPtext)) {
313 printf("***DATA MISCOMPARE AFTER DECRYPT alg %s size %u bits\n",
314 algParams->algStr, (unsigned)algParams->keySizeBits);
315 return testError(quiet);
316 }
317
318 /* Free resources */
319 CSSM_FreeKey(cspHand, NULL, &symKey, CSSM_FALSE);
320 free(symKeyBits); // mallocd by readFile()
321 free(refPTextChars);
322 free(ctextChars);
323 CSSM_FREE(rptext.Data); // mallocd by CSP
324 if(iv) {
325 free(iv);
326 }
327 return 0;
328 }
329
330
331 int main(int argc, char **argv)
332 {
333 int arg;
334 char *argp;
335 CSSM_DATA ptext;
336 CSSM_CSP_HANDLE cspHand;
337 unsigned currAlg; // ALG_xxx
338 int rtn = 0;
339
340 /*
341 * User-spec'd params
342 */
343 unsigned minAlg = ALG_FIRST;
344 unsigned maxAlg = ALG_LAST;
345 CSSM_BOOL verbose = CSSM_FALSE;
346 CSSM_BOOL quiet = CSSM_FALSE;
347 CSSM_BOOL bareCsp = CSSM_TRUE;
348 bool encrypt = false;
349 unsigned ptextSize = PTEXT_SIZE_DEF;
350 char *dirName;
351
352 if(argc < 3) {
353 usage(argv);
354 }
355 switch(argv[1][0]) {
356 case 'e':
357 encrypt = true;
358 break;
359 case 'd':
360 encrypt = false;
361 break;
362 default:
363 usage(argv);
364 }
365 dirName = argv[2];
366
367 for(arg=3; arg<argc; arg++) {
368 argp = argv[arg];
369 switch(argp[0]) {
370 case 'a':
371 if(argp[1] != '=') {
372 usage(argv);
373 }
374 switch(argp[2]) {
375 case 's':
376 minAlg = maxAlg = ALG_ASC;
377 break;
378 case 'd':
379 minAlg = maxAlg = ALG_DES;
380 break;
381 case '3':
382 minAlg = maxAlg = ALG_3DES;
383 break;
384 case '2':
385 minAlg = maxAlg = ALG_RC2;
386 break;
387 case '4':
388 minAlg = maxAlg = ALG_RC4;
389 break;
390 case '5':
391 minAlg = maxAlg = ALG_RC5;
392 break;
393 case 'a':
394 minAlg = maxAlg = ALG_AES;
395 break;
396 case 'b':
397 minAlg = maxAlg = ALG_BFISH;
398 break;
399 case 'c':
400 minAlg = maxAlg = ALG_CAST;
401 break;
402 default:
403 usage(argv);
404 }
405 break;
406 case 'v':
407 verbose = CSSM_TRUE;
408 break;
409 case 'D':
410 bareCsp = CSSM_FALSE;
411 break;
412 case 'p':
413 ptextSize = atoi(&argp[2]);
414 break;
415 case 'q':
416 quiet = CSSM_TRUE;
417 break;
418 case 'h':
419 default:
420 usage(argv);
421 }
422 }
423 ptext.Data = (uint8 *)CSSM_MALLOC(ptextSize);
424 if(ptext.Data == NULL) {
425 printf("Insufficient heap space\n");
426 exit(1);
427 }
428 ptext.Length = ptextSize;
429
430 testStartBanner("symReference", argc, argv);
431
432 cspHand = cspDlDbStartup(bareCsp, NULL);
433 if(cspHand == 0) {
434 exit(1);
435 }
436
437 if(chdir(dirName)) {
438 perror(dirName);
439 printf("Error accessing directory %s. Aborting.\n", dirName);
440 exit(1);
441 }
442 for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
443 const SymAlgParams *algParams = &symAlgParams[currAlg];
444
445 if(encrypt) {
446 rtn = doEncrypt(cspHand, algParams, &ptext, quiet, verbose);
447 }
448 else {
449 rtn = doDecrypt(cspHand, algParams, quiet, verbose);
450 }
451 if(rtn) {
452 break;
453 }
454 } /* for algs */
455
456 cspShutdown(cspHand, bareCsp);
457 if((rtn == 0) && !quiet) {
458 printf("%s test complete\n", argv[0]);
459 }
460 CSSM_FREE(ptext.Data);
461 return rtn;
462 }
463
464