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