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 57static unsigned char *passwdPool; /* all passwords come from here */ 58static 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 74static 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 */ 97static 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 108static 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 */ 129typedef 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 141static 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 200static 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 212int 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 335int 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} 476