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 "feeDES.h" 64#include "byteRep.h" 65#if CRYPTKIT_DER_ENABLE 66#include "CryptKitDER.h" 67#endif 68#include <stdio.h> 69 70/* 71 * 11/27/98 dmitch: The ECDSA_VERIFY_ONLY symbol, when #defined, disables all 72 * of the code in this module except that which is necessary for ECDSA 73 * siggnature verification. 74 */ 75 76#ifndef NULL 77#define NULL ((void *)0) 78#endif // NULL 79 80/* 81 * Magic number for a portable key blobs. Must be in sync with static 82 * final PUBLIC_KEY_STRING_MAGIC in JavaFee/PublicKey.java. 83 */ 84#define PUBLIC_KEY_BLOB_MAGIC_PUB 0xfeeddeef 85#define PUBLIC_KEY_BLOB_MAGIC_PRIV 0xfeeddeed 86#define PUBLIC_KEY_BLOB_VERSION 6 87#define PUBLIC_KEY_BLOB_MINVERSION 6 88 89#if CRYPTKIT_DER_ENABLE 90#define PUBLIC_DER_KEY_BLOB_VERSION 1 91#endif 92 93/* 94 * Private data. All "instance" routines are passed a feePubKey (actually 95 * a void *) which is actually a pointer to one of these. 96 */ 97typedef struct { 98 key plus; 99 key minus; // not needed for ECDSA 100 curveParams *cp; // common params shared by minus, plus 101 giant privGiant; // private key 102} pubKeyInst; 103 104static feeReturn feeGenPrivate(pubKeyInst *pkinst, 105 const unsigned char *passwd, 106 unsigned passwdLen, 107 char hashPasswd); 108static pubKeyInst *pubKeyInstAlloc(void); 109static void pubKeyInstFree(pubKeyInst *pkinst); 110#if GIANTS_VIA_STACK 111static void feePubKeyInitGiants(void); 112#endif 113static feeReturn createKeyBlob(pubKeyInst *pkinst, 114 int isPrivate, // 0 : public 1 : private 115 unsigned char **keyBlob, // mallocd and RETURNED 116 unsigned *keyBlobLen); // RETURNED 117static feeReturn feePubKeyInitFromKeyBlob(feePubKey pubKey, 118 unsigned char *keyBlob, 119 unsigned keyBlobLen); 120 121#pragma mark --- General public API function --- 122 123/* 124 * Obatin a newly allocated feePubKey. 125 */ 126feePubKey feePubKeyAlloc(void) 127{ 128 pubKeyInst *pkinst = pubKeyInstAlloc(); 129 130 #if GIANTS_VIA_STACK 131 feePubKeyInitGiants(); 132 #endif 133 return pkinst; 134} 135 136void feePubKeyFree(feePubKey pubKey) 137{ 138 pubKeyInstFree((pubKeyInst*) pubKey); 139} 140 141#ifndef ECDSA_VERIFY_ONLY 142/* 143 * Init feePubKey from private key data. 144 */ 145feeReturn feePubKeyInitFromPrivDataKeyBits(feePubKey pubKey, 146 const unsigned char *privData, 147 unsigned privDataLen, 148 unsigned keyBits, /* key size in bits */ 149 feePrimeType primeType, /* FPT_Fefault means "best one" */ 150 feeCurveType curveType, /* FCT_Default means "best one" */ 151 char hashPrivData) 152{ 153 feeReturn frtn; 154 feeDepth depth; 155 156 frtn = feeKeyBitsToDepth(keyBits, primeType, curveType, &depth); 157 if(frtn) { 158 return frtn; 159 } 160 return feePubKeyInitFromPrivDataDepth(pubKey, 161 privData, 162 privDataLen, 163 depth, 164 hashPrivData); 165} 166 167feeReturn feePubKeyInitFromPrivDataDepth(feePubKey pubKey, 168 const unsigned char *privData, 169 unsigned privDataLen, 170 feeDepth depth, 171 char hashPrivData) 172{ 173 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 174 feeReturn frtn; 175 176 #if ENGINE_127_BITS 177 if(depth != FEE_DEPTH_127_1) { 178 dbgLog(("Illegal Depth\n")); 179 return FR_IllegalDepth; 180 } 181 #endif // ENGINE_127_BITS 182 if(depth > FEE_DEPTH_MAX) { 183 dbgLog(("Illegal Depth\n")); 184 return FR_IllegalDepth; 185 } 186 187 pkinst->cp = curveParamsForDepth(depth); 188 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 189 if(pkinst->cp->x1Minus != NULL) { 190 pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); 191 } 192 /* else only usable for ECDSA */ 193 194 frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData); 195 if(frtn) { 196 return frtn; 197 } 198 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 199 if(pkinst->cp->x1Minus != NULL) { 200 set_priv_key_giant(pkinst->minus, pkinst->privGiant); 201 } 202 return FR_Success; 203} 204 205#endif /* ECDSA_VERIFY_ONLY */ 206 207/* 208 * Init feePubKey from curve parameters matching existing oldKey. 209 */ 210feeReturn feePubKeyInitFromKey(feePubKey pubKey, 211 const unsigned char *privData, 212 unsigned privDataLen, 213 feePubKey oldKey, 214 char hashPrivData) 215{ 216 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 217 pubKeyInst *oldInst = (pubKeyInst *) oldKey; 218 feeReturn frtn; 219 220 if(oldKey == NULL) { 221 dbgLog(("NULL existing key\n")); 222 return FR_BadPubKey; 223 } 224 225 pkinst->cp = curveParamsCopy(oldInst->cp); 226 if(pkinst->cp->x1Minus != NULL) { 227 pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); 228 if(pkinst->minus == NULL) { 229 goto abort; 230 } 231 } 232 /* else this curve only usable for ECDSA */ 233 234 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 235 if(pkinst->plus == NULL) { 236 goto abort; 237 } 238 frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData); 239 if(frtn) { 240 return frtn; 241 } 242 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 243 if(pkinst->cp->x1Minus != NULL) { 244 set_priv_key_giant(pkinst->minus, pkinst->privGiant); 245 } 246 return FR_Success; 247 248abort: 249 dbgLog(("Bad Existing Public Key\n")); 250 return FR_BadPubKey; 251} 252 253/*** 254 *** Public KeyString support. 255 ***/ 256/* 257 * Init feePubKey from a public key string. 258 * 259 * See ByteRep.doc for info on the format of the public key string and blobs; 260 * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT. 261 */ 262feeReturn feePubKeyInitFromKeyString(feePubKey pubKey, 263 const char *keyStr, 264 unsigned keyStrLen) 265{ 266 unsigned char *blob = NULL; 267 unsigned blobLen; 268 feeReturn frtn; 269 270 blob = dec64((unsigned char *)keyStr, keyStrLen, &blobLen); 271 if(blob == NULL) { 272 dbgLog(("Bad Public Key String (not enc64)\n")); 273 return FR_BadPubKeyString; 274 } 275 frtn = feePubKeyInitFromKeyBlob(pubKey, blob, blobLen); 276 ffree(blob); 277 return frtn; 278} 279 280/* 281 * Create a public key in the form of a null-terminated C string. 282 * This string contains an encoded version of all of our ivars except for 283 * privGiant. 284 * 285 * See ByteRep.doc for info on the format of the public key string and blobs; 286 * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT. 287 */ 288feeReturn feePubKeyCreateKeyString(feePubKey pubKey, 289 char **pubKeyString, /* RETURNED */ 290 unsigned *pubKeyStringLen) /* RETURNED */ 291{ 292 unsigned char *blob; 293 unsigned blobLen; 294 feeReturn frtn; 295 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 296 297 /* get binary pub blob, encode the blob, free the blob */ 298 frtn = createKeyBlob(pkinst, 299 0, // isPrivate 300 &blob, 301 &blobLen); 302 if(frtn) { 303 return frtn; 304 } 305 306 *pubKeyString = (char *)enc64(blob, blobLen, pubKeyStringLen); 307 ffree(blob); 308 return FR_Success; 309} 310 311/*** 312 *** Native key blob support. 313 ***/ 314 315#ifndef ECDSA_VERIFY_ONLY 316 317/* 318 * Obtain portable public and private key blobs from a key. 319 */ 320feeReturn feePubKeyCreatePubBlob(feePubKey pubKey, 321 unsigned char **keyBlob, // mallocd and RETURNED 322 unsigned *keyBlobLen) // RETURNED 323{ 324 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 325 326 return createKeyBlob(pkinst, 327 0, 328 keyBlob, 329 keyBlobLen); 330} 331 332feeReturn feePubKeyCreatePrivBlob(feePubKey pubKey, 333 unsigned char **keyBlob, // mallocd and RETURNED 334 unsigned *keyBlobLen) // RETURNED 335{ 336 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 337 338 if(pkinst->privGiant == NULL) { 339 return FR_IncompatibleKey; 340 } 341 return createKeyBlob(pkinst, 342 1, 343 keyBlob, 344 keyBlobLen); 345} 346 347/* 348 * Given private-capable privKey, initialize pubKey to be its corresponding 349 * public key. 350 */ 351feeReturn feePubKeyInitPubKeyFromPriv(feePubKey privKey, 352 feePubKey pubKey) 353{ 354 pubKeyInst *privInst = (pubKeyInst *)privKey; 355 pubKeyInst *pubInst = (pubKeyInst *)pubKey; 356 357 if((privInst == NULL) || (pubInst == NULL)) { 358 return FR_BadPubKey; 359 } 360 if(privInst->privGiant == NULL) { 361 return FR_IncompatibleKey; 362 } 363 pubInst->cp = curveParamsCopy(privInst->cp); 364 if(pubInst == NULL) { 365 return FR_Memory; 366 } 367 pubInst->plus = new_public_with_key(privInst->plus, pubInst->cp); 368 if(pubInst->plus == NULL) { 369 return FR_Memory; 370 } 371 if(pubInst->cp->x1Minus != NULL) { 372 pubInst->minus = new_public_with_key(privInst->minus, pubInst->cp); 373 if(pubInst->minus == NULL) { 374 return FR_Memory; 375 } 376 } 377 return FR_Success; 378} 379 380#endif /* ECDSA_VERIFY_ONLY */ 381 382/* 383 * Returns non-zero if two keys are equivalent. 384 */ 385int feePubKeyIsEqual(feePubKey key1, feePubKey key2) 386{ 387 pubKeyInst *pkinst1 = (pubKeyInst *) key1; 388 pubKeyInst *pkinst2 = (pubKeyInst *) key2; 389 390 if ((pkinst1 == NULL) || (pkinst2 == NULL)) { 391 return 0; 392 } 393 if((pkinst1->minus != NULL) && (pkinst2->minus != NULL)) { 394 if(key_equal(pkinst1->minus, pkinst2->minus) == 0) { 395 return 0; 396 } 397 } 398 if(key_equal(pkinst1->plus, pkinst2->plus) == 0) { 399 return 0; 400 } 401 return 1; 402} 403 404/* 405 * Returns non-zero if key is private-capable (i.e., capable of signing 406 * and decrypting). 407 */ 408int feePubKeyIsPrivate(feePubKey key) 409{ 410 pubKeyInst *myPkinst = (pubKeyInst *)key; 411 412 return ((myPkinst->privGiant != NULL) ? 1 : 0); 413} 414 415#ifndef ECDSA_VERIFY_ONLY 416 417#if CRYPTKIT_KEY_EXCHANGE 418 419feeReturn feePubKeyCreatePad(feePubKey myKey, 420 feePubKey theirKey, 421 unsigned char **padData, /* RETURNED */ 422 unsigned *padDataLen) /* RETURNED padData length in bytes */ 423{ 424 pubKeyInst *myPkinst = (pubKeyInst *) myKey; 425 pubKeyInst *theirPkinst = (pubKeyInst *) theirKey; 426 giant pad; 427 unsigned char *result; 428 unsigned padLen; 429 key pkey; 430 431 /* 432 * Do some compatibility checking (myKey, theirKey) here...? 433 */ 434 if(DEFAULT_CURVE == CURVE_PLUS) { 435 pkey = theirPkinst->plus; 436 } 437 else { 438 pkey = theirPkinst->minus; 439 } 440 pad = make_pad(myPkinst->privGiant, pkey); 441 result = mem_from_giant(pad, &padLen); 442 freeGiant(pad); 443 444 /* 445 * Ensure we have a the minimum necessary for DES. A bit of a hack, 446 * to be sure. 447 */ 448 if(padLen >= FEE_DES_MIN_STATE_SIZE) { 449 *padData = result; 450 *padDataLen = padLen; 451 } 452 else { 453 *padData = (unsigned char*) fmalloc(FEE_DES_MIN_STATE_SIZE); 454 *padDataLen = FEE_DES_MIN_STATE_SIZE; 455 bzero(*padData, FEE_DES_MIN_STATE_SIZE); 456 bcopy(result, *padData, padLen); 457 ffree(result); 458 } 459 return FR_Success; 460} 461 462#endif /* CRYPTKIT_KEY_EXCHANGE */ 463 464#if CRYPTKIT_HIGH_LEVEL_SIG 465 466#warning HLS 467/* 468 * Generate digital signature, ElGamal style. 469 */ 470feeReturn feePubKeyCreateSignature(feePubKey pubKey, 471 const unsigned char *data, 472 unsigned dataLen, 473 unsigned char **signature, /* fmalloc'd and RETURNED */ 474 unsigned *signatureLen) /* RETURNED */ 475{ 476 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 477 feeHash hash; 478 feeSig sig; 479 unsigned char *Pm = NULL; 480 unsigned PmLen; 481 feeReturn frtn; 482 483 if(pkinst->privGiant == NULL) { 484 dbgLog(("feePubKeyCreateSignature: Attempt to Sign without" 485 " private data\n")); 486 return FR_BadPubKey; 487 } 488 hash = feeHashAlloc(); 489 sig = feeSigNewWithKey(pubKey, NULL, NULL); 490 if(sig == NULL) { 491 /* 492 * Shouldn't happen, but... 493 */ 494 feeHashFree(hash); 495 return FR_BadPubKey; 496 } 497 498 /* 499 * Get Pm to salt hash object 500 */ 501 Pm = feeSigPm(sig, &PmLen); 502 feeHashAddData(hash, Pm, PmLen); 503 504 /* 505 * Now hash the data proper, then sign the hash 506 */ 507 feeHashAddData(hash, data, dataLen); 508 frtn = feeSigSign(sig, 509 feeHashDigest(hash), 510 feeHashDigestLen(), 511 pubKey); 512 if(frtn == FR_Success) { 513 frtn = feeSigData(sig, signature, signatureLen); 514 } 515 feeHashFree(hash); 516 feeSigFree(sig); 517 ffree(Pm); 518 return frtn; 519} 520 521/* 522 * Verify digital signature, ElGamal style. If the signature is ECDSA, 523 * we'll use that format for compatibility. 524 */ 525feeReturn feePubKeyVerifySignature(feePubKey pubKey, 526 const unsigned char *data, 527 unsigned dataLen, 528 const unsigned char *signature, 529 unsigned signatureLen) 530{ 531 feeHash hash; 532 feeSig sig; 533 unsigned char *Pm = NULL; 534 unsigned PmLen; 535 feeReturn frtn; 536 537 hash = feeHashAlloc(); 538 frtn = feeSigParse(signature, signatureLen, &sig); 539 if(frtn) { 540 feeHashFree(hash); 541 #if CRYPTKIT_ECDSA_ENABLE 542 if(frtn == FR_WrongSignatureType) { 543 return feePubKeyVerifyECDSASignature(pubKey, 544 data, 545 dataLen, 546 signature, 547 signatureLen); 548 } 549 #endif /* CRYPTKIT_ECDSA_ENABLE */ 550 return frtn; 551 } 552 553 /* 554 * Get PM as salt; eat salt, then hash data 555 */ 556 Pm = feeSigPm(sig, &PmLen); 557 feeHashAddData(hash, Pm, PmLen); 558 feeHashAddData(hash, data, dataLen); 559 frtn = feeSigVerify(sig, 560 feeHashDigest(hash), 561 feeHashDigestLen(), 562 pubKey); 563 564 feeHashFree(hash); 565 feeSigFree(sig); 566 ffree(Pm); 567 return frtn; 568} 569 570#pragma mark --- ECDSA signature: high level routines --- 571 572#if CRYPTKIT_ECDSA_ENABLE 573/* 574 * Generate digital signature, ECDSA style. 575 */ 576feeReturn feePubKeyCreateECDSASignature(feePubKey pubKey, 577 const unsigned char *data, 578 unsigned dataLen, 579 unsigned char **signature, /* fmalloc'd and RETURNED */ 580 unsigned *signatureLen) /* RETURNED */ 581{ 582 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 583 sha1Obj sha1; 584 feeReturn frtn; 585 586 if(pkinst->privGiant == NULL) { 587 dbgLog(("feePubKeyCreateECDSASignature: Attempt to Sign " 588 "without private data\n")); 589 return FR_BadPubKey; 590 } 591 sha1 = sha1Alloc(); 592 sha1AddData(sha1, data, dataLen); 593 frtn = feeECDSASign(pubKey, 594 sha1Digest(sha1), 595 sha1DigestLen(), 596 NULL, // randFcn 597 NULL, 598 signature, 599 signatureLen); 600 sha1Free(sha1); 601 return frtn; 602} 603#endif /* CRYPTKIT_ECDSA_ENABLE */ 604#endif /* CRYPTKIT_HIGH_LEVEL_SIG */ 605#endif /* ECDSA_VERIFY_ONLY */ 606 607#if CRYPTKIT_HIGH_LEVEL_SIG 608 609#if CRYPTKIT_ECDSA_ENABLE 610 611/* 612 * Verify digital signature, ECDSA style. 613 */ 614feeReturn feePubKeyVerifyECDSASignature(feePubKey pubKey, 615 const unsigned char *data, 616 unsigned dataLen, 617 const unsigned char *signature, 618 unsigned signatureLen) 619{ 620 sha1Obj sha1; 621 feeReturn frtn; 622 623 sha1 = sha1Alloc(); 624 sha1AddData(sha1, data, dataLen); 625 frtn = feeECDSAVerify(signature, 626 signatureLen, 627 sha1Digest(sha1), 628 sha1DigestLen(), 629 pubKey); 630 sha1Free(sha1); 631 return frtn; 632} 633 634#endif /* CRYPTKIT_ECDSA_ENABLE */ 635 636#endif /* CRYPTKIT_HIGH_LEVEL_SIG */ 637 638#pragma mark --- ECDH --- 639 640/* 641 * Diffie-Hellman. Public key is specified either as a feePubKey or 642 * a ANSI X9.62 format public key string (0x04 | x | y). In either case 643 * the caller must ensure that the two keys are on the same curve. 644 * Output data is fmalloc'd here; caller must free. Output data is 645 * exactly the size of the curve's modulus in bytes. 646 */ 647feeReturn feePubKeyECDH( 648 feePubKey privKey, 649 /* one of the following two is non-NULL */ 650 feePubKey pubKey, 651 const unsigned char *pubKeyStr, 652 unsigned pubKeyStrLen, 653 /* output fmallocd and RETURNED here */ 654 unsigned char **output, 655 unsigned *outputLen) 656{ 657 feePubKey theirPub = pubKey; 658 feeReturn frtn = FR_Success; 659 pubKeyInst *privInst = (pubKeyInst *) privKey; 660 661 if(privInst->privGiant == NULL) { 662 dbgLog(("feePubKeyECDH: privKey not a private key\n")); 663 return FR_IncompatibleKey; 664 } 665 666 if(theirPub == NULL) { 667 if(pubKeyStr == NULL) { 668 return FR_IllegalArg; 669 } 670 671 /* Cook up a public key with the same curveParams as the private key */ 672 feeDepth depth; 673 frtn = curveParamsDepth(privInst->cp, &depth); 674 if(frtn) { 675 return frtn; 676 } 677 theirPub = feePubKeyAlloc(); 678 if(theirPub == NULL) { 679 return FR_Memory; 680 } 681 frtn = feePubKeyInitFromECDSAPubBlob(theirPub, pubKeyStr, pubKeyStrLen, depth); 682 if(frtn) { 683 goto errOut; 684 } 685 } 686 687 pubKeyInst *pubInst = (pubKeyInst *) theirPub; 688 689 giant outputGiant = make_pad(privInst->privGiant, pubInst->plus); 690 if(outputGiant == NULL) { 691 dbgLog(("feePubKeyECDH: make_pad error\n")); 692 frtn = FR_Internal; 693 } 694 else { 695 *outputLen = (privInst->cp->q + 7) / 8; 696 *output = (unsigned char *)fmalloc(*outputLen); 697 if(*output == NULL) { 698 frtn = FR_Memory; 699 goto errOut; 700 } 701 serializeGiant(outputGiant, *output, *outputLen); 702 freeGiant(outputGiant); 703 } 704errOut: 705 if((pubKey == NULL) && (theirPub != NULL)) { 706 feePubKeyFree(theirPub); 707 } 708 return frtn; 709} 710 711#pragma mark --- feePubKey data accessors --- 712 713unsigned feePubKeyBitsize(feePubKey pubKey) 714{ 715 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 716 switch(pkinst->cp->primeType) { 717 case FPT_General: /* cp->q is here for just this purpose */ 718 case FPT_Mersenne: 719 return pkinst->cp->q; 720 case FPT_FEE: /* could be larger or smaller than 2^q-1 */ 721 default: 722 return bitlen(pkinst->cp->basePrime); 723 } 724 /* NOT REACHED */ 725 return 0; 726} 727 728/* 729 * Accessor routines. 730 */ 731/* private only...*/ 732key feePubKeyPlusCurve(feePubKey pubKey) 733{ 734 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 735 736 return pkinst->plus; 737} 738 739key feePubKeyMinusCurve(feePubKey pubKey) 740{ 741 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 742 743 return pkinst->minus; 744} 745 746curveParams *feePubKeyCurveParams(feePubKey pubKey) 747{ 748 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 749 750 return pkinst->cp; 751} 752 753giant feePubKeyPrivData(feePubKey pubKey) 754{ 755 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 756 757 return pkinst->privGiant; 758} 759 760const char *feePubKeyAlgorithmName(void) 761{ 762 return "Elliptic Curve - FEE by Apple Computer"; 763} 764 765#pragma mark --- Private functions --- 766 767/* 768 * alloc, free pubKeyInst 769 */ 770static pubKeyInst *pubKeyInstAlloc(void) 771{ 772 pubKeyInst *pkinst = (pubKeyInst *) fmalloc(sizeof(pubKeyInst)); 773 774 bzero(pkinst, sizeof(pubKeyInst)); 775 return pkinst; 776} 777 778static void pubKeyInstFree(pubKeyInst *pkinst) 779{ 780 if(pkinst->minus) { 781 free_key(pkinst->minus); 782 } 783 if(pkinst->plus) { 784 free_key(pkinst->plus); 785 } 786 if(pkinst->cp) { 787 freeCurveParams(pkinst->cp); 788 } 789 if(pkinst->privGiant) { 790 /* 791 * Zero out the private data... 792 */ 793 clearGiant(pkinst->privGiant); 794 freeGiant(pkinst->privGiant); 795 } 796 ffree(pkinst); 797} 798 799#ifndef ECDSA_VERIFY_ONLY 800 801/* 802 * Create a pubKeyInst.privGiant given a password of 803 * arbitrary length. 804 * Currently, the only error is "private data too short" (FR_IllegalArg). 805 */ 806 807#define NO_PRIV_MUNGE 0 /* skip this step */ 808 809static feeReturn feeGenPrivate(pubKeyInst *pkinst, 810 const unsigned char *passwd, 811 unsigned passwdLen, 812 char hashPasswd) 813{ 814 unsigned privLen; // desired size of pkinst->privData 815 feeHash *hash = NULL; // a malloc'd array 816 unsigned digestLen; // size of MD5 digest 817 unsigned dataSize; // min(privLen, passwdLen) 818 unsigned numDigests = 0; 819 unsigned i; 820 unsigned char *cp; 821 unsigned toMove; // for this digest 822 unsigned moved; // total digested 823 unsigned char *digest = NULL; 824 unsigned char *privData = NULL; // temp, before modg(curveOrder) 825 giant corder; // lesser of two curve orders 826 827 /* 828 * generate privData which is just larger than the smaller 829 * curve order. 830 * We'll take the result mod the curve order when we're done. 831 * Note we do *not* have to free corder - it's a pointer to a giant 832 * in pkinst->cp. 833 */ 834 corder = lesserX1Order(pkinst->cp); 835 CKASSERT(!isZero(corder)); 836 privLen = (bitlen(corder) / 8) + 1; 837 838 if(!hashPasswd) { 839 /* 840 * Caller trusts the incoming entropy. Verify it's big enough and proceed. 841 */ 842 if(passwdLen < privLen) { 843 return FR_ShortPrivData; 844 } 845 privLen = passwdLen; 846 privData = (unsigned char *)passwd; 847 goto finishUp; 848 } 849 if(passwdLen < 2) { 850 return FR_IllegalArg; 851 } 852 853 854 /* 855 * Calculate how many MD5 digests we'll generate. 856 */ 857 if(privLen > passwdLen) { 858 dataSize = passwdLen; 859 } 860 else { 861 dataSize = privLen; 862 } 863 digestLen = feeHashDigestLen(); 864 numDigests = (dataSize + digestLen - 1) / digestLen; 865 866 hash = (void**) fmalloc(numDigests * sizeof(feeHash)); 867 for(i=0; i<numDigests; i++) { 868 hash[i] = feeHashAlloc(); 869 } 870 871 /* 872 * fill digests with passwd data, digestLen (or resid length) 873 * at a time. If (passwdLen > privLen), last digest will hash all 874 * remaining passwd data. 875 */ 876 cp = (unsigned char *)passwd; 877 moved = 0; 878 for(i=0; i<numDigests; i++) { 879 if(i == (numDigests - 1)) { // last digest 880 toMove = passwdLen - moved; 881 } 882 else { 883 toMove = digestLen; 884 } 885 feeHashAddData(hash[i], cp, toMove); 886 cp += toMove; 887 moved += toMove; 888 } 889 890 /* 891 * copy digests to privData, up to privLen bytes. Pad with 892 * additional copies of digests if necessary. 893 */ 894 privData = (unsigned char*) fmalloc(privLen); 895 cp = privData; 896 moved = 0; 897 i = 0; // digest number 898 for(moved=0; moved<privLen; ) { 899 if((moved + digestLen) > privLen) { 900 toMove = privLen - moved; 901 } 902 else { 903 toMove = digestLen; 904 } 905 digest = feeHashDigest(hash[i++]); 906 bcopy(digest, cp, toMove); 907 cp += toMove; 908 moved += toMove; 909 if(i == numDigests) { 910 i = 0; // wrap to 0, start padding 911 } 912 } 913 914finishUp: 915 /* 916 * Convert to giant, justify result to within [2, lesserX1Order] 917 */ 918 pkinst->privGiant = giant_with_data(privData, privLen); 919 920 #if FEE_DEBUG 921 if(isZero(pkinst->privGiant)) { 922 printf("feeGenPrivate: privData = 0!\n"); 923 } 924 #endif // FEE_DEBUG 925 926 lesserX1OrderJustify(pkinst->privGiant, pkinst->cp); 927 if(hashPasswd) { 928 memset(privData, 0, privLen); 929 ffree(privData); 930 for(i=0; i<numDigests; i++) { 931 feeHashFree(hash[i]); 932 } 933 ffree(hash); 934 } 935 return FR_Success; 936} 937 938#endif /* ECDSA_VERIFY_ONLY */ 939 940#if FEE_DEBUG 941 942void printPubKey(feePubKey pubKey) 943{ 944 pubKeyInst *pkinst = pubKey; 945 946 printf("\ncurveParams:\n"); 947 printCurveParams(pkinst->cp); 948 printf("plus:\n"); 949 printKey(pkinst->plus); 950 printf("minus:\n"); 951 printKey(pkinst->minus); 952 if(pkinst->privGiant != NULL) { 953 printf("privGiant : "); 954 printGiant(pkinst->privGiant); 955 } 956} 957 958#else // FEE_DEBUG 959void printPubKey(feePubKey pubKey) {} 960#endif // FEE_DEBUG 961 962/* 963 * Prime the curveParams and giants modules for quick allocs of giants. 964 */ 965#if GIANTS_VIA_STACK 966 967static int giantsInitd = 0; 968 969static void feePubKeyInitGiants(void) 970{ 971 if(giantsInitd) { 972 return; 973 } 974 curveParamsInitGiants(); 975 giantsInitd = 1; 976} 977#endif 978 979#pragma mark --- Native (custom) key blob formatting --- 980 981/* 982 * Exported key blob support. New, 23 Mar 1998. 983 * 984 * Convert to public or private key blob. 985 */ 986 987#ifndef ECDSA_VERIFY_ONLY 988 989/*** 990 *** Common native blob support 991 ***/ 992static feeReturn createKeyBlob(pubKeyInst *pkinst, 993 int isPrivate, // 0 : public 1 : private 994 unsigned char **keyBlob, // mallocd and RETURNED 995 unsigned *keyBlobLen) // RETURNED 996{ 997 unsigned char *s; // running ptr into *origS 998 unsigned sLen; 999 int magic; 1000 1001 /* common blob elements */ 1002 sLen = (4 * sizeof(int)) + // magic, version, minVersion, 1003 // spare 1004 lengthOfByteRepCurveParams(pkinst->cp); 1005 if(isPrivate) { 1006 /* private only */ 1007 sLen += lengthOfByteRepGiant(pkinst->privGiant); 1008 magic = PUBLIC_KEY_BLOB_MAGIC_PRIV; 1009 } 1010 else { 1011 /* public only */ 1012 sLen += (lengthOfByteRepKey(pkinst->plus) + 1013 lengthOfByteRepKey(pkinst->minus)); 1014 magic = PUBLIC_KEY_BLOB_MAGIC_PUB; 1015 } 1016 *keyBlob = s = (unsigned char*) fmalloc(sLen); 1017 s += intToByteRep(magic, s); 1018 s += intToByteRep(PUBLIC_KEY_BLOB_VERSION, s); 1019 s += intToByteRep(PUBLIC_KEY_BLOB_MINVERSION, s); 1020 s += intToByteRep(0, s); // spare 1021 s += curveParamsToByteRep(pkinst->cp, s); 1022 if(isPrivate) { 1023 s += giantToByteRep(pkinst->privGiant, s); 1024 } 1025 else { 1026 /* keyToByteRep writes y for plus curve only */ 1027 s += keyToByteRep(pkinst->plus, s); 1028 if(pkinst->minus != NULL) { 1029 s += keyToByteRep(pkinst->minus, s); 1030 } 1031 else { 1032 /* TBD */ 1033 dbgLog(("work needed here for blobs with no minus key\n")); 1034 } 1035 } 1036 *keyBlobLen = sLen; 1037 return FR_Success; 1038} 1039 1040#endif /* ECDSA_VERIFY_ONLY */ 1041 1042/* 1043 * Init an empty feePubKey from a native blob (non-DER format). 1044 */ 1045static feeReturn feePubKeyInitFromKeyBlob(feePubKey pubKey, 1046 unsigned char *keyBlob, 1047 unsigned keyBlobLen) 1048{ 1049 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1050 unsigned char *s; // running pointer 1051 unsigned sLen; // bytes remaining in *s 1052 int magic; 1053 unsigned len; // for length of individual components 1054 int minVersion; 1055 int version; 1056 int isPrivate; 1057 1058 s = keyBlob; 1059 sLen = keyBlobLen; 1060 if(sLen < (4 * sizeof(int))) { // magic, version, minVersion, spare 1061 /* 1062 * Too short for all the ints we need 1063 */ 1064 dbgLog(("feePublicKey: key blob (1)\n")); 1065 return FR_BadKeyBlob; 1066 } 1067 1068 magic = byteRepToInt(s); 1069 s += sizeof(int); 1070 sLen -= sizeof(int); 1071 switch(magic) { 1072 case PUBLIC_KEY_BLOB_MAGIC_PUB: 1073 isPrivate = 0; 1074 break; 1075 case PUBLIC_KEY_BLOB_MAGIC_PRIV: 1076 isPrivate = 1; 1077 break; 1078 default: 1079 dbgLog(("feePublicKey: Bad Public Key Magic Number\n")); 1080 return FR_BadKeyBlob; 1081 } 1082 1083 /* 1084 * Switch on this for version-specific cases 1085 */ 1086 version = byteRepToInt(s); 1087 s += sizeof(int); 1088 sLen -= sizeof(int); 1089 1090 minVersion = byteRepToInt(s); 1091 s += sizeof(int); 1092 sLen -= sizeof(int); 1093 if(minVersion > PUBLIC_KEY_BLOB_VERSION) { 1094 /* 1095 * old code, newer key blob - can't parse 1096 */ 1097 dbgLog(("feePublicKey: Incompatible Public Key (1)\n")); 1098 return FR_BadKeyBlob; 1099 } 1100 1101 s += sizeof(int); // skip spare 1102 sLen -= sizeof(int); 1103 1104 pkinst->cp = byteRepToCurveParams(s, sLen, &len); 1105 if(pkinst->cp == NULL) { 1106 dbgLog(("feePublicKey: Bad Key Blob(2)\n")); 1107 return FR_BadKeyBlob; 1108 } 1109 s += len; 1110 sLen -= len; 1111 1112 /* 1113 * Private key blob: privGiant. 1114 * Public Key blob: plusX, minusX, plusY. 1115 */ 1116 if(isPrivate) { 1117 pkinst->privGiant = byteRepToGiant(s, sLen, &len); 1118 if(pkinst->privGiant == NULL) { 1119 dbgLog(("feePublicKey: Bad Key Blob(3)\n")); 1120 return FR_BadKeyBlob; 1121 } 1122 s += len; 1123 sLen -= len; 1124 } 1125 else { 1126 /* this writes x and y */ 1127 pkinst->plus = byteRepToKey(s, 1128 sLen, 1129 CURVE_PLUS, // twist 1130 pkinst->cp, 1131 &len); 1132 if(pkinst->plus == NULL) { 1133 dbgLog(("feePublicKey: Bad Key Blob(4)\n")); 1134 return FR_BadKeyBlob; 1135 } 1136 s += len; 1137 sLen -= len; 1138 1139 /* this only writes x */ 1140 pkinst->minus = byteRepToKey(s, 1141 sLen, 1142 CURVE_MINUS, // twist 1143 pkinst->cp, 1144 &len); 1145 if(pkinst->minus == NULL) { 1146 dbgLog(("feePublicKey: Bad Key Blob(5)\n")); 1147 return FR_BadKeyBlob; 1148 } 1149 s += len; 1150 sLen -= len; 1151 } 1152 1153 /* 1154 * One more thing: cook up public plusX and minusX for private key 1155 * blob case. 1156 */ 1157 if(isPrivate) { 1158 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 1159 pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); 1160 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 1161 set_priv_key_giant(pkinst->minus, pkinst->privGiant); 1162 } 1163 return FR_Success; 1164 1165} 1166 1167feeReturn feePubKeyInitFromPubBlob(feePubKey pubKey, 1168 unsigned char *keyBlob, 1169 unsigned keyBlobLen) 1170{ 1171 return feePubKeyInitFromKeyBlob(pubKey, keyBlob, keyBlobLen); 1172} 1173 1174#ifndef ECDSA_VERIFY_ONLY 1175 1176feeReturn feePubKeyInitFromPrivBlob(feePubKey pubKey, 1177 unsigned char *keyBlob, 1178 unsigned keyBlobLen) 1179{ 1180 return feePubKeyInitFromKeyBlob(pubKey, keyBlob, keyBlobLen); 1181} 1182 1183#endif /* ECDSA_VERIFY_ONLY */ 1184 1185#if CRYPTKIT_DER_ENABLE 1186#ifndef ECDSA_VERIFY_ONLY 1187 1188/* 1189 * DER format support. 1190 * Obtain portable public and private DER-encoded key blobs from a key. 1191 */ 1192feeReturn feePubKeyCreateDERPubBlob(feePubKey pubKey, 1193 unsigned char **keyBlob, // mallocd and RETURNED 1194 unsigned *keyBlobLen) // RETURNED 1195{ 1196 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1197 1198 if(pkinst == NULL) { 1199 return FR_BadPubKey; 1200 } 1201 if(pkinst->minus == NULL) { 1202 /* Only ECDSA key formats supported */ 1203 return FR_IncompatibleKey; 1204 } 1205 return feeDEREncodePublicKey(PUBLIC_DER_KEY_BLOB_VERSION, 1206 pkinst->cp, 1207 pkinst->plus->x, 1208 pkinst->minus->x, 1209 isZero(pkinst->plus->y) ? NULL : pkinst->plus->y, 1210 keyBlob, 1211 keyBlobLen); 1212} 1213 1214feeReturn feePubKeyCreateDERPrivBlob(feePubKey pubKey, 1215 unsigned char **keyBlob, // mallocd and RETURNED 1216 unsigned *keyBlobLen) // RETURNED 1217{ 1218 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1219 1220 if(pkinst == NULL) { 1221 return FR_BadPubKey; 1222 } 1223 if(pkinst->privGiant == NULL) { 1224 return FR_IncompatibleKey; 1225 } 1226 if(pkinst->minus == NULL) { 1227 /* Only ECDSA key formats supported */ 1228 return FR_IncompatibleKey; 1229 } 1230 return feeDEREncodePrivateKey(PUBLIC_DER_KEY_BLOB_VERSION, 1231 pkinst->cp, 1232 pkinst->privGiant, 1233 keyBlob, 1234 keyBlobLen); 1235} 1236 1237#endif /* ECDSA_VERIFY_ONLY */ 1238 1239/* 1240 * Init an empty feePubKey from a DER-encoded blob, public and private key versions. 1241 */ 1242feeReturn feePubKeyInitFromDERPubBlob(feePubKey pubKey, 1243 unsigned char *keyBlob, 1244 size_t keyBlobLen) 1245{ 1246 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1247 feeReturn frtn; 1248 int version; 1249 1250 if(pkinst == NULL) { 1251 return FR_BadPubKey; 1252 } 1253 1254 /* kind of messy, maybe we should clean this up. But new_public() does too 1255 * much - e.g., it allocates the x and y which we really don't want */ 1256 memset(pkinst, 0, sizeof(pubKeyInst)); 1257 pkinst->plus = (key) fmalloc(sizeof(keystruct)); 1258 pkinst->minus = (key) fmalloc(sizeof(keystruct)); 1259 if((pkinst->plus == NULL) || (pkinst->minus == NULL)) { 1260 return FR_Memory; 1261 } 1262 memset(pkinst->plus, 0, sizeof(keystruct)); 1263 memset(pkinst->minus, 0, sizeof(keystruct)); 1264 pkinst->cp = NULL; 1265 pkinst->privGiant = NULL; 1266 pkinst->plus->twist = CURVE_PLUS; 1267 pkinst->minus->twist = CURVE_MINUS; 1268 frtn = feeDERDecodePublicKey(keyBlob, 1269 (unsigned)keyBlobLen, 1270 &version, // currently unused 1271 &pkinst->cp, 1272 &pkinst->plus->x, 1273 &pkinst->minus->x, 1274 &pkinst->plus->y); 1275 if(frtn) { 1276 return frtn; 1277 } 1278 /* minus curve, y is not used */ 1279 pkinst->minus->y = newGiant(1); 1280 int_to_giant(0, pkinst->minus->y); 1281 pkinst->plus->cp = pkinst->minus->cp = pkinst->cp; 1282 return FR_Success; 1283} 1284 1285#ifndef ECDSA_VERIFY_ONLY 1286 1287feeReturn feePubKeyInitFromDERPrivBlob(feePubKey pubKey, 1288 unsigned char *keyBlob, 1289 size_t keyBlobLen) 1290{ 1291 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1292 int version; 1293 feeReturn frtn; 1294 1295 if(pkinst == NULL) { 1296 return FR_BadPubKey; 1297 } 1298 memset(pkinst, 0, sizeof(pubKeyInst)); 1299 frtn = feeDERDecodePrivateKey(keyBlob, 1300 (unsigned)keyBlobLen, 1301 &version, // currently unused 1302 &pkinst->cp, 1303 &pkinst->privGiant); 1304 if(frtn) { 1305 return frtn; 1306 } 1307 1308 /* since this blob only had the private data, infer the remaining fields */ 1309 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 1310 pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); 1311 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 1312 set_priv_key_giant(pkinst->minus, pkinst->privGiant); 1313 return FR_Success; 1314} 1315 1316#endif /* ECDSA_VERIFY_ONLY */ 1317 1318#pragma mark --- X509 (public) and PKCS8 (private) key formatting --- 1319 1320feeReturn feePubKeyCreateX509Blob( 1321 feePubKey pubKey, // public key 1322 unsigned char **keyBlob, // mallocd and RETURNED 1323 unsigned *keyBlobLen) // RETURNED 1324{ 1325 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1326 unsigned char *xyStr = NULL; 1327 unsigned xyStrLen = 0; 1328 feeReturn frtn = feeCreateECDSAPubBlob(pubKey, &xyStr, &xyStrLen); 1329 if(frtn) { 1330 return frtn; 1331 } 1332 frtn = feeDEREncodeX509PublicKey(xyStr, xyStrLen, pkinst->cp, keyBlob, keyBlobLen); 1333 ffree(xyStr); 1334 return frtn; 1335} 1336 1337feeReturn feePubKeyCreatePKCS8Blob( 1338 feePubKey pubKey, // private key 1339 unsigned char **keyBlob, // mallocd and RETURNED 1340 unsigned *keyBlobLen) // RETURNED 1341{ 1342 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1343 unsigned char *privStr = NULL; 1344 unsigned privStrLen = 0; 1345 feeReturn frtn = feeCreateECDSAPrivBlob(pubKey, &privStr, &privStrLen); 1346 if(frtn) { 1347 return frtn; 1348 } 1349 unsigned char *pubStr = NULL; 1350 unsigned pubStrLen = 0; 1351 frtn = feeCreateECDSAPubBlob(pubKey, &pubStr, &pubStrLen); 1352 if(frtn) { 1353 goto errOut; 1354 } 1355 frtn = feeDEREncodePKCS8PrivateKey(privStr, privStrLen, 1356 pubStr, pubStrLen, 1357 pkinst->cp, keyBlob, keyBlobLen); 1358errOut: 1359 if(privStr) { 1360 ffree(privStr); 1361 } 1362 if(pubStr) { 1363 ffree(pubStr); 1364 } 1365 return frtn; 1366} 1367 1368feeReturn feePubKeyInitFromX509Blob( 1369 feePubKey pubKey, // public key 1370 unsigned char *keyBlob, 1371 size_t keyBlobLen) 1372{ 1373 feeDepth depth; 1374 unsigned char *xyStr = NULL; 1375 unsigned xyStrLen = 0; 1376 1377 /* obtain x/y and depth from X509 encoding */ 1378 feeReturn frtn = feeDERDecodeX509PublicKey(keyBlob, (unsigned)keyBlobLen, &depth, 1379 &xyStr, &xyStrLen); 1380 if(frtn) { 1381 return frtn; 1382 } 1383 1384 frtn = feePubKeyInitFromECDSAPubBlob(pubKey, xyStr, xyStrLen, depth); 1385 ffree(xyStr); 1386 return frtn; 1387} 1388 1389 1390feeReturn feePubKeyInitFromPKCS8Blob( 1391 feePubKey pubKey, // private key 1392 unsigned char *keyBlob, 1393 size_t keyBlobLen) 1394{ 1395 feeDepth depth; 1396 unsigned char *privStr = NULL; 1397 unsigned privStrLen = 0; 1398 1399 /* obtain x/y and depth from PKCS8 encoding */ 1400 /* For now we ignore the possible public key string */ 1401 feeReturn frtn = feeDERDecodePKCS8PrivateKey(keyBlob, (unsigned)keyBlobLen, &depth, 1402 &privStr, &privStrLen, NULL, NULL); 1403 if(frtn) { 1404 return frtn; 1405 } 1406 1407 frtn = feePubKeyInitFromECDSAPrivBlob(pubKey, privStr, privStrLen, depth); 1408 ffree(privStr); 1409 return frtn; 1410} 1411 1412#pragma mark --- OpenSSL key formatting --- 1413 1414/* 1415 * The native OpenSSL ECDSA key format contains both the private and public 1416 * components in one blob. This throws a bit of a monkey wrench into the API 1417 * here, as we only have one encoder - which requires a private key - and one 1418 * decoder, which can result in the decoding of either a public or a private 1419 * key. 1420 */ 1421feeReturn feePubKeyCreateOpenSSLBlob( 1422 feePubKey pubKey, // private key 1423 unsigned char **keyBlob, // mallocd and RETURNED 1424 unsigned *keyBlobLen) // RETURNED 1425{ 1426 pubKeyInst *pkinst = (pubKeyInst *) pubKey; 1427 unsigned char *privStr = NULL; 1428 unsigned privStrLen = 0; 1429 feeReturn frtn = feeCreateECDSAPrivBlob(pubKey, &privStr, &privStrLen); 1430 if(frtn) { 1431 return frtn; 1432 } 1433 unsigned char *pubStr = NULL; 1434 unsigned pubStrLen = 0; 1435 frtn = feeCreateECDSAPubBlob(pubKey, &pubStr, &pubStrLen); 1436 if(frtn) { 1437 goto errOut; 1438 } 1439 frtn = feeDEREncodeOpenSSLPrivateKey(privStr, privStrLen, 1440 pubStr, pubStrLen, 1441 pkinst->cp, keyBlob, keyBlobLen); 1442errOut: 1443 if(privStr) { 1444 ffree(privStr); 1445 } 1446 if(pubStr) { 1447 ffree(pubStr); 1448 } 1449 return frtn; 1450} 1451 1452feeReturn feePubKeyInitFromOpenSSLBlob( 1453 feePubKey pubKey, // private or public key 1454 int pubOnly, 1455 unsigned char *keyBlob, 1456 size_t keyBlobLen) 1457{ 1458 feeDepth depth; 1459 unsigned char *privStr = NULL; 1460 unsigned privStrLen = 0; 1461 unsigned char *pubStr = NULL; 1462 unsigned pubStrLen = 0; 1463 1464 /* obtain x/y, public bit string, and depth from PKCS8 encoding */ 1465 feeReturn frtn = feeDERDecodeOpenSSLKey(keyBlob, (unsigned)keyBlobLen, &depth, 1466 &privStr, &privStrLen, &pubStr, &pubStrLen); 1467 if(frtn) { 1468 return frtn; 1469 } 1470 1471 if(pubOnly) { 1472 frtn = feePubKeyInitFromECDSAPubBlob(pubKey, pubStr, pubStrLen, depth); 1473 } 1474 else { 1475 frtn = feePubKeyInitFromECDSAPrivBlob(pubKey, privStr, privStrLen, depth); 1476 } 1477 if(privStr) { 1478 ffree(privStr); 1479 } 1480 if(pubStr) { 1481 ffree(pubStr); 1482 } 1483 return frtn; 1484} 1485 1486#endif /* CRYPTKIT_DER_ENABLE */ 1487 1488/* 1489 * ANSI X9.62/Certicom key support. 1490 * Public key is 04 || x || y 1491 * Private key is privData per Certicom SEC1 C.4. 1492 */ 1493feeReturn feeCreateECDSAPubBlob(feePubKey pubKey, 1494 unsigned char **keyBlob, 1495 unsigned *keyBlobLen) 1496{ 1497 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1498 if(pkinst == NULL) { 1499 return FR_BadPubKey; 1500 } 1501 1502 unsigned giantBytes = (pkinst->cp->q + 7) / 8; 1503 unsigned blobSize = 1 + (2 * giantBytes); 1504 unsigned char *blob = fmalloc(blobSize); 1505 if(blob == NULL) { 1506 return FR_Memory; 1507 } 1508 *blob = 0x04; 1509 serializeGiant(pkinst->plus->x, blob+1, giantBytes); 1510 serializeGiant(pkinst->plus->y, blob+1+giantBytes, giantBytes); 1511 *keyBlob = blob; 1512 *keyBlobLen = blobSize; 1513 return FR_Success; 1514} 1515 1516feeReturn feeCreateECDSAPrivBlob(feePubKey pubKey, 1517 unsigned char **keyBlob, 1518 unsigned *keyBlobLen) 1519{ 1520 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1521 if(pkinst == NULL) { 1522 return FR_BadPubKey; 1523 } 1524 if(pkinst->privGiant == NULL) { 1525 return FR_IncompatibleKey; 1526 } 1527 1528 /* 1529 * Return the raw private key bytes padded with zeroes in 1530 * the m.s. end to fill exactly one prime-size byte array. 1531 */ 1532 unsigned giantBytes = (pkinst->cp->q + 7) / 8; 1533 unsigned char *blob = fmalloc(giantBytes); 1534 if(blob == NULL) { 1535 return FR_Memory; 1536 } 1537 serializeGiant(pkinst->privGiant, blob, giantBytes); 1538 *keyBlob = blob; 1539 *keyBlobLen = giantBytes; 1540 return FR_Success; 1541} 1542 1543/* Caller determines depth from other sources (e.g. AlgId.Params) */ 1544feeReturn feePubKeyInitFromECDSAPubBlob(feePubKey pubKey, 1545 const unsigned char *keyBlob, 1546 unsigned keyBlobLen, 1547 feeDepth depth) 1548{ 1549 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1550 if(pkinst == NULL) { 1551 return FR_BadPubKey; 1552 } 1553 curveParams *cp = curveParamsForDepth(depth); 1554 if(cp == NULL) { 1555 return FR_IllegalDepth; 1556 } 1557 unsigned giantBytes = (cp->q + 7) / 8; 1558 unsigned blobSize = 1 + (2 * giantBytes); 1559 if(keyBlobLen != blobSize) { 1560 dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blobLen\n")); 1561 return FR_BadKeyBlob; 1562 } 1563 if(*keyBlob != 0x04) { 1564 dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blob leader\n")); 1565 return FR_BadKeyBlob; 1566 } 1567 1568 pkinst->cp = cp; 1569 pkinst->plus = new_public(cp, CURVE_PLUS); 1570 deserializeGiant(keyBlob+1, pkinst->plus->x, giantBytes); 1571 deserializeGiant(keyBlob+1+giantBytes, pkinst->plus->y, giantBytes); 1572 return FR_Success; 1573} 1574 1575feeReturn feePubKeyInitFromECDSAPrivBlob(feePubKey pubKey, 1576 const unsigned char *keyBlob, 1577 unsigned keyBlobLen, 1578 feeDepth depth) 1579{ 1580 pubKeyInst *pkinst = (pubKeyInst *)pubKey; 1581 if(pkinst == NULL) { 1582 return FR_BadPubKey; 1583 } 1584 curveParams *cp = curveParamsForDepth(depth); 1585 if(cp == NULL) { 1586 return FR_IllegalDepth; 1587 } 1588 unsigned giantDigits = cp->basePrime->sign; 1589 unsigned giantBytes = (cp->q + 7) / 8; 1590 1591 /* 1592 * The specified private key can be one byte smaller than the modulus */ 1593 if((keyBlobLen > giantBytes) || (keyBlobLen < (giantBytes - 1))) { 1594 dbgLog(("feePubKeyInitFromECDSAPrivBlob: bad blobLen\n")); 1595 return FR_BadKeyBlob; 1596 } 1597 1598 pkinst->cp = cp; 1599 1600 /* cook up a new private giant */ 1601 pkinst->privGiant = newGiant(giantDigits); 1602 if(pkinst->privGiant == NULL) { 1603 return FR_Memory; 1604 } 1605 deserializeGiant(keyBlob, pkinst->privGiant, keyBlobLen); 1606 1607 /* since this blob only had the private data, infer the remaining fields */ 1608 pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); 1609 set_priv_key_giant(pkinst->plus, pkinst->privGiant); 1610 return FR_Success; 1611} 1612 1613