1/* 2 * Tool to cook up key pair, sign & verify, any which way 3 * with tons of options. 4 */ 5#include <string.h> 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 <security_cdsa_utils/cuFileIo.h> 14 15#define DATA_SIZE_DEF 100 16#define USAGE_DEF "noUsage" 17#define LOOPS_DEF 10 18#define FEE_PASSWD_LEN 32 /* private data length in bytes, FEE only */ 19 20static void usage(char **argv) 21{ 22 printf("usage: %s [options]\n", argv[0]); 23 printf("Options:\n"); 24 printf(" a=algorithm\n"); 25 printf(" f=FEE/MD5 F=FEE/SHA1 e=ECDSA r=RSA/MD5 2=RSA/MD2 \n"); 26 printf(" s=RSA/SHA1 d=DSA R=rawRSA (No digest) \n"); 27 printf(" 4=RSA/SHA224 6=RSA/SHA256 3=RSA/SHA384 5=RSA/SHA512;\n"); 28 printf(" E=ECDSA/ANSI; 7=ECDSA/SHA256; 8=ECDSA/SHA384; 9=ECDSA/512; default=RSA/SHA1\n"); 29 printf(" d=dataSize (default = %d)\n", DATA_SIZE_DEF); 30 printf(" k=keySize\n"); 31 printf(" b (pub is blob)\n"); 32 printf(" r (priv is blob)\n"); 33 printf(" B=[1xboOt] (pub key in PKCS1/X509/BSAFE/OpenSSH1/OpenSSH2/Octet form)\n"); 34 printf(" RSA = {PKCS1,X509,OpenSSH1,OpenSSH2} default = PKCS1\n"); 35 printf(" DSA = {BSAFE,X509,OpenSSH2} default = X509\n"); 36 printf(" ECDSA = {X509, Only!} default = X509\n"); 37 printf(" P=primeType (m=Mersenne, f=FEE, g=general; FEE only)\n"); 38 printf(" C=curveType (m=Montgomery, w=Weierstrass, a=ANSI; FEE only)\n"); 39 printf(" l=loops (0=forever)\n"); 40 printf(" s(ign only)\n"); 41 printf(" V(erify only)\n"); 42 printf(" c(ontexts only)\n"); 43 printf(" S (we generate seed, for FEE only)\n"); 44 printf(" n(o padding; default is PKCS1)\n"); 45 printf(" p=pauseInterval (default=0, no pause)\n"); 46 printf(" D (CSP/DL; default = bare CSP)\n"); 47 printf(" L (dump key and signature blobs)\n"); 48 printf(" o (key blobs in OCTET_STRING format)\n"); 49 printf(" q(uiet)\n"); 50 printf(" v(erbose))\n"); 51 exit(1); 52} 53 54/* parse public key format character */ 55static CSSM_KEYBLOB_FORMAT parsePubKeyFormat(char c, char **argv) 56{ 57 switch(c) { 58 case '1': 59 return CSSM_KEYBLOB_RAW_FORMAT_PKCS1; 60 case 'x': 61 return CSSM_KEYBLOB_RAW_FORMAT_X509; 62 case 'b': 63 return CSSM_KEYBLOB_RAW_FORMAT_FIPS186; 64 case 'o': 65 return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH; 66 case 'O': 67 return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2; 68 default: 69 usage(argv); 70 } 71 /* not reached */ 72 return -1; 73} 74 75int main(int argc, char **argv) 76{ 77 int arg; 78 char *argp; 79 CSSM_CSP_HANDLE cspHand; 80 CSSM_CC_HANDLE pubSigHand; 81 CSSM_CC_HANDLE privSigHand; 82 CSSM_RETURN crtn; 83 CSSM_DATA randData = {0, NULL}; 84 CSSM_KEY privKey; 85 CSSM_KEY pubKey; 86 CSSM_DATA sigData = {0, NULL}; 87 unsigned loop; 88 int i; 89 unsigned dataSize = DATA_SIZE_DEF; 90 unsigned keySize = CSP_KEY_SIZE_DEFAULT; 91 uint32 sigAlg = CSSM_ALGID_SHA1WithRSA; 92 uint32 keyGenAlg = CSSM_ALGID_RSA; 93 unsigned pauseInterval = 0; 94 unsigned loops = LOOPS_DEF; 95 CSSM_BOOL quiet = CSSM_FALSE; 96 CSSM_BOOL pubIsRef = CSSM_TRUE; 97 CSSM_BOOL privIsRef = CSSM_TRUE; 98 CSSM_BOOL doSign = CSSM_TRUE; 99 CSSM_BOOL doVerify = CSSM_TRUE; 100 CSSM_BOOL contextsOnly = CSSM_FALSE; 101 CSSM_BOOL noPadding = CSSM_FALSE; 102 CSSM_BOOL verbose = CSSM_FALSE; 103 CSSM_BOOL bareCsp = CSSM_TRUE; 104 CSSM_BOOL genSeed = CSSM_FALSE; 105 CSSM_BOOL dumpBlobs = CSSM_FALSE; 106 CSSM_KEYBLOB_FORMAT privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE; 107 CSSM_KEYBLOB_FORMAT pubKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE; 108 uint32 primeType = CSSM_FEE_PRIME_TYPE_DEFAULT; // FEE only 109 uint32 curveType = CSSM_FEE_CURVE_TYPE_DEFAULT; // FEE only 110 111 for(arg=1; arg<argc; arg++) { 112 argp = argv[arg]; 113 switch(argv[arg][0]) { 114 case 'a': 115 if(argp[1] != '=') { 116 usage(argv); 117 } 118 switch(argp[2]) { 119 case 'f': 120 sigAlg = CSSM_ALGID_FEE_MD5; 121 keyGenAlg = CSSM_ALGID_FEE; 122 break; 123 case 'F': 124 sigAlg = CSSM_ALGID_FEE_SHA1; 125 keyGenAlg = CSSM_ALGID_FEE; 126 break; 127 case 'e': 128 sigAlg = CSSM_ALGID_SHA1WithECDSA; 129 keyGenAlg = CSSM_ALGID_FEE; 130 break; 131 case 'E': 132 sigAlg = CSSM_ALGID_SHA1WithECDSA; 133 keyGenAlg = CSSM_ALGID_ECDSA; 134 break; 135 case '7': 136 sigAlg = CSSM_ALGID_SHA256WithECDSA; 137 keyGenAlg = CSSM_ALGID_ECDSA; 138 break; 139 case '8': 140 sigAlg = CSSM_ALGID_SHA384WithECDSA; 141 keyGenAlg = CSSM_ALGID_ECDSA; 142 break; 143 case '9': 144 sigAlg = CSSM_ALGID_SHA512WithECDSA; 145 keyGenAlg = CSSM_ALGID_ECDSA; 146 break; 147 case 'r': 148 sigAlg = CSSM_ALGID_MD5WithRSA; 149 keyGenAlg = CSSM_ALGID_RSA; 150 break; 151 case '2': 152 sigAlg = CSSM_ALGID_MD2WithRSA; 153 keyGenAlg = CSSM_ALGID_RSA; 154 break; 155 case 's': 156 sigAlg = CSSM_ALGID_SHA1WithRSA; 157 keyGenAlg = CSSM_ALGID_RSA; 158 break; 159 case 'd': 160 sigAlg = CSSM_ALGID_SHA1WithDSA; 161 keyGenAlg = CSSM_ALGID_DSA; 162 break; 163 case 'R': 164 sigAlg = CSSM_ALGID_RSA; 165 keyGenAlg = CSSM_ALGID_RSA; 166 break; 167 case '4': 168 sigAlg = CSSM_ALGID_SHA224WithRSA; 169 keyGenAlg = CSSM_ALGID_RSA; 170 break; 171 case '6': 172 sigAlg = CSSM_ALGID_SHA256WithRSA; 173 keyGenAlg = CSSM_ALGID_RSA; 174 break; 175 case '3': 176 sigAlg = CSSM_ALGID_SHA384WithRSA; 177 keyGenAlg = CSSM_ALGID_RSA; 178 break; 179 case '5': 180 sigAlg = CSSM_ALGID_SHA512WithRSA; 181 keyGenAlg = CSSM_ALGID_RSA; 182 break; 183 default: 184 usage(argv); 185 } 186 break; 187 case 'd': 188 dataSize = atoi(&argv[arg][2]); 189 break; 190 case 'k': 191 keySize = atoi(&argv[arg][2]); 192 break; 193 case 'l': 194 loops = atoi(&argv[arg][2]); 195 break; 196 case 'p': 197 pauseInterval = atoi(&argv[arg][2]); 198 break; 199 case 'b': 200 pubIsRef = CSSM_FALSE; 201 break; 202 case 'r': 203 privIsRef = CSSM_FALSE; 204 break; 205 case 'B': 206 if(argp[1] != '=') { 207 usage(argv); 208 } 209 pubKeyFormat = parsePubKeyFormat(argp[2], argv); 210 break; 211 case 's': 212 doVerify = CSSM_FALSE; 213 break; 214 case 'V': 215 doSign = CSSM_FALSE; 216 break; 217 case 'S': 218 genSeed = CSSM_TRUE; 219 break; 220 case 'n': 221 noPadding = CSSM_TRUE; 222 break; 223 case 'L': 224 dumpBlobs = CSSM_TRUE; 225 break; 226 case 'c': 227 contextsOnly = CSSM_TRUE; 228 break; 229 case 'D': 230 bareCsp = CSSM_FALSE; 231 break; 232 case 'q': 233 quiet = CSSM_TRUE; 234 break; 235 case 'v': 236 verbose = CSSM_TRUE; 237 break; 238 case 'o': 239 /* this is for FEE only */ 240 pubKeyFormat = privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; 241 break; 242 case 'C': 243 switch(argp[2]) { 244 case 'm': 245 curveType = CSSM_FEE_CURVE_TYPE_MONTGOMERY; 246 break; 247 case 'w': 248 curveType = CSSM_FEE_CURVE_TYPE_WEIERSTRASS; 249 break; 250 case 'a': 251 curveType = CSSM_FEE_CURVE_TYPE_ANSI_X9_62; 252 break; 253 default: 254 usage(argv); 255 } 256 break; 257 case 'P': 258 switch(argp[2]) { 259 case 'm': 260 primeType = CSSM_FEE_PRIME_TYPE_MERSENNE; 261 break; 262 case 'f': 263 primeType = CSSM_FEE_PRIME_TYPE_FEE; 264 break; 265 case 'g': 266 primeType = CSSM_FEE_PRIME_TYPE_GENERAL; 267 break; 268 default: 269 usage(argv); 270 } 271 break; 272 default: 273 usage(argv); 274 } 275 } 276 if(!doSign && !doVerify) { 277 printf("s and v mutually exclusive\n"); 278 exit(1); 279 } 280 cspHand = cspDlDbStartup(bareCsp, NULL); 281 if(cspHand == 0) { 282 exit(1); 283 } 284 printf("Starting sigtest; args: "); 285 for(i=1; i<argc; i++) { 286 printf("%s ", argv[i]); 287 } 288 if(keyGenAlg == CSSM_ALGID_FEE) { 289 uint8 passwd[FEE_PASSWD_LEN]; 290 CSSM_DATA pwdData = {FEE_PASSWD_LEN, passwd}; 291 CSSM_DATA_PTR pwdDataPtr; 292 293 if(genSeed) { 294 simpleGenData(&pwdData, FEE_PASSWD_LEN, FEE_PASSWD_LEN); 295 pwdDataPtr = &pwdData; 296 } 297 else { 298 pwdDataPtr = NULL; 299 } 300 crtn = cspGenFEEKeyPair(cspHand, 301 USAGE_DEF, 302 strlen(USAGE_DEF), 303 keySize, 304 primeType, 305 curveType, 306 &pubKey, 307 pubIsRef, 308 CSSM_KEYUSE_VERIFY, 309 pubKeyFormat, 310 &privKey, 311 privIsRef, 312 CSSM_KEYUSE_SIGN, 313 CSSM_KEYBLOB_RAW_FORMAT_NONE, 314 pwdDataPtr); 315 316 } 317 else if((keyGenAlg == CSSM_ALGID_DSA) && !bareCsp) { 318 /* CSPDL doesn't do gen alg params */ 319 crtn = cspGenDSAKeyPair(cspHand, 320 USAGE_DEF, 321 strlen(USAGE_DEF), 322 keySize, 323 &pubKey, 324 pubIsRef, 325 CSSM_KEYUSE_VERIFY, 326 pubKeyFormat, 327 &privKey, 328 privIsRef, 329 CSSM_KEYUSE_SIGN, 330 CSSM_KEYBLOB_RAW_FORMAT_NONE, 331 CSSM_FALSE, 332 NULL); 333 } 334 else { 335 crtn = cspGenKeyPair(cspHand, 336 keyGenAlg, 337 USAGE_DEF, 338 strlen(USAGE_DEF), 339 keySize, 340 &pubKey, 341 pubIsRef, 342 CSSM_KEYUSE_VERIFY, 343 pubKeyFormat, 344 &privKey, 345 privIsRef, 346 CSSM_KEYUSE_SIGN, 347 privKeyFormat, 348 genSeed); 349 } 350 if(crtn) { 351 CSSM_ModuleDetach(cspHand); 352 exit(1); 353 } 354 if(dumpBlobs) { 355 if(!pubIsRef) { 356 writeFile("pubKey.blob", pubKey.KeyData.Data, pubKey.KeyData.Length); 357 printf("...wrote %lu bytes to pubKey.blob\n", pubKey.KeyData.Length); 358 } 359 if(!privIsRef) { 360 writeFile("privKey.blob", privKey.KeyData.Data, privKey.KeyData.Length); 361 printf("...wrote %lu bytes to privKey.blob\n", privKey.KeyData.Length); 362 } 363 } 364 randData.Data = (uint8 *)CSSM_MALLOC(dataSize); 365 randData.Length = dataSize; 366 simpleGenData(&randData, dataSize, dataSize); 367 printf("\n"); 368 for(loop=1; ; loop++) { 369 if(!quiet) { 370 printf("...Loop %d\n", loop); 371 } 372 if((loop == 1) || doSign) { 373 crtn = CSSM_CSP_CreateSignatureContext(cspHand, 374 sigAlg, 375 NULL, // passPhrase 376 &privKey, 377 &privSigHand); 378 if(crtn) { 379 printError("CSSM_CSP_CreateSignatureContext (1)", crtn); 380 break; 381 } 382 if(noPadding) { 383 crtn = AddContextAttribute(privSigHand, 384 CSSM_ATTRIBUTE_PADDING, 385 sizeof(uint32), 386 CAT_Uint32, 387 NULL, 388 CSSM_PADDING_NONE); 389 if(crtn) { 390 break; 391 } 392 } 393 if(!contextsOnly) { 394 crtn = CSSM_SignData(privSigHand, 395 &randData, 396 1, 397 CSSM_ALGID_NONE, 398 &sigData); 399 if(crtn) { 400 printError("CSSM_SignData error", crtn); 401 break; 402 } 403 } 404 crtn = CSSM_DeleteContext(privSigHand); 405 if(crtn) { 406 printError("CSSM_DeleteContext", crtn); 407 break; 408 } 409 if(dumpBlobs) { 410 writeFile("sig.blob", sigData.Data, sigData.Length); 411 printf("...wrote %lu bytes to sig.blob\n", sigData.Length); 412 } 413 } 414 if(doVerify) { 415 crtn = CSSM_CSP_CreateSignatureContext(cspHand, 416 sigAlg, 417 NULL, // passPhrase 418 &pubKey, 419 &pubSigHand); 420 if(crtn) { 421 printError("CSSM_CSP_CreateSignatureContext (2)", crtn); 422 break; 423 } 424 if(noPadding) { 425 crtn = AddContextAttribute(pubSigHand, 426 CSSM_ATTRIBUTE_PADDING, 427 sizeof(uint32), 428 CAT_Uint32, 429 NULL, 430 CSSM_PADDING_NONE); 431 if(crtn) { 432 break; 433 } 434 } 435 if(!contextsOnly) { 436 crtn = CSSM_VerifyData(pubSigHand, 437 &randData, 438 1, 439 CSSM_ALGID_NONE, 440 &sigData); 441 if(crtn) { 442 printError("CSSM_VerifyData", crtn); 443 break; 444 } 445 } 446 crtn = CSSM_DeleteContext(pubSigHand); 447 if(crtn) { 448 printError("CSSM_DeleteContext", crtn); 449 break; 450 } 451 } 452 if(doSign & !contextsOnly) { 453 CSSM_FREE(sigData.Data); 454 sigData.Length = 0; 455 sigData.Data = NULL; 456 } 457 /* else keep it around for next verify */ 458 459 if(loops && (loop == loops)) { 460 break; 461 } 462 if(pauseInterval && ((loop % pauseInterval) == 0)) { 463 char inch; 464 465 fpurge(stdin); 466 printf("Hit CR to proceed, q to quit: "); 467 inch = getchar(); 468 if(inch == 'q') { 469 break; 470 } 471 } 472 } 473 if(randData.Data != NULL) { 474 CSSM_FREE(randData.Data); 475 } 476 if(CSSM_ModuleDetach(cspHand)) { 477 printError("CSSM_CSP_Detach", crtn); 478 exit(1); 479 } 480 if(crtn == CSSM_OK) { 481 if(!quiet) { 482 printf("OK\n"); 483 } 484 } 485 return crtn; 486} 487