1/* 2 * rawSig.c - Test compatiblity of (hash+sign) ops vs. manual digest followed 3 * by raw sign. 4 */ 5 6#include <stdlib.h> 7#include <stdio.h> 8#include <time.h> 9#include <Security/cssm.h> 10#include <Security/cssmapple.h> 11#include "cspwrap.h" 12#include "common.h" 13#include "bsafeUtils.h" 14#include "cspdlTesting.h" 15#include <string.h> 16 17/* 18 * Defaults. 19 */ 20#define OLOOPS_DEF 10 /* outer loops, one key pair per loop */ 21#define ILOOPS_DEF 10 /* sig loops */ 22#define MAX_TEXT_SIZE 1024 23 24#define LOOP_NOTIFY 20 25 26/* 27 * Enumerate algs our own way to allow iteration. 28 */ 29#define ALG_RSA_MD5 1 30#define ALG_RSA_SHA1 2 31#define ALG_RSA_MD2 3 32#define ALG_FEE_MD5 4 33#define ALG_FEE_SHA1 5 34#define ALG_ECDSA_SHA1 6 35#define ALG_DSA_SHA1 7 36#define ALG_ANSI_ECDSA_SHA1 8 37#define ALG_ECDSA_SHA256 9 38#define ALG_ECDSA_SHA384 10 39#define ALG_ECDSA_SHA512 11 40#define ALG_FIRST ALG_RSA_MD5 41#define ALG_LAST ALG_ECDSA_SHA512 42 43static void usage(char **argv) 44{ 45 printf("usage: %s [options]\n", argv[0]); 46 printf(" Options:\n"); 47 printf(" a=alg (5=RSA/MD5; 2=RSA/MD2; R=RSA/SHA1; d=DSA/SHA1; f=FEE/MD5; F=FEE/SHA1; \n"); 48 printf(" e=ECDSA/SHA1; E=ANSI_ECDSA/SHA1; 7=ECDSA/SHA256; 8=ECDSA/SHA384; 9=ECDSA/512; default=all)\n"); 49 printf(" l=outerloops (default=%d; 0=forever)\n", OLOOPS_DEF); 50 printf(" i=innerLoops (default=%d)\n", ILOOPS_DEF); 51 printf(" k=keySizeInBits; default is random\n"); 52 printf(" p=pauseInterval (default=0, no pause)\n"); 53 printf(" s(mall keys)\n"); 54 printf(" D (CSP/DL; default = bare CSP)\n"); 55 printf(" v(erbose)\n"); 56 printf(" q(uiet)\n"); 57 printf(" h(elp)\n"); 58 exit(1); 59} 60 61int main(int argc, char **argv) 62{ 63 int arg; 64 char *argp; 65 unsigned oloop; 66 unsigned iloop; 67 CSSM_DATA ptext = {0, NULL}; 68 CSSM_CSP_HANDLE cspHand; 69 int i; 70 int rtn = 0; 71 uint32 keySizeInBits = 0; 72 CSSM_KEY pubKey; 73 CSSM_KEY privKey; 74 CSSM_DATA sig = {0, NULL}; 75 CSSM_DATA digest = {0, NULL}; 76 CSSM_RETURN crtn; 77 unsigned currAlg; 78 79 /* current alg (e.g. ALG_FEE_SHA1) parsed to come up with these */ 80 CSSM_ALGORITHMS digestAlg; 81 CSSM_ALGORITHMS rawSigAlg; 82 CSSM_ALGORITHMS sigAlg; 83 CSSM_ALGORITHMS keyGenAlg; 84 const char *sigAlgStr; 85 86 /* 87 * User-spec'd params 88 */ 89 CSSM_BOOL keySizeSpec = CSSM_FALSE; 90 unsigned oloops = OLOOPS_DEF; 91 unsigned iloops = ILOOPS_DEF; 92 CSSM_BOOL verbose = CSSM_FALSE; 93 CSSM_BOOL quiet = CSSM_FALSE; 94 unsigned pauseInterval = 0; 95 CSSM_BOOL bareCsp = CSSM_TRUE; 96 unsigned minAlg = ALG_FIRST; 97 uint32 maxAlg = ALG_LAST; 98 CSSM_BOOL smallKeys = CSSM_FALSE; 99 100 for(arg=1; arg<argc; arg++) { 101 argp = argv[arg]; 102 switch(argp[0]) { 103 case 'a': 104 switch(argp[2]) { 105 case 'f': 106 minAlg = maxAlg = ALG_FEE_MD5; 107 break; 108 case 'F': 109 minAlg = maxAlg = ALG_FEE_SHA1; 110 break; 111 case 'e': 112 minAlg = maxAlg = ALG_ECDSA_SHA1; 113 break; 114 case '5': 115 minAlg = maxAlg = ALG_RSA_MD5; 116 break; 117 case '2': 118 minAlg = maxAlg = ALG_RSA_MD2; 119 break; 120 case 'R': 121 minAlg = maxAlg = ALG_RSA_SHA1; 122 break; 123 case 'd': 124 minAlg = maxAlg = ALG_DSA_SHA1; 125 break; 126 case 'E': 127 minAlg = maxAlg = ALG_ANSI_ECDSA_SHA1; 128 break; 129 case '7': 130 minAlg = maxAlg = ALG_ECDSA_SHA256; 131 break; 132 case '8': 133 minAlg = maxAlg = ALG_ECDSA_SHA384; 134 break; 135 case '9': 136 minAlg = maxAlg = ALG_ECDSA_SHA512; 137 break; 138 default: 139 usage(argv); 140 } 141 break; 142 case 'l': 143 oloops = atoi(&argp[2]); 144 break; 145 case 'i': 146 iloops = atoi(&argp[2]); 147 break; 148 case 'k': 149 keySizeInBits = atoi(&argp[2]); 150 keySizeSpec = CSSM_TRUE; 151 break; 152 case 'v': 153 verbose = CSSM_TRUE; 154 break; 155 case 'D': 156 bareCsp = CSSM_FALSE; 157 break; 158 case 'q': 159 quiet = CSSM_TRUE; 160 break; 161 case 's': 162 smallKeys = CSSM_TRUE; 163 break; 164 case 'p': 165 pauseInterval = atoi(&argp[2]);; 166 break; 167 case 'h': 168 default: 169 usage(argv); 170 } 171 } 172 173 ptext.Data = (uint8 *)CSSM_MALLOC(MAX_TEXT_SIZE); 174 if(ptext.Data == NULL) { 175 printf("Insufficient heap space\n"); 176 exit(1); 177 } 178 /* ptext length set in inner test loop */ 179 180 printf("Starting rawSig; args: "); 181 for(i=1; i<argc; i++) { 182 printf("%s ", argv[i]); 183 } 184 printf("\n"); 185 cspHand = cspDlDbStartup(bareCsp, NULL); 186 if(cspHand == 0) { 187 exit(1); 188 } 189 if(pauseInterval) { 190 fpurge(stdin); 191 printf("Top of test; hit CR to proceed: "); 192 getchar(); 193 } 194 for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) { 195 /* get current algs */ 196 switch(currAlg) { 197 case ALG_RSA_MD5: 198 digestAlg = CSSM_ALGID_MD5; 199 rawSigAlg = CSSM_ALGID_RSA; 200 sigAlg = CSSM_ALGID_MD5WithRSA; 201 keyGenAlg = CSSM_ALGID_RSA; 202 sigAlgStr = "MD5WithRSA"; 203 break; 204 case ALG_RSA_MD2: 205 digestAlg = CSSM_ALGID_MD2; 206 rawSigAlg = CSSM_ALGID_RSA; 207 sigAlg = CSSM_ALGID_MD2WithRSA; 208 keyGenAlg = CSSM_ALGID_RSA; 209 sigAlgStr = "MD2WithRSA"; 210 break; 211 case ALG_RSA_SHA1: 212 digestAlg = CSSM_ALGID_SHA1; 213 rawSigAlg = CSSM_ALGID_RSA; 214 sigAlg = CSSM_ALGID_SHA1WithRSA; 215 keyGenAlg = CSSM_ALGID_RSA; 216 sigAlgStr = "SHA1WithRSA"; 217 break; 218 case ALG_DSA_SHA1: 219 digestAlg = CSSM_ALGID_SHA1; 220 rawSigAlg = CSSM_ALGID_DSA; 221 sigAlg = CSSM_ALGID_SHA1WithDSA; 222 keyGenAlg = CSSM_ALGID_DSA; 223 sigAlgStr = "SHA1WithDSA"; 224 break; 225 case ALG_FEE_MD5: 226 digestAlg = CSSM_ALGID_MD5; 227 rawSigAlg = CSSM_ALGID_FEE; 228 sigAlg = CSSM_ALGID_FEE_MD5; 229 keyGenAlg = CSSM_ALGID_FEE; 230 sigAlgStr = "MD5WithFEE"; 231 break; 232 case ALG_FEE_SHA1: 233 digestAlg = CSSM_ALGID_SHA1; 234 rawSigAlg = CSSM_ALGID_FEE; 235 sigAlg = CSSM_ALGID_FEE_SHA1; 236 keyGenAlg = CSSM_ALGID_FEE; 237 sigAlgStr = "SHA1WithFEE"; 238 break; 239 case ALG_ECDSA_SHA1: 240 digestAlg = CSSM_ALGID_SHA1; 241 rawSigAlg = CSSM_ALGID_ECDSA; 242 sigAlg = CSSM_ALGID_SHA1WithECDSA; 243 keyGenAlg = CSSM_ALGID_FEE; 244 sigAlgStr = "SHA1WithECDSA"; 245 break; 246 case ALG_ANSI_ECDSA_SHA1: 247 digestAlg = CSSM_ALGID_SHA1; 248 rawSigAlg = CSSM_ALGID_ECDSA; 249 sigAlg = CSSM_ALGID_SHA1WithECDSA; 250 keyGenAlg = CSSM_ALGID_ECDSA; 251 sigAlgStr = "ANSI ECDSA"; 252 break; 253 case ALG_ECDSA_SHA256: 254 digestAlg = CSSM_ALGID_SHA256; 255 rawSigAlg = CSSM_ALGID_ECDSA; 256 sigAlg = CSSM_ALGID_SHA256WithECDSA; 257 keyGenAlg = CSSM_ALGID_ECDSA; 258 sigAlgStr = "ECDSA/SHA256"; 259 break; 260 case ALG_ECDSA_SHA384: 261 digestAlg = CSSM_ALGID_SHA384; 262 rawSigAlg = CSSM_ALGID_ECDSA; 263 sigAlg = CSSM_ALGID_SHA384WithECDSA; 264 keyGenAlg = CSSM_ALGID_ECDSA; 265 sigAlgStr = "ECDSA/SHA384"; 266 break; 267 case ALG_ECDSA_SHA512: 268 digestAlg = CSSM_ALGID_SHA512; 269 rawSigAlg = CSSM_ALGID_ECDSA; 270 sigAlg = CSSM_ALGID_SHA512WithECDSA; 271 keyGenAlg = CSSM_ALGID_ECDSA; 272 sigAlgStr = "ECDSA/SHA512"; 273 break; 274 default: 275 printf("BRRZAP!\n"); 276 exit(1); 277 } 278 if(!quiet) { 279 printf("Testing alg %s...\n", sigAlgStr); 280 } 281 for(oloop=0; ; oloop++) { 282 283 /* key size? */ 284 if(smallKeys) { 285 keySizeInBits = cspDefaultKeySize(keyGenAlg); 286 } 287 else if(!keySizeSpec) { 288 /* random key size */ 289 keySizeInBits = randKeySizeBits(rawSigAlg, OT_Sign); 290 } 291 292 if(!quiet) { 293 if(verbose || ((oloop % LOOP_NOTIFY) == 0)) { 294 printf(" ...oloop %d keySize %u\n", oloop, (unsigned)keySizeInBits); 295 } 296 } 297 298 /* generate a key pair */ 299 if(currAlg == ALG_DSA_SHA1) { 300 CSSM_BOOL doGenParams; 301 302 if(bareCsp || CSPDL_DSA_GEN_PARAMS) { 303 doGenParams = CSSM_TRUE; 304 } 305 else { 306 /* CSPDL - no gen params */ 307 doGenParams = CSSM_FALSE; 308 } 309 crtn = cspGenDSAKeyPair(cspHand, 310 "foo", 311 3, 312 keySizeInBits, 313 &pubKey, 314 CSSM_TRUE, // all keys ref for speed 315 CSSM_KEYUSE_VERIFY, 316 CSSM_KEYBLOB_RAW_FORMAT_NONE, 317 &privKey, 318 CSSM_TRUE, 319 CSSM_KEYUSE_SIGN, 320 CSSM_KEYBLOB_RAW_FORMAT_NONE, 321 doGenParams, // genParams 322 NULL); // params 323 } 324 else { 325 crtn = cspGenKeyPair(cspHand, 326 keyGenAlg, 327 "foo", 328 3, 329 keySizeInBits, 330 &pubKey, 331 CSSM_TRUE, // all keys ref for speed 332 CSSM_KEYUSE_VERIFY, 333 CSSM_KEYBLOB_RAW_FORMAT_NONE, 334 &privKey, 335 CSSM_TRUE, 336 CSSM_KEYUSE_SIGN, 337 CSSM_KEYBLOB_RAW_FORMAT_NONE, 338 CSSM_FALSE); // genSeed not used 339 } 340 if(crtn) { 341 return testError(quiet); 342 } 343 344 for(iloop=0; iloop<iloops; iloop++) { 345 CSSM_CC_HANDLE sigHand; 346 347 /* new plaintext each inner loop */ 348 simpleGenData(&ptext, 1, MAX_TEXT_SIZE); 349 if(!quiet) { 350 if(verbose || ((iloop % LOOP_NOTIFY) == 0)) { 351 printf(" ...iloop %d text size %lu\n", 352 iloop, ptext.Length); 353 } 354 } 355 356 /*** phase 1 ***/ 357 358 /* digest+sign */ 359 crtn = cspStagedSign(cspHand, 360 sigAlg, 361 &privKey, 362 &ptext, 363 CSSM_TRUE, // multiUpdates 364 &sig); 365 if(crtn && testError(quiet)) { 366 goto abort; 367 } 368 369 /* manual digest */ 370 crtn = cspStagedDigest(cspHand, 371 digestAlg, 372 CSSM_FALSE, // mallocDigest 373 CSSM_TRUE, // multiUpdates 374 &ptext, 375 &digest); 376 if(crtn && testError(quiet)) { 377 goto abort; 378 } 379 380 /* raw verify of the digest */ 381 crtn = CSSM_CSP_CreateSignatureContext(cspHand, 382 rawSigAlg, 383 NULL, // passPhrase 384 &pubKey, 385 &sigHand); 386 if(crtn) { 387 printError("CSSM_CSP_CreateSignatureContext (1)", crtn); 388 return crtn; 389 } 390 crtn = CSSM_VerifyData(sigHand, 391 &digest, 392 1, 393 digestAlg, 394 &sig); 395 if(crtn) { 396 printError("CSSM_VerifyData(raw)", crtn); 397 if(testError(quiet)) { 398 goto abort; 399 } 400 } 401 402 /* free resources - reuse the digest for raw sign */ 403 appFreeCssmData(&sig, CSSM_FALSE); 404 CSSM_DeleteContext(sigHand); 405 406 /*** phase 2 ***/ 407 408 /* raw sign the digest */ 409 crtn = CSSM_CSP_CreateSignatureContext(cspHand, 410 rawSigAlg, 411 NULL, // passPhrase 412 &privKey, 413 &sigHand); 414 if(crtn) { 415 printError("CSSM_CSP_CreateSignatureContext (2)", crtn); 416 return crtn; 417 } 418 crtn = CSSM_SignData(sigHand, 419 &digest, 420 1, 421 digestAlg, 422 &sig); 423 if(crtn) { 424 printError("CSSM_SignData(raw)", crtn); 425 if(testError(quiet)) { 426 goto abort; 427 } 428 } 429 430 /* all-in-one verify */ 431 crtn = cspStagedSigVerify(cspHand, 432 sigAlg, 433 &pubKey, 434 &ptext, 435 &sig, 436 CSSM_TRUE, // multiUpdates 437 CSSM_OK); 438 if(crtn && testError(quiet)) { 439 goto abort; 440 } 441 442 /* clean up */ 443 appFreeCssmData(&sig, CSSM_FALSE); 444 appFreeCssmData(&digest, CSSM_FALSE); 445 CSSM_DeleteContext(sigHand); 446 } /* end of inner loop */ 447 448 /* free keys */ 449 cspFreeKey(cspHand, &pubKey); 450 cspFreeKey(cspHand, &privKey); 451 452 if(oloops && (oloop == oloops)) { 453 break; 454 } 455 if(pauseInterval && ((oloop % pauseInterval) == 0)) { 456 fpurge(stdin); 457 printf("hit CR to proceed: "); 458 getchar(); 459 } 460 } /* oloop */ 461 } /* for alg */ 462 463abort: 464 cspShutdown(cspHand, bareCsp); 465 if(pauseInterval) { 466 fpurge(stdin); 467 printf("ModuleDetach/Unload complete; hit CR to exit: "); 468 getchar(); 469 } 470 if((rtn == 0) && !quiet) { 471 printf("%s test complete\n", argv[0]); 472 } 473 CSSM_FREE(ptext.Data); 474 return rtn; 475} 476 477 478