feePublicKey.c
1 /* Copyright (c) 1998,2011-2012,2014 Apple Inc. All Rights Reserved. 2 * 3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT 4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE 5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE 6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, 7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL 8 * EXPOSE YOU TO LIABILITY. 9 *************************************************************************** 10 * 11 * feePublicKey.c - Portable FEE public key object. 12 * 13 * Revision History 14 * ---------------- 15 * 11/27/98 dmitch 16 * Added ECDSA_VERIFY_ONLY dependencies. 17 * 10/06/98 ap 18 * Changed to compile with C++. 19 * 9 Sep 98 at NeXT 20 * Major changes for IEEE P1363 compliance. 21 * 23 Mar 98 at Apple 22 * Added blob support. 23 * 21 Jan 98 at Apple 24 * Fixed feePubKeyBitsize bitlen bug for PT_GENERAL case. 25 * 05 Jan 98 at Apple 26 * ECDSA now uses SHA-1 hash. Imcompatible with old ECDSA signatures. 27 * 17 Jul 97 at Apple 28 * Added ECDSA signature routines. 29 * 12 Jun 97 at Apple 30 * Added feePubKeyInitGiants() 31 * Deleted obsolete code 32 * Changes for lesserX1OrderJustify (was curveOrderJustify) 33 * 31 Mar 97 at Apple 34 * Fixed leak in feePubKeyCreateKeyString() 35 * 15 Jan 97 at NeXT 36 * PUBLIC_KEY_STRING_VERSION = 3; broke compatibility with all older 37 * versions. 38 * Cleaned up which_curve/index code to use CURVE_MINUS/CURVE_PLUS. 39 * 12 Dec 96 at NeXT 40 * Added initFromEnc64KeyStr(). 41 * 20 Aug 96 at NeXT 42 * Ported to C. 43 * ???? 1994 Blaine Garst at NeXT 44 * Created. 45 */ 46 47 #include "ckconfig.h" 48 #include "feePublicKey.h" 49 #include "feePublicKeyPrivate.h" 50 #include "ckutilities.h" 51 #include "giantIntegers.h" 52 #include "elliptic.h" 53 #include "curveParams.h" 54 #include "falloc.h" 55 #include "feeTypes.h" 56 #include "feeDebug.h" 57 #include "feeHash.h" 58 #include "ckSHA1.h" 59 #include "feeDigitalSignature.h" 60 #include "feeECDSA.h" 61 #include "platform.h" 62 #include "enc64.h" 63 #include "byteRep.h" 64 #include "CryptKitDER.h" 65 #include <stdio.h> 66 67 /* 68 * 11/27/98 dmitch: The ECDSA_VERIFY_ONLY symbol, when #defined, disables all 69 * of the code in this module except that which is necessary for ECDSA 70 * siggnature verification. 71 */ 72 73 #ifndef NULL 74 #define NULL ((void *)0) 75 #endif // NULL 76 77 /* 78 * Magic number for a portable key blobs. Must be in sync with static 79 * final PUBLIC_KEY_STRING_MAGIC in JavaFee/PublicKey.java. 80 */ 81 #define PUBLIC_KEY_BLOB_MAGIC_PUB 0xfeeddeef 82 #define PUBLIC_KEY_BLOB_MAGIC_PRIV 0xfeeddeed 83 #define PUBLIC_KEY_BLOB_VERSION 6 84 #define PUBLIC_KEY_BLOB_MINVERSION 6 85 86 #define PUBLIC_DER_KEY_BLOB_VERSION 1 87 88 /* 89 * Private data. All "instance" routines are passed a feePubKey (actually 90 * a void *) which is actually a pointer to one of these. 91 */ 92 typedef struct { 93 key plus; 94 key minus; // not needed for ECDSA 95 curveParams *cp; // common params shared by minus, plus 96 giant privGiant; // private key 97 } pubKeyInst; 98 99 static feeReturn feeGenPrivate(pubKeyInst *pkinst, 100 const unsigned char *passwd, 101 unsigned passwdLen, 102 char hashPasswd); 103 static pubKeyInst *pubKeyInstAlloc(void); 104 static void pubKeyInstFree(pubKeyInst *pkinst); 105 106 static feeReturn createKeyBlob(pubKeyInst *pkinst, 107 int isPrivate, // 0 : public 1 : private 108 unsigned char **keyBlob, // mallocd and RETURNED 109 unsigned *keyBlobLen); // RETURNED 110 static feeReturn feePubKeyInitFromKeyBlob(feePubKey pubKey, 111 unsigned char *keyBlob, 112 unsigned keyBlobLen); 113 114 #pragma mark --- General public API function --- 115 116 /* 117 * Obatin a newly allocated feePubKey. 118 */ 119 feePubKey feePubKeyAlloc(void) 120 { 121 pubKeyInst *pkinst = pubKeyInstAlloc(); 122 123 124 return pkinst; 125 } 126 127 void feePubKeyFree(feePubKey pubKey) 128 { 129 pubKeyInstFree((pubKeyInst*) pubKey); 130 } 131 132 #ifndef ECDSA_VERIFY_ONLY 133 /* 134 * Init feePubKey from private key data. 135 */ 136 feeReturn feePubKeyInitFromPrivDataKeyBits(feePubKey pubKey, 137 const unsigned char *privData, 138 unsigned privDataLen, 139 unsigned keyBits, /* key size in bits */ 140 feePrimeType primeType, /* FPT_Fefault means "best one" */ 141 feeCurveType curveType, /* FCT_Default means "best one" */ 142 char hashPrivData) 143 { 144 feeReturn frtn; 145 feeDepth depth; 146 147 frtn = feeKeyBitsToDepth(keyBits, primeType, curveType, &depth); 148 if(frtn) { 149 return frtn; 150 } 151 return feePubKeyInitFromPrivDataDepth(pubKey, 152 privData, 153 privDataLen, 154 depth, 155 hashPrivData); 156 } 157 158 feeReturn feePubKeyInitFromPrivDataDepth(feePubKey pubKey, 159 const unsigned char *privData, 160 unsigned privDataLen, 161 feeDepth depth, 162 char hashPrivData) 163 { 164 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 165 feeReturn frtn; 166 167 if(depth > FEE_DEPTH_MAX) { 168 dbgLog(("Illegal Depth\n")); 169 return FR_IllegalDepth; 170 } 171 172 pkinst->cp = curveParamsForDepth(depth); 173 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 174 if(pkinst->cp->x1Minus != NULL) { 175 pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); 176 } 177 /* else only usable for ECDSA */ 178 179 frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData); 180 if(frtn) { 181 return frtn; 182 } 183 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 184 if(pkinst->cp->x1Minus != NULL) { 185 set_priv_key_giant(pkinst->minus, pkinst->privGiant); 186 } 187 return FR_Success; 188 } 189 190 #endif /* ECDSA_VERIFY_ONLY */ 191 192 /* 193 * Init feePubKey from curve parameters matching existing oldKey. 194 */ 195 feeReturn feePubKeyInitFromKey(feePubKey pubKey, 196 const unsigned char *privData, 197 unsigned privDataLen, 198 feePubKey oldKey, 199 char hashPrivData) 200 { 201 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 202 pubKeyInst *oldInst = (pubKeyInst *) oldKey; 203 feeReturn frtn; 204 205 if(oldKey == NULL) { 206 dbgLog(("NULL existing key\n")); 207 return FR_BadPubKey; 208 } 209 210 pkinst->cp = curveParamsCopy(oldInst->cp); 211 if(pkinst->cp->x1Minus != NULL) { 212 pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); 213 if(pkinst->minus == NULL) { 214 goto abort; 215 } 216 } 217 /* else this curve only usable for ECDSA */ 218 219 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 220 if(pkinst->plus == NULL) { 221 goto abort; 222 } 223 frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData); 224 if(frtn) { 225 return frtn; 226 } 227 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 228 if(pkinst->cp->x1Minus != NULL) { 229 set_priv_key_giant(pkinst->minus, pkinst->privGiant); 230 } 231 return FR_Success; 232 233 abort: 234 dbgLog(("Bad Existing Public Key\n")); 235 return FR_BadPubKey; 236 } 237 238 /*** 239 *** Public KeyString support. 240 ***/ 241 /* 242 * Init feePubKey from a public key string. 243 * 244 * See ByteRep.doc for info on the format of the public key string and blobs; 245 * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT. 246 */ 247 feeReturn feePubKeyInitFromKeyString(feePubKey pubKey, 248 const char *keyStr, 249 unsigned keyStrLen) 250 { 251 unsigned char *blob = NULL; 252 unsigned blobLen; 253 feeReturn frtn; 254 255 blob = dec64((unsigned char *)keyStr, keyStrLen, &blobLen); 256 if(blob == NULL) { 257 dbgLog(("Bad Public Key String (not enc64)\n")); 258 return FR_BadPubKeyString; 259 } 260 frtn = feePubKeyInitFromKeyBlob(pubKey, blob, blobLen); 261 ffree(blob); 262 return frtn; 263 } 264 265 /* 266 * Create a public key in the form of a null-terminated C string. 267 * This string contains an encoded version of all of our ivars except for 268 * privGiant. 269 * 270 * See ByteRep.doc for info on the format of the public key string and blobs; 271 * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT. 272 */ 273 feeReturn feePubKeyCreateKeyString(feePubKey pubKey, 274 char **pubKeyString, /* RETURNED */ 275 unsigned *pubKeyStringLen) /* RETURNED */ 276 { 277 unsigned char *blob; 278 unsigned blobLen; 279 feeReturn frtn; 280 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 281 282 /* get binary pub blob, encode the blob, free the blob */ 283 frtn = createKeyBlob(pkinst, 284 0, // isPrivate 285 &blob, 286 &blobLen); 287 if(frtn) { 288 return frtn; 289 } 290 291 *pubKeyString = (char *)enc64(blob, blobLen, pubKeyStringLen); 292 ffree(blob); 293 return FR_Success; 294 } 295 296 /*** 297 *** Native key blob support. 298 ***/ 299 300 #ifndef ECDSA_VERIFY_ONLY 301 302 /* 303 * Obtain portable public and private key blobs from a key. 304 */ 305 feeReturn feePubKeyCreatePubBlob(feePubKey pubKey, 306 unsigned char **keyBlob, // mallocd and RETURNED 307 unsigned *keyBlobLen) // RETURNED 308 { 309 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 310 311 return createKeyBlob(pkinst, 312 0, 313 keyBlob, 314 keyBlobLen); 315 } 316 317 feeReturn feePubKeyCreatePrivBlob(feePubKey pubKey, 318 unsigned char **keyBlob, // mallocd and RETURNED 319 unsigned *keyBlobLen) // RETURNED 320 { 321 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 322 323 if(pkinst->privGiant == NULL) { 324 return FR_IncompatibleKey; 325 } 326 return createKeyBlob(pkinst, 327 1, 328 keyBlob, 329 keyBlobLen); 330 } 331 332 /* 333 * Given private-capable privKey, initialize pubKey to be its corresponding 334 * public key. 335 */ 336 feeReturn feePubKeyInitPubKeyFromPriv(feePubKey privKey, 337 feePubKey pubKey) 338 { 339 pubKeyInst *privInst = (pubKeyInst *)privKey; 340 pubKeyInst *pubInst = (pubKeyInst *)pubKey; 341 342 if((privInst == NULL) || (pubInst == NULL)) { 343 return FR_BadPubKey; 344 } 345 if(privInst->privGiant == NULL) { 346 return FR_IncompatibleKey; 347 } 348 pubInst->cp = curveParamsCopy(privInst->cp); 349 if(pubInst == NULL) { 350 return FR_Memory; 351 } 352 pubInst->plus = new_public_with_key(privInst->plus, pubInst->cp); 353 if(pubInst->plus == NULL) { 354 return FR_Memory; 355 } 356 if(pubInst->cp->x1Minus != NULL) { 357 pubInst->minus = new_public_with_key(privInst->minus, pubInst->cp); 358 if(pubInst->minus == NULL) { 359 return FR_Memory; 360 } 361 } 362 return FR_Success; 363 } 364 365 #endif /* ECDSA_VERIFY_ONLY */ 366 367 /* 368 * Returns non-zero if two keys are equivalent. 369 */ 370 int feePubKeyIsEqual(feePubKey key1, feePubKey key2) 371 { 372 pubKeyInst *pkinst1 = (pubKeyInst *) key1; 373 pubKeyInst *pkinst2 = (pubKeyInst *) key2; 374 375 if ((pkinst1 == NULL) || (pkinst2 == NULL)) { 376 return 0; 377 } 378 if((pkinst1->minus != NULL) && (pkinst2->minus != NULL)) { 379 if(key_equal(pkinst1->minus, pkinst2->minus) == 0) { 380 return 0; 381 } 382 } 383 if(key_equal(pkinst1->plus, pkinst2->plus) == 0) { 384 return 0; 385 } 386 return 1; 387 } 388 389 /* 390 * Returns non-zero if key is private-capable (i.e., capable of signing 391 * and decrypting). 392 */ 393 int feePubKeyIsPrivate(feePubKey key) 394 { 395 pubKeyInst *myPkinst = (pubKeyInst *)key; 396 397 return ((myPkinst->privGiant != NULL) ? 1 : 0); 398 } 399 400 #pragma mark --- ECDH --- 401 402 /* 403 * Diffie-Hellman. Public key is specified either as a feePubKey or 404 * a ANSI X9.62 format public key string (0x04 | x | y). In either case 405 * the caller must ensure that the two keys are on the same curve. 406 * Output data is fmalloc'd here; caller must free. Output data is 407 * exactly the size of the curve's modulus in bytes. 408 */ 409 feeReturn feePubKeyECDH( 410 feePubKey privKey, 411 /* one of the following two is non-NULL */ 412 feePubKey pubKey, 413 const unsigned char *pubKeyStr, 414 unsigned pubKeyStrLen, 415 /* output fmallocd and RETURNED here */ 416 unsigned char **output, 417 unsigned *outputLen) 418 { 419 feePubKey theirPub = pubKey; 420 feeReturn frtn = FR_Success; 421 pubKeyInst *privInst = (pubKeyInst *) privKey; 422 423 if(privInst->privGiant == NULL) { 424 dbgLog(("feePubKeyECDH: privKey not a private key\n")); 425 return FR_IncompatibleKey; 426 } 427 428 if(theirPub == NULL) { 429 if(pubKeyStr == NULL) { 430 return FR_IllegalArg; 431 } 432 433 /* Cook up a public key with the same curveParams as the private key */ 434 feeDepth depth; 435 frtn = curveParamsDepth(privInst->cp, &depth); 436 if(frtn) { 437 return frtn; 438 } 439 theirPub = feePubKeyAlloc(); 440 if(theirPub == NULL) { 441 return FR_Memory; 442 } 443 frtn = feePubKeyInitFromECDSAPubBlob(theirPub, pubKeyStr, pubKeyStrLen, depth); 444 if(frtn) { 445 goto errOut; 446 } 447 } 448 449 pubKeyInst *pubInst = (pubKeyInst *) theirPub; 450 451 giant outputGiant = make_pad(privInst->privGiant, pubInst->plus); 452 if(outputGiant == NULL) { 453 dbgLog(("feePubKeyECDH: make_pad error\n")); 454 frtn = FR_Internal; 455 } 456 else { 457 *outputLen = (privInst->cp->q + 7) / 8; 458 *output = (unsigned char *)fmalloc(*outputLen); 459 if(*output == NULL) { 460 frtn = FR_Memory; 461 goto errOut; 462 } 463 serializeGiant(outputGiant, *output, *outputLen); 464 freeGiant(outputGiant); 465 } 466 errOut: 467 if((pubKey == NULL) && (theirPub != NULL)) { 468 feePubKeyFree(theirPub); 469 } 470 return frtn; 471 } 472 473 #pragma mark --- feePubKey data accessors --- 474 475 unsigned feePubKeyBitsize(feePubKey pubKey) 476 { 477 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 478 switch(pkinst->cp->primeType) { 479 case FPT_General: /* cp->q is here for just this purpose */ 480 case FPT_Mersenne: 481 return pkinst->cp->q; 482 case FPT_FEE: /* could be larger or smaller than 2^q-1 */ 483 default: 484 return bitlen(pkinst->cp->basePrime); 485 } 486 } 487 488 /* 489 * Accessor routines. 490 */ 491 /* private only...*/ 492 key feePubKeyPlusCurve(feePubKey pubKey) 493 { 494 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 495 496 return pkinst->plus; 497 } 498 499 key feePubKeyMinusCurve(feePubKey pubKey) 500 { 501 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 502 503 return pkinst->minus; 504 } 505 506 curveParams *feePubKeyCurveParams(feePubKey pubKey) 507 { 508 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 509 510 return pkinst->cp; 511 } 512 513 giant feePubKeyPrivData(feePubKey pubKey) 514 { 515 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 516 517 return pkinst->privGiant; 518 } 519 520 const char *feePubKeyAlgorithmName(void) 521 { 522 return "Elliptic Curve - FEE by Apple Computer"; 523 } 524 525 #pragma mark --- Private functions --- 526 527 /* 528 * alloc, free pubKeyInst 529 */ 530 static pubKeyInst *pubKeyInstAlloc(void) 531 { 532 pubKeyInst *pkinst = (pubKeyInst *) fmalloc(sizeof(pubKeyInst)); 533 534 bzero(pkinst, sizeof(pubKeyInst)); 535 return pkinst; 536 } 537 538 static void pubKeyInstFree(pubKeyInst *pkinst) 539 { 540 if(pkinst->minus) { 541 free_key(pkinst->minus); 542 } 543 if(pkinst->plus) { 544 free_key(pkinst->plus); 545 } 546 if(pkinst->cp) { 547 freeCurveParams(pkinst->cp); 548 } 549 if(pkinst->privGiant) { 550 /* 551 * Zero out the private data... 552 */ 553 clearGiant(pkinst->privGiant); 554 freeGiant(pkinst->privGiant); 555 } 556 ffree(pkinst); 557 } 558 559 #ifndef ECDSA_VERIFY_ONLY 560 561 /* 562 * Create a pubKeyInst.privGiant given a password of 563 * arbitrary length. 564 * Currently, the only error is "private data too short" (FR_IllegalArg). 565 */ 566 567 #define NO_PRIV_MUNGE 0 /* skip this step */ 568 569 static feeReturn feeGenPrivate(pubKeyInst *pkinst, 570 const unsigned char *passwd, 571 unsigned passwdLen, 572 char hashPasswd) 573 { 574 unsigned privLen; // desired size of pkinst->privData 575 feeHash *hash = NULL; // a malloc'd array 576 unsigned digestLen; // size of MD5 digest 577 unsigned dataSize; // min(privLen, passwdLen) 578 unsigned numDigests = 0; 579 unsigned i; 580 unsigned char *cp; 581 unsigned toMove; // for this digest 582 unsigned moved; // total digested 583 unsigned char *digest = NULL; 584 unsigned char *privData = NULL; // temp, before modg(curveOrder) 585 giant corder; // lesser of two curve orders 586 587 /* 588 * generate privData which is just larger than the smaller 589 * curve order. 590 * We'll take the result mod the curve order when we're done. 591 * Note we do *not* have to free corder - it's a pointer to a giant 592 * in pkinst->cp. 593 */ 594 corder = lesserX1Order(pkinst->cp); 595 CKASSERT(!isZero(corder)); 596 privLen = (bitlen(corder) / 8) + 1; 597 598 if(!hashPasswd) { 599 /* 600 * Caller trusts the incoming entropy. Verify it's big enough and proceed. 601 */ 602 if(passwdLen < privLen) { 603 return FR_ShortPrivData; 604 } 605 privLen = passwdLen; 606 privData = (unsigned char *)passwd; 607 goto finishUp; 608 } 609 if(passwdLen < 2) { 610 return FR_IllegalArg; 611 } 612 613 614 /* 615 * Calculate how many MD5 digests we'll generate. 616 */ 617 if(privLen > passwdLen) { 618 dataSize = passwdLen; 619 } 620 else { 621 dataSize = privLen; 622 } 623 digestLen = feeHashDigestLen(); 624 numDigests = (dataSize + digestLen - 1) / digestLen; 625 626 hash = (void**) fmalloc(numDigests * sizeof(feeHash)); 627 for(i=0; i<numDigests; i++) { 628 hash[i] = feeHashAlloc(); 629 } 630 631 /* 632 * fill digests with passwd data, digestLen (or resid length) 633 * at a time. If (passwdLen > privLen), last digest will hash all 634 * remaining passwd data. 635 */ 636 cp = (unsigned char *)passwd; 637 moved = 0; 638 for(i=0; i<numDigests; i++) { 639 if(i == (numDigests - 1)) { // last digest 640 toMove = passwdLen - moved; 641 } 642 else { 643 toMove = digestLen; 644 } 645 feeHashAddData(hash[i], cp, toMove); 646 cp += toMove; 647 moved += toMove; 648 } 649 650 /* 651 * copy digests to privData, up to privLen bytes. Pad with 652 * additional copies of digests if necessary. 653 */ 654 privData = (unsigned char*) fmalloc(privLen); 655 cp = privData; 656 moved = 0; 657 i = 0; // digest number 658 for(moved=0; moved<privLen; ) { 659 if((moved + digestLen) > privLen) { 660 toMove = privLen - moved; 661 } 662 else { 663 toMove = digestLen; 664 } 665 digest = feeHashDigest(hash[i++]); 666 bcopy(digest, cp, toMove); 667 cp += toMove; 668 moved += toMove; 669 if(i == numDigests) { 670 i = 0; // wrap to 0, start padding 671 } 672 } 673 674 finishUp: 675 /* 676 * Convert to giant, justify result to within [2, lesserX1Order] 677 */ 678 pkinst->privGiant = giant_with_data(privData, privLen); 679 680 #if FEE_DEBUG 681 if(isZero(pkinst->privGiant)) { 682 printf("feeGenPrivate: privData = 0!\n"); 683 } 684 #endif // FEE_DEBUG 685 686 lesserX1OrderJustify(pkinst->privGiant, pkinst->cp); 687 if(hashPasswd) { 688 memset(privData, 0, privLen); 689 ffree(privData); 690 for(i=0; i<numDigests; i++) { 691 feeHashFree(hash[i]); 692 } 693 ffree(hash); 694 } 695 return FR_Success; 696 } 697 698 #endif /* ECDSA_VERIFY_ONLY */ 699 700 #if FEE_DEBUG 701 702 void printPubKey(feePubKey pubKey) 703 { 704 pubKeyInst *pkinst = pubKey; 705 706 printf("\ncurveParams:\n"); 707 printCurveParams(pkinst->cp); 708 printf("plus:\n"); 709 printKey(pkinst->plus); 710 printf("minus:\n"); 711 printKey(pkinst->minus); 712 if(pkinst->privGiant != NULL) { 713 printf("privGiant : "); 714 printGiant(pkinst->privGiant); 715 } 716 } 717 718 #else // FEE_DEBUG 719 void printPubKey(feePubKey pubKey) {} 720 #endif // FEE_DEBUG 721 722 723 #pragma mark --- Native (custom) key blob formatting --- 724 725 /* 726 * Exported key blob support. New, 23 Mar 1998. 727 * 728 * Convert to public or private key blob. 729 */ 730 731 #ifndef ECDSA_VERIFY_ONLY 732 733 /*** 734 *** Common native blob support 735 ***/ 736 static feeReturn createKeyBlob(pubKeyInst *pkinst, 737 int isPrivate, // 0 : public 1 : private 738 unsigned char **keyBlob, // mallocd and RETURNED 739 unsigned *keyBlobLen) // RETURNED 740 { 741 unsigned char *s; // running ptr into *origS 742 unsigned sLen; 743 int magic; 744 745 /* common blob elements */ 746 sLen = (4 * sizeof(int)) + // magic, version, minVersion, 747 // spare 748 lengthOfByteRepCurveParams(pkinst->cp); 749 if(isPrivate) { 750 /* private only */ 751 sLen += lengthOfByteRepGiant(pkinst->privGiant); 752 magic = PUBLIC_KEY_BLOB_MAGIC_PRIV; 753 } 754 else { 755 /* public only */ 756 sLen += (lengthOfByteRepKey(pkinst->plus) + 757 lengthOfByteRepKey(pkinst->minus)); 758 magic = PUBLIC_KEY_BLOB_MAGIC_PUB; 759 } 760 *keyBlob = s = (unsigned char*) fmalloc(sLen); 761 s += intToByteRep(magic, s); 762 s += intToByteRep(PUBLIC_KEY_BLOB_VERSION, s); 763 s += intToByteRep(PUBLIC_KEY_BLOB_MINVERSION, s); 764 s += intToByteRep(0, s); // spare 765 s += curveParamsToByteRep(pkinst->cp, s); 766 if(isPrivate) { 767 s += giantToByteRep(pkinst->privGiant, s); 768 } 769 else { 770 /* keyToByteRep writes y for plus curve only */ 771 s += keyToByteRep(pkinst->plus, s); 772 if(pkinst->minus != NULL) { 773 s += keyToByteRep(pkinst->minus, s); 774 } 775 else { 776 /* TBD */ 777 dbgLog(("work needed here for blobs with no minus key\n")); 778 } 779 } 780 *keyBlobLen = sLen; 781 return FR_Success; 782 } 783 784 #endif /* ECDSA_VERIFY_ONLY */ 785 786 /* 787 * Init an empty feePubKey from a native blob (non-DER format). 788 */ 789 static feeReturn feePubKeyInitFromKeyBlob(feePubKey pubKey, 790 unsigned char *keyBlob, 791 unsigned keyBlobLen) 792 { 793 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 794 unsigned char *s; // running pointer 795 unsigned sLen; // bytes remaining in *s 796 int magic; 797 unsigned len; // for length of individual components 798 int minVersion; 799 int version; 800 int isPrivate; 801 802 s = keyBlob; 803 sLen = keyBlobLen; 804 if(sLen < (4 * sizeof(int))) { // magic, version, minVersion, spare 805 /* 806 * Too short for all the ints we need 807 */ 808 dbgLog(("feePublicKey: key blob (1)\n")); 809 return FR_BadKeyBlob; 810 } 811 812 magic = byteRepToInt(s); 813 s += sizeof(int); 814 sLen -= sizeof(int); 815 switch(magic) { 816 case PUBLIC_KEY_BLOB_MAGIC_PUB: 817 isPrivate = 0; 818 break; 819 case PUBLIC_KEY_BLOB_MAGIC_PRIV: 820 isPrivate = 1; 821 break; 822 default: 823 dbgLog(("feePublicKey: Bad Public Key Magic Number\n")); 824 return FR_BadKeyBlob; 825 } 826 827 /* 828 * Switch on this for version-specific cases 829 */ 830 version = byteRepToInt(s); 831 s += sizeof(int); 832 sLen -= sizeof(int); 833 834 minVersion = byteRepToInt(s); 835 s += sizeof(int); 836 sLen -= sizeof(int); 837 if(minVersion > PUBLIC_KEY_BLOB_VERSION) { 838 /* 839 * old code, newer key blob - can't parse 840 */ 841 dbgLog(("feePublicKey: Incompatible Public Key (1)\n")); 842 return FR_BadKeyBlob; 843 } 844 845 s += sizeof(int); // skip spare 846 sLen -= sizeof(int); 847 848 pkinst->cp = byteRepToCurveParams(s, sLen, &len); 849 if(pkinst->cp == NULL) { 850 dbgLog(("feePublicKey: Bad Key Blob(2)\n")); 851 return FR_BadKeyBlob; 852 } 853 s += len; 854 sLen -= len; 855 856 /* 857 * Private key blob: privGiant. 858 * Public Key blob: plusX, minusX, plusY. 859 */ 860 if(isPrivate) { 861 pkinst->privGiant = byteRepToGiant(s, sLen, &len); 862 if(pkinst->privGiant == NULL) { 863 dbgLog(("feePublicKey: Bad Key Blob(3)\n")); 864 return FR_BadKeyBlob; 865 } 866 s += len; 867 sLen -= len; 868 } 869 else { 870 /* this writes x and y */ 871 pkinst->plus = byteRepToKey(s, 872 sLen, 873 CURVE_PLUS, // twist 874 pkinst->cp, 875 &len); 876 if(pkinst->plus == NULL) { 877 dbgLog(("feePublicKey: Bad Key Blob(4)\n")); 878 return FR_BadKeyBlob; 879 } 880 s += len; 881 sLen -= len; 882 883 /* this only writes x */ 884 pkinst->minus = byteRepToKey(s, 885 sLen, 886 CURVE_MINUS, // twist 887 pkinst->cp, 888 &len); 889 if(pkinst->minus == NULL) { 890 dbgLog(("feePublicKey: Bad Key Blob(5)\n")); 891 return FR_BadKeyBlob; 892 } 893 s += len; 894 sLen -= len; 895 } 896 897 /* 898 * One more thing: cook up public plusX and minusX for private key 899 * blob case. 900 */ 901 if(isPrivate) { 902 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 903 pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); 904 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 905 set_priv_key_giant(pkinst->minus, pkinst->privGiant); 906 } 907 return FR_Success; 908 909 } 910 911 feeReturn feePubKeyInitFromPubBlob(feePubKey pubKey, 912 unsigned char *keyBlob, 913 unsigned keyBlobLen) 914 { 915 return feePubKeyInitFromKeyBlob(pubKey, keyBlob, keyBlobLen); 916 } 917 918 #ifndef ECDSA_VERIFY_ONLY 919 920 feeReturn feePubKeyInitFromPrivBlob(feePubKey pubKey, 921 unsigned char *keyBlob, 922 unsigned keyBlobLen) 923 { 924 return feePubKeyInitFromKeyBlob(pubKey, keyBlob, keyBlobLen); 925 } 926 927 #endif /* ECDSA_VERIFY_ONLY */ 928 929 #ifndef ECDSA_VERIFY_ONLY 930 931 /* 932 * DER format support. 933 * Obtain portable public and private DER-encoded key blobs from a key. 934 */ 935 feeReturn feePubKeyCreateDERPubBlob(feePubKey pubKey, 936 unsigned char **keyBlob, // mallocd and RETURNED 937 unsigned *keyBlobLen) // RETURNED 938 { 939 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 940 941 if(pkinst == NULL) { 942 return FR_BadPubKey; 943 } 944 if(pkinst->minus == NULL) { 945 /* Only ECDSA key formats supported */ 946 return FR_IncompatibleKey; 947 } 948 return feeDEREncodePublicKey(PUBLIC_DER_KEY_BLOB_VERSION, 949 pkinst->cp, 950 pkinst->plus->x, 951 pkinst->minus->x, 952 isZero(pkinst->plus->y) ? NULL : pkinst->plus->y, 953 keyBlob, 954 keyBlobLen); 955 } 956 957 feeReturn feePubKeyCreateDERPrivBlob(feePubKey pubKey, 958 unsigned char **keyBlob, // mallocd and RETURNED 959 unsigned *keyBlobLen) // RETURNED 960 { 961 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 962 963 if(pkinst == NULL) { 964 return FR_BadPubKey; 965 } 966 if(pkinst->privGiant == NULL) { 967 return FR_IncompatibleKey; 968 } 969 if(pkinst->minus == NULL) { 970 /* Only ECDSA key formats supported */ 971 return FR_IncompatibleKey; 972 } 973 return feeDEREncodePrivateKey(PUBLIC_DER_KEY_BLOB_VERSION, 974 pkinst->cp, 975 pkinst->privGiant, 976 keyBlob, 977 keyBlobLen); 978 } 979 980 #endif /* ECDSA_VERIFY_ONLY */ 981 982 /* 983 * Init an empty feePubKey from a DER-encoded blob, public and private key versions. 984 */ 985 feeReturn feePubKeyInitFromDERPubBlob(feePubKey pubKey, 986 unsigned char *keyBlob, 987 size_t keyBlobLen) 988 { 989 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 990 feeReturn frtn; 991 int version; 992 993 if(pkinst == NULL) { 994 return FR_BadPubKey; 995 } 996 997 /* kind of messy, maybe we should clean this up. But new_public() does too 998 * much - e.g., it allocates the x and y which we really don't want */ 999 memset(pkinst, 0, sizeof(pubKeyInst)); 1000 pkinst->plus = (key) fmalloc(sizeof(keystruct)); 1001 pkinst->minus = (key) fmalloc(sizeof(keystruct)); 1002 if((pkinst->plus == NULL) || (pkinst->minus == NULL)) { 1003 return FR_Memory; 1004 } 1005 memset(pkinst->plus, 0, sizeof(keystruct)); 1006 memset(pkinst->minus, 0, sizeof(keystruct)); 1007 pkinst->cp = NULL; 1008 pkinst->privGiant = NULL; 1009 pkinst->plus->twist = CURVE_PLUS; 1010 pkinst->minus->twist = CURVE_MINUS; 1011 frtn = feeDERDecodePublicKey(keyBlob, 1012 (unsigned)keyBlobLen, 1013 &version, // currently unused 1014 &pkinst->cp, 1015 &pkinst->plus->x, 1016 &pkinst->minus->x, 1017 &pkinst->plus->y); 1018 if(frtn) { 1019 return frtn; 1020 } 1021 /* minus curve, y is not used */ 1022 pkinst->minus->y = newGiant(1); 1023 int_to_giant(0, pkinst->minus->y); 1024 pkinst->plus->cp = pkinst->minus->cp = pkinst->cp; 1025 return FR_Success; 1026 } 1027 1028 #ifndef ECDSA_VERIFY_ONLY 1029 1030 feeReturn feePubKeyInitFromDERPrivBlob(feePubKey pubKey, 1031 unsigned char *keyBlob, 1032 size_t keyBlobLen) 1033 { 1034 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1035 int version; 1036 feeReturn frtn; 1037 1038 if(pkinst == NULL) { 1039 return FR_BadPubKey; 1040 } 1041 memset(pkinst, 0, sizeof(pubKeyInst)); 1042 frtn = feeDERDecodePrivateKey(keyBlob, 1043 (unsigned)keyBlobLen, 1044 &version, // currently unused 1045 &pkinst->cp, 1046 &pkinst->privGiant); 1047 if(frtn) { 1048 return frtn; 1049 } 1050 1051 /* since this blob only had the private data, infer the remaining fields */ 1052 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 1053 pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); 1054 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 1055 set_priv_key_giant(pkinst->minus, pkinst->privGiant); 1056 return FR_Success; 1057 } 1058 1059 #endif /* ECDSA_VERIFY_ONLY */ 1060 1061 #pragma mark --- X509 (public) and PKCS8 (private) key formatting --- 1062 1063 feeReturn feePubKeyCreateX509Blob( 1064 feePubKey pubKey, // public key 1065 unsigned char **keyBlob, // mallocd and RETURNED 1066 unsigned *keyBlobLen) // RETURNED 1067 { 1068 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1069 unsigned char *xyStr = NULL; 1070 unsigned xyStrLen = 0; 1071 feeReturn frtn = feeCreateECDSAPubBlob(pubKey, &xyStr, &xyStrLen); 1072 if(frtn) { 1073 return frtn; 1074 } 1075 frtn = feeDEREncodeX509PublicKey(xyStr, xyStrLen, pkinst->cp, keyBlob, keyBlobLen); 1076 ffree(xyStr); 1077 return frtn; 1078 } 1079 1080 feeReturn feePubKeyCreatePKCS8Blob( 1081 feePubKey pubKey, // private key 1082 unsigned char **keyBlob, // mallocd and RETURNED 1083 unsigned *keyBlobLen) // RETURNED 1084 { 1085 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1086 unsigned char *privStr = NULL; 1087 unsigned privStrLen = 0; 1088 feeReturn frtn = feeCreateECDSAPrivBlob(pubKey, &privStr, &privStrLen); 1089 if(frtn) { 1090 return frtn; 1091 } 1092 unsigned char *pubStr = NULL; 1093 unsigned pubStrLen = 0; 1094 frtn = feeCreateECDSAPubBlob(pubKey, &pubStr, &pubStrLen); 1095 if(frtn) { 1096 goto errOut; 1097 } 1098 frtn = feeDEREncodePKCS8PrivateKey(privStr, privStrLen, 1099 pubStr, pubStrLen, 1100 pkinst->cp, keyBlob, keyBlobLen); 1101 errOut: 1102 if(privStr) { 1103 ffree(privStr); 1104 } 1105 if(pubStr) { 1106 ffree(pubStr); 1107 } 1108 return frtn; 1109 } 1110 1111 feeReturn feePubKeyInitFromX509Blob( 1112 feePubKey pubKey, // public key 1113 unsigned char *keyBlob, 1114 size_t keyBlobLen) 1115 { 1116 feeDepth depth; 1117 unsigned char *xyStr = NULL; 1118 unsigned xyStrLen = 0; 1119 1120 /* obtain x/y and depth from X509 encoding */ 1121 feeReturn frtn = feeDERDecodeX509PublicKey(keyBlob, (unsigned)keyBlobLen, &depth, 1122 &xyStr, &xyStrLen); 1123 if(frtn) { 1124 return frtn; 1125 } 1126 1127 frtn = feePubKeyInitFromECDSAPubBlob(pubKey, xyStr, xyStrLen, depth); 1128 ffree(xyStr); 1129 return frtn; 1130 } 1131 1132 1133 feeReturn feePubKeyInitFromPKCS8Blob( 1134 feePubKey pubKey, // private key 1135 unsigned char *keyBlob, 1136 size_t keyBlobLen) 1137 { 1138 feeDepth depth; 1139 unsigned char *privStr = NULL; 1140 unsigned privStrLen = 0; 1141 1142 /* obtain x/y and depth from PKCS8 encoding */ 1143 /* For now we ignore the possible public key string */ 1144 feeReturn frtn = feeDERDecodePKCS8PrivateKey(keyBlob, (unsigned)keyBlobLen, &depth, 1145 &privStr, &privStrLen, NULL, NULL); 1146 if(frtn) { 1147 return frtn; 1148 } 1149 1150 frtn = feePubKeyInitFromECDSAPrivBlob(pubKey, privStr, privStrLen, depth); 1151 ffree(privStr); 1152 return frtn; 1153 } 1154 1155 #pragma mark --- OpenSSL key formatting --- 1156 1157 /* 1158 * The native OpenSSL ECDSA key format contains both the private and public 1159 * components in one blob. This throws a bit of a monkey wrench into the API 1160 * here, as we only have one encoder - which requires a private key - and one 1161 * decoder, which can result in the decoding of either a public or a private 1162 * key. 1163 */ 1164 feeReturn feePubKeyCreateOpenSSLBlob( 1165 feePubKey pubKey, // private key 1166 unsigned char **keyBlob, // mallocd and RETURNED 1167 unsigned *keyBlobLen) // RETURNED 1168 { 1169 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1170 unsigned char *privStr = NULL; 1171 unsigned privStrLen = 0; 1172 feeReturn frtn = feeCreateECDSAPrivBlob(pubKey, &privStr, &privStrLen); 1173 if(frtn) { 1174 return frtn; 1175 } 1176 unsigned char *pubStr = NULL; 1177 unsigned pubStrLen = 0; 1178 frtn = feeCreateECDSAPubBlob(pubKey, &pubStr, &pubStrLen); 1179 if(frtn) { 1180 goto errOut; 1181 } 1182 frtn = feeDEREncodeOpenSSLPrivateKey(privStr, privStrLen, 1183 pubStr, pubStrLen, 1184 pkinst->cp, keyBlob, keyBlobLen); 1185 errOut: 1186 if(privStr) { 1187 ffree(privStr); 1188 } 1189 if(pubStr) { 1190 ffree(pubStr); 1191 } 1192 return frtn; 1193 } 1194 1195 feeReturn feePubKeyInitFromOpenSSLBlob( 1196 feePubKey pubKey, // private or public key 1197 int pubOnly, 1198 unsigned char *keyBlob, 1199 size_t keyBlobLen) 1200 { 1201 feeDepth depth; 1202 unsigned char *privStr = NULL; 1203 unsigned privStrLen = 0; 1204 unsigned char *pubStr = NULL; 1205 unsigned pubStrLen = 0; 1206 1207 /* obtain x/y, public bit string, and depth from PKCS8 encoding */ 1208 feeReturn frtn = feeDERDecodeOpenSSLKey(keyBlob, (unsigned)keyBlobLen, &depth, 1209 &privStr, &privStrLen, &pubStr, &pubStrLen); 1210 if(frtn) { 1211 return frtn; 1212 } 1213 1214 if(pubOnly) { 1215 frtn = feePubKeyInitFromECDSAPubBlob(pubKey, pubStr, pubStrLen, depth); 1216 } 1217 else { 1218 frtn = feePubKeyInitFromECDSAPrivBlob(pubKey, privStr, privStrLen, depth); 1219 } 1220 if(privStr) { 1221 ffree(privStr); 1222 } 1223 if(pubStr) { 1224 ffree(pubStr); 1225 } 1226 return frtn; 1227 } 1228 1229 /* 1230 * ANSI X9.62/Certicom key support. 1231 * Public key is 04 || x || y 1232 * Private key is privData per Certicom SEC1 C.4. 1233 */ 1234 feeReturn feeCreateECDSAPubBlob(feePubKey pubKey, 1235 unsigned char **keyBlob, 1236 unsigned *keyBlobLen) 1237 { 1238 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1239 if(pkinst == NULL) { 1240 return FR_BadPubKey; 1241 } 1242 1243 unsigned giantBytes = (pkinst->cp->q + 7) / 8; 1244 unsigned blobSize = 1 + (2 * giantBytes); 1245 unsigned char *blob = fmalloc(blobSize); 1246 if(blob == NULL) { 1247 return FR_Memory; 1248 } 1249 *blob = 0x04; 1250 serializeGiant(pkinst->plus->x, blob+1, giantBytes); 1251 serializeGiant(pkinst->plus->y, blob+1+giantBytes, giantBytes); 1252 *keyBlob = blob; 1253 *keyBlobLen = blobSize; 1254 return FR_Success; 1255 } 1256 1257 feeReturn feeCreateECDSAPrivBlob(feePubKey pubKey, 1258 unsigned char **keyBlob, 1259 unsigned *keyBlobLen) 1260 { 1261 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1262 if(pkinst == NULL) { 1263 return FR_BadPubKey; 1264 } 1265 if(pkinst->privGiant == NULL) { 1266 return FR_IncompatibleKey; 1267 } 1268 1269 /* 1270 * Return the raw private key bytes padded with zeroes in 1271 * the m.s. end to fill exactly one prime-size byte array. 1272 */ 1273 unsigned giantBytes = (pkinst->cp->q + 7) / 8; 1274 unsigned char *blob = fmalloc(giantBytes); 1275 if(blob == NULL) { 1276 return FR_Memory; 1277 } 1278 serializeGiant(pkinst->privGiant, blob, giantBytes); 1279 *keyBlob = blob; 1280 *keyBlobLen = giantBytes; 1281 return FR_Success; 1282 } 1283 1284 /* Caller determines depth from other sources (e.g. AlgId.Params) */ 1285 feeReturn feePubKeyInitFromECDSAPubBlob(feePubKey pubKey, 1286 const unsigned char *keyBlob, 1287 unsigned keyBlobLen, 1288 feeDepth depth) 1289 { 1290 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1291 if(pkinst == NULL) { 1292 return FR_BadPubKey; 1293 } 1294 curveParams *cp = curveParamsForDepth(depth); 1295 if(cp == NULL) { 1296 return FR_IllegalDepth; 1297 } 1298 unsigned giantBytes = (cp->q + 7) / 8; 1299 unsigned blobSize = 1 + (2 * giantBytes); 1300 if(keyBlobLen != blobSize) { 1301 dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blobLen\n")); 1302 return FR_BadKeyBlob; 1303 } 1304 if(*keyBlob != 0x04) { 1305 dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blob leader\n")); 1306 return FR_BadKeyBlob; 1307 } 1308 1309 pkinst->cp = cp; 1310 pkinst->plus = new_public(cp, CURVE_PLUS); 1311 deserializeGiant(keyBlob+1, pkinst->plus->x, giantBytes); 1312 deserializeGiant(keyBlob+1+giantBytes, pkinst->plus->y, giantBytes); 1313 return FR_Success; 1314 } 1315 1316 feeReturn feePubKeyInitFromECDSAPrivBlob(feePubKey pubKey, 1317 const unsigned char *keyBlob, 1318 unsigned keyBlobLen, 1319 feeDepth depth) 1320 { 1321 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1322 if(pkinst == NULL) { 1323 return FR_BadPubKey; 1324 } 1325 curveParams *cp = curveParamsForDepth(depth); 1326 if(cp == NULL) { 1327 return FR_IllegalDepth; 1328 } 1329 unsigned giantDigits = cp->basePrime->sign; 1330 unsigned giantBytes = (cp->q + 7) / 8; 1331 1332 /* 1333 * The specified private key can be one byte smaller than the modulus */ 1334 if((keyBlobLen > giantBytes) || (keyBlobLen < (giantBytes - 1))) { 1335 dbgLog(("feePubKeyInitFromECDSAPrivBlob: bad blobLen\n")); 1336 return FR_BadKeyBlob; 1337 } 1338 1339 pkinst->cp = cp; 1340 1341 /* cook up a new private giant */ 1342 pkinst->privGiant = newGiant(giantDigits); 1343 if(pkinst->privGiant == NULL) { 1344 return FR_Memory; 1345 } 1346 deserializeGiant(keyBlob, pkinst->privGiant, keyBlobLen); 1347 1348 /* since this blob only had the private data, infer the remaining fields */ 1349 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 1350 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 1351 return FR_Success; 1352 } 1353