]> git.saurik.com Git - apple/security.git/blob - libsecurity_cryptkit/ckutils/badsig/badsig.c
Security-55471.14.18.tar.gz
[apple/security.git] / libsecurity_cryptkit / ckutils / badsig / badsig.c
1 /* Copyright 1996-1997 Apple Computer, Inc.
2 *
3 * badsig.c - Verify bad signature detect
4 *
5 * Revision History
6 * ----------------
7 * 26 Aug 1996 Doug Mitchell at NeXT
8 * Created.
9 */
10
11 /*
12 * text size = {random, from 100 bytes to 1 megabyte, in
13 * geometrical steps, i.e. the number of
14 * bytes would be 10^r, where r is random out of
15 * {2,3,4,5,6}, plus a random integer in {0,..99}};
16 *
17 * password size = constant;
18 *
19 * for loop_count
20 * text contents = {random data, random size as specified above};
21 * passsword data = random;
22 *
23 Alternate between ECDSA and ElGamal on sucessive loops:
24 * generate signature, validate;
25 * for each byte of signature {
26 * corrupt text byte;
27 * verify bad signature;
28 * restore corrupted byte;
29 * }
30 * }
31 */
32
33 #import "Crypt.h"
34 #include "ckconfig.h"
35
36 #if !CRYPTKIT_HIGH_LEVEL_SIG
37 #error Can not build this program against a lib with !CRYPTKIT_HIGH_LEVEL_SIG.
38 #endif
39
40 #import <sys/param.h>
41 #import <libc.h>
42
43 static unsigned char *passwdPool; /* all passwords come from here */
44 static unsigned char *dataPool; /* plaintext comes from here */
45
46 #define MAX_DATA_SIZE ((1024 * 1024) + 100) /* bytes */
47
48 /*
49 * Defaults.
50 */
51 #define LOOPS_DEF 1
52 #define MIN_EXP 2 /* for data size 10**exp */
53 #define MAX_EXP 4
54 #define PWD_LENGTH 15 /* bytes */
55 #define DEPTH_DEFAULT FEE_DEPTH_DEFAULT
56 #define INCR_DEFAULT 1 /* munge every incr bytes */
57
58 ///#define DEPTH_DEFAULT FEE_DEPTH_5
59
60 static void usage(char **argv)
61 {
62 printf("usage: %s [options]\n", argv[0]);
63 printf(" Options:\n");
64 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
65 printf(" n=minExp (default=%d)\n", MIN_EXP);
66 printf(" x=maxExp (default=max=%d)\n", MAX_EXP);
67 printf(" p=passwdLength (default=%d)\n", PWD_LENGTH);
68 printf(" D=depth (default=%d)\n", DEPTH_DEFAULT);
69 printf(" i=increment (default=%d)\n", INCR_DEFAULT);
70 #if CRYPTKIT_ECDSA_ENABLE
71 printf(" e (ElGamal only, no ECDSA)\n");
72 #endif
73 printf(" s=seed\n");
74 printf(" v(erbose)\n");
75 printf(" q(uiet)\n");
76 printf(" h(elp)\n");
77 exit(1);
78 }
79
80 /*
81 * ...min <= return <= max
82 */
83 static int genRand(int min, int max)
84 {
85
86 /* note random() only yields a 31-bit number... */
87
88 if(max == min) /* avoid % 1 ! */
89 return(max);
90 else
91 return(min + (random() % (max-min+1)));
92 }
93
94 static unsigned char *genPasswd(unsigned passwdLength)
95 {
96 unsigned *ip = (unsigned *)passwdPool;
97 unsigned intCount = passwdLength / 4;
98 int i;
99 unsigned char *cp;
100 unsigned residue = passwdLength & 0x3;
101
102 for (i=0; i<intCount; i++) {
103 *ip++ = random();
104 }
105 cp = (unsigned char *)ip;
106 for(i=0; i<residue; i++) {
107 *cp = (unsigned char)random();
108 }
109 return passwdPool;
110 }
111
112 /*
113 * Calculate random data size, fill dataPool with that many random bytes.
114 */
115 typedef enum {
116 DT_Random,
117 DT_Zero,
118 DT_ASCII
119 } dataType;
120
121 #define MIN_OFFSET 0
122 #define MAX_OFFSET 99
123
124 #define MIN_ASCII ' '
125 #define MAX_ASCII '~'
126
127 static unsigned char *genData(unsigned minExp,
128 unsigned maxExp,
129 dataType type,
130 unsigned *length) // RETURNED
131 {
132 int exp;
133 int offset;
134 int size;
135 unsigned *ip;
136 unsigned intCount;
137 unsigned residue;
138 char *cp;
139 int i;
140 char ac;
141
142 /*
143 * Calculate "random" size : (10 ** (random exponent)) + random offset
144 */
145 exp = genRand(minExp, maxExp);
146 offset = genRand(MIN_OFFSET, MAX_OFFSET);
147 size = 1;
148 while(exp--) { // size = 10 ** exp
149 size *= 10;
150 }
151 size += offset;
152
153 switch(type) {
154 case DT_Zero:
155 bzero(dataPool, size);
156 break;
157 case DT_ASCII:
158 ac = MIN_ASCII;
159 cp = dataPool;
160 for(i=0; i<size; i++) {
161 *cp++ = ac++;
162 if(ac > MAX_ASCII) {
163 ac = MIN_ASCII;
164 }
165 }
166 break;
167 case DT_Random:
168 intCount = size >> 2;
169 ip = (unsigned *)dataPool;
170 for(i=0; i<intCount; i++) {
171 *ip++ = random();
172 }
173
174 residue = size & 0x3;
175 cp = (unsigned char *)ip;
176 for(i=0; i<residue; i++) {
177 *cp++ = (unsigned char)random();
178 }
179 break;
180 }
181 *length = size;
182 return dataPool;
183 }
184
185
186 static int sigError()
187 {
188 char resp[100];
189
190 printf("Attach via debugger for more info.\n");
191 printf("a to abort, c to continue: ");
192 gets(resp);
193 return (resp[0] != 'c');
194 }
195
196 #define LOG_FREQ 200
197
198 int doTest(unsigned char *ptext,
199 unsigned ptextLen,
200 unsigned char *passwd,
201 unsigned passwdLen,
202 int verbose,
203 int quiet,
204 unsigned depth,
205 unsigned incr,
206 int doECDSA,
207 int doECDSAVfy) // ignored if doECDSASig == 0
208 {
209 feePubKey *pubKey;
210 unsigned char *sig;
211 unsigned sigLen;
212 unsigned byte;
213 unsigned char origData;
214 unsigned char bits;
215 feeReturn frtn;
216
217 pubKey = feePubKeyAlloc();
218 frtn = feePubKeyInitFromPrivDataDepth(pubKey,
219 passwd,
220 passwdLen,
221 depth,
222 1);
223 if(frtn) {
224 printf("feePubKeyInitFromPrivData returned %s\n",
225 feeReturnString(frtn));
226 return sigError();
227 }
228 #if CRYPTKIT_ECDSA_ENABLE
229 if(doECDSA) {
230 frtn = feePubKeyCreateECDSASignature(pubKey,
231 ptext,
232 ptextLen,
233 &sig,
234 &sigLen);
235 if(frtn) {
236 printf("feePubKeyCreateECDSASignature returned %s\n",
237 feeReturnString(frtn));
238 return sigError();
239 }
240 if(doECDSAVfy) {
241 frtn = feePubKeyVerifyECDSASignature(pubKey,
242 ptext,
243 ptextLen,
244 sig,
245 sigLen);
246 }
247 else {
248 frtn = feePubKeyVerifySignature(pubKey,
249 ptext,
250 ptextLen,
251 sig,
252 sigLen);
253 }
254 }
255 else {
256 #else
257 {
258 #endif /* CRYPTKIT_ECDSA_ENABLE */
259 frtn = feePubKeyCreateSignature(pubKey,
260 ptext,
261 ptextLen,
262 &sig,
263 &sigLen);
264 if(frtn) {
265 printf("feePubKeyCreateSignature returned %s\n",
266 feeReturnString(frtn));
267 return sigError();
268 }
269 frtn = feePubKeyVerifySignature(pubKey,
270 ptext,
271 ptextLen,
272 sig,
273 sigLen);
274 }
275 if(frtn) {
276 printf("**Unexpected BAD signature\n");
277 return sigError();
278 }
279 for(byte=0; byte<ptextLen; byte += incr) {
280 if(!quiet && (verbose || ((byte % LOG_FREQ) == 0))) {
281 printf("....byte %d\n", byte);
282 }
283 origData = ptext[byte];
284
285 /*
286 * Generate random non-zero byte
287 */
288 do {
289 bits = random() & 0xff;
290 } while(bits == 0);
291
292 ptext[byte] ^= bits;
293 #if CRYPTKIT_ECDSA_ENABLE
294 if(doECDSA && doECDSAVfy) {
295 frtn = feePubKeyVerifyECDSASignature(pubKey,
296 ptext,
297 ptextLen,
298 sig,
299 sigLen);
300 }
301 else {
302 #else
303 {
304 #endif /* CRYPTKIT_ECDSA_ENABLE */
305 frtn = feePubKeyVerifySignature(pubKey,
306 ptext,
307 ptextLen,
308 sig,
309 sigLen);
310 }
311 if(frtn == FR_Success) {
312 printf("**Unexpected GOOD signature\n");
313 return sigError();
314 }
315 ptext[byte] = origData;
316 }
317 feePubKeyFree(pubKey);
318 return 0;
319 }
320
321 int main(int argc, char **argv)
322 {
323 int arg;
324 char *argp;
325 int loop;
326 unsigned char *ptext;
327 unsigned ptextLen;
328 unsigned char *passwd;
329 int doECDSA;
330 int doECDSAVfy;
331
332 /*
333 * User-spec'd params
334 */
335 unsigned passwdLen = PWD_LENGTH;
336 unsigned loops = LOOPS_DEF;
337 int seedSpec = 0;
338 unsigned seed;
339 int verbose = 0;
340 unsigned minExp = MIN_EXP;
341 unsigned maxExp = MAX_EXP;
342 int quiet = 0;
343 unsigned depth = DEPTH_DEFAULT;
344 unsigned incr = INCR_DEFAULT;
345 #if CRYPTKIT_ECDSA_ENABLE
346 int elGamalOnly = 0;
347 #else
348 int elGamalOnly = 1;
349 #endif
350
351 for(arg=1; arg<argc; arg++) {
352 argp = argv[arg];
353 switch(argp[0]) {
354 case 'l':
355 loops = atoi(&argp[2]);
356 break;
357 case 'n':
358 minExp = atoi(&argp[2]);
359 break;
360 case 'x':
361 maxExp = atoi(&argp[2]);
362 if(maxExp > MAX_EXP) {
363 usage(argv);
364 }
365 break;
366 case 'D':
367 depth = atoi(&argp[2]);
368 break;
369 case 'i':
370 incr = atoi(&argp[2]);
371 break;
372 case 's':
373 seed = atoi(&argp[2]);
374 seedSpec = 1;
375 break;
376 case 'p':
377 passwdLen = atoi(&argp[2]);
378 if(passwdLen == 0) {
379 usage(argv);
380 }
381 break;
382 case 'e':
383 elGamalOnly = 1;
384 break;
385 case 'v':
386 verbose = 1;
387 break;
388 case 'q':
389 quiet = 1;
390 break;
391 case 'h':
392 default:
393 usage(argv);
394 }
395 }
396
397 if(seedSpec == 0) {
398 time((long *)(&seed));
399 }
400 srandom(seed);
401 passwdPool = malloc(passwdLen);
402 dataPool = malloc(MAX_DATA_SIZE);
403
404 printf("Starting %s test: loops %d seed %d elGamalOnly %d depth %d\n",
405 argv[0], loops, seed, elGamalOnly, depth);
406
407 #if 0
408 /* debug only */
409 {
410 char s[20];
411 printf("attach, then CR to continue: ");
412 gets(s);
413 }
414 #endif 0
415
416 for(loop=1; ; loop++) {
417
418 ptext = genData(minExp, maxExp, DT_Random, &ptextLen);
419 passwd = genPasswd(passwdLen);
420
421 /*
422 * Alternate between ECDSA and ElGamal
423 */
424 if(elGamalOnly) {
425 doECDSA = 0;
426 doECDSAVfy = 0;
427 }
428 else {
429 if(loop & 1) {
430 doECDSA = 1;
431 if(loop & 2) {
432 doECDSAVfy = 1;
433 }
434 else {
435 doECDSAVfy = 0;
436 }
437 }
438 else {
439 doECDSA = 0;
440 doECDSAVfy = 0;
441 }
442 }
443 if(!quiet) {
444 printf("..loop %d text size %d ECDSA %d ECDSAVfy %d\n",
445 loop, ptextLen, doECDSA, doECDSAVfy);
446 }
447 if(doTest(ptext, ptextLen, passwd, passwdLen,
448 verbose, quiet, depth, incr,
449 doECDSA, doECDSAVfy)) {
450 exit(1);
451 }
452
453 if(loops && (loop == loops)) {
454 break;
455 }
456 }
457 if(!quiet) {
458 printf("%s test complete\n", argv[0]);
459 }
460 return 0;
461 }