1/* 2 * keyHashAsym.c - CSSM_APPLECSP_KEYDIGEST passthrough test for all 3 * known asymmetric algorithms and key formats 4 */ 5 6#include <stdlib.h> 7#include <stdio.h> 8#include <time.h> 9#include <string.h> 10#include <Security/cssm.h> 11#include "cspwrap.h" 12#include "common.h" 13#include "cspdlTesting.h" 14#include <security_cdsa_utils/cuFileIo.h> 15 16#define USAGE_NAME "noUsage" 17#define USAGE_NAME_LEN (strlen(USAGE_NAME)) 18#define LOOPS_DEF 10 19 20#define DSA_PARAM_FILE "dsaParams_512.der" 21#define DH_PARAM_FILE "dhParams_512.der" 22 23static void usage(char **argv) 24{ 25 printf("usage: %s [options]\n", argv[0]); 26 printf("Options:\n"); 27 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); 28 printf(" D (CSP/DL; default = bare CSP)\n"); 29 printf(" p(ause on each loop)\n"); 30 printf(" q(uiet)\n"); 31 printf(" v(erbose))\n"); 32 exit(1); 33} 34 35static CSSM_DATA dsa512Params; 36static CSSM_DATA dh512Params; 37 38/* 39 * Describe parameters for one test iteration. 40 */ 41typedef struct { 42 CSSM_ALGORITHMS keyAlg; 43 CSSM_KEYBLOB_FORMAT pubKeyForm; 44 CSSM_KEYBLOB_FORMAT privKeyForm; 45 uint32 keySizeInBits; 46 CSSM_DATA *algParams; // optional 47} KeyHashTest; 48 49KeyHashTest KeyHashTestParams[] = 50{ 51 /* RSA */ 52 { CSSM_ALGID_RSA, 53 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, 54 512, NULL 55 }, 56 { CSSM_ALGID_RSA, 57 CSSM_KEYBLOB_RAW_FORMAT_PKCS1, CSSM_KEYBLOB_RAW_FORMAT_NONE, 58 512, NULL 59 }, 60 { CSSM_ALGID_RSA, 61 CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_NONE, 62 512, NULL 63 }, 64 { CSSM_ALGID_RSA, 65 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS1, 66 512, NULL 67 }, 68 { CSSM_ALGID_RSA, 69 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, 70 512, NULL 71 }, 72 73 /* ECDSA */ 74 { CSSM_ALGID_ECDSA, 75 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, 76 192, NULL 77 }, 78 { CSSM_ALGID_ECDSA, 79 CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, 80 256, NULL 81 }, 82 { CSSM_ALGID_ECDSA, 83 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, 84 384, NULL 85 }, 86 { CSSM_ALGID_ECDSA, 87 CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, 88 521, NULL 89 }, 90 91 /* DSA */ 92 { CSSM_ALGID_DSA, 93 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, 94 512, &dsa512Params 95 }, 96 { CSSM_ALGID_DSA, 97 CSSM_KEYBLOB_RAW_FORMAT_FIPS186, CSSM_KEYBLOB_RAW_FORMAT_NONE, 98 512, &dsa512Params 99 }, 100 { CSSM_ALGID_DSA, 101 CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_NONE, 102 512, &dsa512Params 103 }, 104 { CSSM_ALGID_DSA, 105 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_FIPS186, 106 512, &dsa512Params 107 }, 108 { CSSM_ALGID_DSA, 109 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_OPENSSL, 110 512, &dsa512Params 111 }, 112 { CSSM_ALGID_DSA, 113 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, 114 512, &dsa512Params 115 }, 116 { CSSM_ALGID_DSA, 117 CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, 118 512, &dsa512Params 119 }, 120 121 /* Diffie-Hellman */ 122 { CSSM_ALGID_DH, 123 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, 124 512, &dh512Params 125 }, 126 { CSSM_ALGID_DH, 127 CSSM_KEYBLOB_RAW_FORMAT_PKCS3, CSSM_KEYBLOB_RAW_FORMAT_NONE, 128 512, &dh512Params 129 }, 130 { CSSM_ALGID_DH, 131 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS3, 132 512, &dh512Params 133 }, 134 { CSSM_ALGID_DH, 135 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, 136 512, &dh512Params 137 }, 138 { CSSM_ALGID_DH, 139 CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_NONE, 140 512, &dh512Params 141 }, 142 { CSSM_ALGID_DH, 143 CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, 144 512, &dh512Params 145 }, 146 147 /* FEE */ 148 { CSSM_ALGID_FEE, 149 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, 150 127, NULL 151 }, 152 { CSSM_ALGID_FEE, 153 CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, CSSM_KEYBLOB_RAW_FORMAT_NONE, 154 128, NULL 155 }, 156 { CSSM_ALGID_FEE, 157 CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, 158 161, NULL 159 }, 160 { CSSM_ALGID_FEE, 161 CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, 162 CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, 163 192, NULL 164 }, 165 166}; 167#define NUM_TEST_PARAMS\ 168 (sizeof(KeyHashTestParams) / sizeof(KeyHashTestParams[0])) 169 170static void dumpBuf(uint8 *buf, 171 unsigned len) 172{ 173 unsigned i; 174 175 printf(" "); 176 for(i=0; i<len; i++) { 177 printf("%02X ", buf[i]); 178 if((i % 24) == 23) { 179 printf("\n "); 180 } 181 } 182 printf("\n"); 183} 184 185const char *formStr(CSSM_KEYBLOB_FORMAT form) 186{ 187 switch(form) { 188 case CSSM_KEYBLOB_RAW_FORMAT_NONE: return "NONE"; 189 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: return "PKCS1"; 190 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: return "PKCS3"; 191 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: return "FIPS186"; 192 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: return "PKCS8"; 193 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: return "OCTET_STRING"; 194 case CSSM_KEYBLOB_RAW_FORMAT_OTHER: return "OTHER"; 195 case CSSM_KEYBLOB_RAW_FORMAT_X509: return "X509"; 196 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: return "OPENSSH"; 197 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: return "OPENSSL"; 198 default: 199 printf("**BRRZAP! formStr needs work\n"); 200 exit(1); 201 } 202} 203 204const char *algStr(CSSM_ALGORITHMS alg) 205{ 206 switch(alg) { 207 case CSSM_ALGID_RSA: return "RSA"; 208 case CSSM_ALGID_DSA: return "DSA"; 209 case CSSM_ALGID_DH: return "DH"; 210 case CSSM_ALGID_FEE: return "FEE"; 211 case CSSM_ALGID_ECDSA: return "ECDSA"; 212 default: 213 printf("**BRRZAP! algStr needs work\n"); 214 exit(1); 215 } 216} 217 218static void showTestParams(KeyHashTest *testParam) 219{ 220 printf("alg %s pubForm %s privForm %s\n", 221 algStr(testParam->keyAlg), 222 formStr(testParam->pubKeyForm), 223 formStr(testParam->privKeyForm)); 224 225} 226 227/* 228 * Generate key pair of specified alg and raw format. 229 * Alg params are optional, though they are expected to be here 230 * for DH and DSA. 231 */ 232static CSSM_RETURN genKeyPair( 233 CSSM_CSP_HANDLE cspHand, 234 CSSM_ALGORITHMS keyAlg, 235 uint32 keySize, // in bits 236 CSSM_KEY_PTR pubKey, 237 CSSM_KEYBLOB_FORMAT pubFormat, 238 CSSM_KEY_PTR privKey, 239 CSSM_KEYBLOB_FORMAT privFormat, 240 const CSSM_DATA *inParams) // optional 241{ 242 CSSM_RETURN crtn; 243 CSSM_CC_HANDLE ccHand; 244 CSSM_DATA keyLabelData; 245 CSSM_RETURN ocrtn = CSSM_OK; 246 247 keyLabelData.Data = (uint8 *)USAGE_NAME, 248 keyLabelData.Length = USAGE_NAME_LEN; 249 memset(pubKey, 0, sizeof(CSSM_KEY)); 250 memset(privKey, 0, sizeof(CSSM_KEY)); 251 252 crtn = CSSM_CSP_CreateKeyGenContext(cspHand, 253 keyAlg, 254 keySize, 255 NULL, // Seed 256 NULL, // Salt 257 NULL, // StartDate 258 NULL, // EndDate 259 inParams, // Params, may be NULL 260 &ccHand); 261 if(crtn) { 262 printError("CSSM_CSP_CreateKeyGenContext", crtn); 263 return crtn; 264 } 265 266 /* optional format specifiers */ 267 if(pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { 268 crtn = AddContextAttribute(ccHand, 269 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, 270 sizeof(uint32), 271 CAT_Uint32, 272 NULL, 273 pubFormat); 274 if(crtn) { 275 printError("AddContextAttribute(" 276 "CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); 277 return crtn; 278 } 279 } 280 if(privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { 281 crtn = AddContextAttribute(ccHand, 282 CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, 283 sizeof(uint32), 284 CAT_Uint32, 285 NULL, 286 privFormat); 287 if(crtn) { 288 printError("AddContextAttribute(" 289 "CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn); 290 return crtn; 291 } 292 } 293 CSSM_KEYATTR_FLAGS attrFlags = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; 294 crtn = CSSM_GenerateKeyPair(ccHand, 295 CSSM_KEYUSE_DERIVE, 296 attrFlags, 297 &keyLabelData, 298 pubKey, 299 CSSM_KEYUSE_DERIVE, 300 attrFlags, 301 &keyLabelData, // same labels 302 NULL, // CredAndAclEntry 303 privKey); 304 if(crtn) { 305 printError("CSSM_GenerateKeyPair", crtn); 306 ocrtn = crtn; 307 } 308 if(ccHand != 0) { 309 crtn = CSSM_DeleteContext(ccHand); 310 if(crtn) { 311 printError("CSSM_DeleteContext", crtn); 312 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 313 } 314 } 315 return ocrtn; 316} 317 318/* 319 * Given two keys (presumably, in this test, one a raw key and 320 * one an equivalent ref key), calculate the key digest of both of them 321 * and ensure they're the same. 322 */ 323static int compareKeyHashes( 324 const CSSM_DATA *key1Hash, 325 const char *key1Descr, 326 const CSSM_DATA *key2Hash, 327 const char *key2Descr, 328 CSSM_BOOL verbose) 329{ 330 if(appCompareCssmData(key1Hash, key2Hash)) { 331 return 0; 332 } 333 printf("***Key Digest miscompare (%s,%s)***\n", key1Descr, key2Descr); 334 if(!verbose) { 335 printf("...%s hash:\n", key1Descr); 336 dumpBuf(key1Hash->Data, key1Hash->Length); 337 printf("...%s hash:\n", key2Descr); 338 dumpBuf(key2Hash->Data, key2Hash->Length); 339 } 340 return 1; 341} 342 343/* 344 * Given a KeyHashTest: 345 * -- cook up key pair, raw, specified formats 346 * -- NULL unwrap each raw to ref; 347 * -- obtain four key digests; 348 * -- ensure all digests match; 349 */ 350static int doTest( 351 CSSM_CSP_HANDLE rawCspHand, // generate keys here 352 CSSM_CSP_HANDLE refCspHand, // null unwrap here 353 KeyHashTest *testParam, 354 CSSM_BOOL verbose, 355 CSSM_BOOL quiet) 356{ 357 CSSM_RETURN crtn; 358 CSSM_KEY pubKey; 359 CSSM_KEY privKey; 360 CSSM_KEY pubKeyRef; 361 CSSM_KEY privKeyRef; 362 CSSM_DATA_PTR rawPubHash; 363 CSSM_DATA_PTR rawPrivHash; 364 CSSM_DATA_PTR refPubHash; 365 CSSM_DATA_PTR refPrivHash; 366 int rtn = 0; 367 368 /* generate key pair, specified raw form */ 369 crtn = genKeyPair(rawCspHand, 370 testParam->keyAlg, 371 testParam->keySizeInBits, 372 &pubKey, 373 testParam->pubKeyForm, 374 &privKey, 375 testParam->privKeyForm, 376 testParam->algParams); 377 if(crtn) { 378 return testError(quiet); 379 } 380 381 /* null unwrap both raw keys to ref form */ 382 crtn = cspRawKeyToRef(refCspHand, &pubKey, &pubKeyRef); 383 if(crtn) { 384 return testError(quiet); 385 } 386 crtn = cspRawKeyToRef(refCspHand, &privKey, &privKeyRef); 387 if(crtn) { 388 return testError(quiet); 389 } 390 391 /* calculate four key digests */ 392 crtn = cspKeyHash(rawCspHand, &pubKey, &rawPubHash); 393 if(crtn) { 394 return testError(quiet); 395 } 396 crtn = cspKeyHash(rawCspHand, &privKey, &rawPrivHash); 397 if(crtn) { 398 return testError(quiet); 399 } 400 crtn = cspKeyHash(refCspHand, &pubKeyRef, &refPubHash); 401 if(crtn) { 402 return testError(quiet); 403 } 404 crtn = cspKeyHash(refCspHand, &privKeyRef, &refPrivHash); 405 if(crtn) { 406 return testError(quiet); 407 } 408 409 if(verbose) { 410 printf("...raw pub key hash:\n"); 411 dumpBuf(rawPubHash->Data, rawPubHash->Length); 412 printf("...ref pub key hash:\n"); 413 dumpBuf(refPubHash->Data, refPubHash->Length); 414 printf("...raw priv key hash:\n"); 415 dumpBuf(rawPrivHash->Data, rawPrivHash->Length); 416 printf("...ref priv key hash:\n"); 417 dumpBuf(refPrivHash->Data, refPrivHash->Length); 418 } 419 420 /* compare */ 421 rtn += compareKeyHashes(rawPubHash, "Raw public", 422 refPubHash, "Ref public", verbose); 423 rtn += compareKeyHashes(rawPrivHash, "Raw private", 424 refPrivHash, "Ref private", verbose); 425 rtn += compareKeyHashes(refPubHash, "Ref public", 426 refPrivHash, "Ref private", verbose); 427 if(rtn) { 428 rtn = testError(quiet); 429 } 430 cspFreeKey(rawCspHand, &pubKey); 431 cspFreeKey(rawCspHand, &privKey); 432 cspFreeKey(refCspHand, &pubKeyRef); 433 cspFreeKey(refCspHand, &privKeyRef); 434 appFreeCssmData(rawPubHash, CSSM_TRUE); 435 appFreeCssmData(rawPrivHash, CSSM_TRUE); 436 appFreeCssmData(refPubHash, CSSM_TRUE); 437 appFreeCssmData(refPrivHash, CSSM_TRUE); 438 return rtn; 439} 440 441int main(int argc, char **argv) 442{ 443 int arg; 444 char *argp; 445 unsigned loop; 446 CSSM_CSP_HANDLE rawCspHand; // always Raw CSP 447 CSSM_CSP_HANDLE refCspHand; // CSPDL if !bareCsp 448 int rtn = 0; 449 int i; 450 unsigned len; 451 452 /* 453 * User-spec'd params 454 */ 455 unsigned loops = LOOPS_DEF; 456 CSSM_BOOL verbose = CSSM_FALSE; 457 CSSM_BOOL quiet = CSSM_FALSE; 458 CSSM_BOOL bareCsp = CSSM_TRUE; 459 CSSM_BOOL doPause = CSSM_FALSE; 460 461 for(arg=1; arg<argc; arg++) { 462 argp = argv[arg]; 463 switch(argp[0]) { 464 case 'l': 465 loops = atoi(&argp[2]); 466 break; 467 case 'D': 468 bareCsp = CSSM_FALSE; 469 break; 470 case 'p': 471 doPause = CSSM_TRUE; 472 break; 473 case 'v': 474 verbose = CSSM_TRUE; 475 break; 476 case 'q': 477 quiet = CSSM_TRUE; 478 break; 479 case 'h': 480 default: 481 usage(argv); 482 } 483 } 484 485 /* prefetch the alg params */ 486 rtn = readFile(DSA_PARAM_FILE, &dsa512Params.Data, &len); 487 if(rtn) { 488 printf("***%s file missing. Aborting.\n", DSA_PARAM_FILE); 489 exit(1); 490 } 491 dsa512Params.Length = len; 492 rtn = readFile(DH_PARAM_FILE, &dh512Params.Data, &len); 493 if(rtn) { 494 printf("***%s file missing. Aborting.\n", DH_PARAM_FILE); 495 exit(1); 496 } 497 dh512Params.Length = len; 498 499 printf("Starting keyHashAsym; args: "); 500 for(i=1; i<argc; i++) { 501 printf("%s ", argv[i]); 502 } 503 printf("\n"); 504 refCspHand = cspDlDbStartup(bareCsp, NULL); 505 if(refCspHand == 0) { 506 exit(1); 507 } 508 if(bareCsp) { 509 /* raw and ref on same CSP */ 510 rawCspHand = refCspHand; 511 } 512 else { 513 /* generate on CSPDL, NULL unwrap to bare CSP */ 514 rawCspHand = cspDlDbStartup(CSSM_TRUE, NULL); 515 if(rawCspHand == 0) { 516 exit(1); 517 } 518 } 519 for(loop=1; ; loop++) { 520 if(!quiet) { 521 printf("...loop %d\n", loop); 522 } 523 for(unsigned testNum=0; testNum<NUM_TEST_PARAMS; testNum++) { 524 KeyHashTest *testParams = &KeyHashTestParams[testNum]; 525 if(!quiet) { 526 printf("..."); showTestParams(testParams); 527 } 528 rtn = doTest(rawCspHand, refCspHand, testParams, verbose, quiet); 529 if(rtn) { 530 goto done; 531 } 532 if(doPause) { 533 fpurge(stdin); 534 printf("Hit CR to proceed: "); 535 getchar(); 536 } 537 } 538 if(loops && (loop == loops)) { 539 break; 540 } 541 } 542done: 543 if((rtn == 0) && !quiet) { 544 printf("...%s complete\n", argv[0]); 545 } 546 return rtn; 547} 548