1 /* Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
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 COMPUTER, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
11 * feePublicKey.c - Portable FEE public key object.
16 * Added ECDSA_VERIFY_ONLY dependencies.
18 * Changed to compile with C++.
19 * 9 Sep 98 Doug Mitchell at NeXT
20 * Major changes for IEEE P1363 compliance.
21 * 23 Mar 98 Doug Mitchell at Apple
23 * 21 Jan 98 Doug Mitchell at Apple
24 * Fixed feePubKeyBitsize bitlen bug for PT_GENERAL case.
25 * 05 Jan 98 Doug Mitchell at Apple
26 * ECDSA now uses SHA-1 hash. Imcompatible with old ECDSA signatures.
27 * 17 Jul 97 Doug Mitchell at Apple
28 * Added ECDSA signature routines.
29 * 12 Jun 97 Doug Mitchell at Apple
30 * Added feePubKeyInitGiants()
31 * Deleted obsolete code
32 * Changes for lesserX1OrderJustify (was curveOrderJustify)
33 * 31 Mar 97 Doug Mitchell at Apple
34 * Fixed leak in feePubKeyCreateKeyString()
35 * 15 Jan 97 Doug Mitchell at NeXT
36 * PUBLIC_KEY_STRING_VERSION = 3; broke compatibility with all older
38 * Cleaned up which_curve/index code to use CURVE_MINUS/CURVE_PLUS.
39 * 12 Dec 96 Doug Mitchell at NeXT
40 * Added initFromEnc64KeyStr().
41 * 20 Aug 96 Doug Mitchell at NeXT
43 * ???? 1994 Blaine Garst at NeXT
48 #include "feePublicKey.h"
49 #include "feePublicKeyPrivate.h"
50 #include "ckutilities.h"
51 #include "giantIntegers.h"
53 #include "curveParams.h"
59 #include "feeDigitalSignature.h"
65 #if CRYPTKIT_DER_ENABLE
66 #include "CryptKitDER.h"
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.
77 #define NULL ((void *)0)
81 * Magic number for a portable key blobs. Must be in sync with static
82 * final PUBLIC_KEY_STRING_MAGIC in JavaFee/PublicKey.java.
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
89 #if CRYPTKIT_DER_ENABLE
90 #define PUBLIC_DER_KEY_BLOB_VERSION 1
94 * Private data. All "instance" routines are passed a feePubKey (actually
95 * a void *) which is actually a pointer to one of these.
99 key minus
; // not needed for ECDSA
100 curveParams
*cp
; // common params shared by minus, plus
101 giant privGiant
; // private key
104 static feeReturn
feeGenPrivate(pubKeyInst
*pkinst
,
105 const unsigned char *passwd
,
108 static pubKeyInst
*pubKeyInstAlloc(void);
109 static void pubKeyInstFree(pubKeyInst
*pkinst
);
111 static void feePubKeyInitGiants(void);
113 static feeReturn
createKeyBlob(pubKeyInst
*pkinst
,
114 int isPrivate
, // 0 : public 1 : private
115 unsigned char **keyBlob
, // mallocd and RETURNED
116 unsigned *keyBlobLen
); // RETURNED
117 static feeReturn
feePubKeyInitFromKeyBlob(feePubKey pubKey
,
118 unsigned char *keyBlob
,
119 unsigned keyBlobLen
);
121 #pragma mark --- General public API function ---
124 * Obatin a newly allocated feePubKey.
126 feePubKey
feePubKeyAlloc(void)
128 pubKeyInst
*pkinst
= pubKeyInstAlloc();
131 feePubKeyInitGiants();
136 void feePubKeyFree(feePubKey pubKey
)
138 pubKeyInstFree((pubKeyInst
*) pubKey
);
141 #ifndef ECDSA_VERIFY_ONLY
143 * Init feePubKey from private key data.
145 feeReturn
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" */
156 frtn
= feeKeyBitsToDepth(keyBits
, primeType
, curveType
, &depth
);
160 return feePubKeyInitFromPrivDataDepth(pubKey
,
167 feeReturn
feePubKeyInitFromPrivDataDepth(feePubKey pubKey
,
168 const unsigned char *privData
,
169 unsigned privDataLen
,
173 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
177 if(depth
!= FEE_DEPTH_127_1
) {
178 dbgLog(("Illegal Depth\n"));
179 return FR_IllegalDepth
;
181 #endif // ENGINE_127_BITS
182 if(depth
> FEE_DEPTH_MAX
) {
183 dbgLog(("Illegal Depth\n"));
184 return FR_IllegalDepth
;
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
);
192 /* else only usable for ECDSA */
194 frtn
= feeGenPrivate(pkinst
, privData
, privDataLen
, hashPrivData
);
198 set_priv_key_giant(pkinst
->plus
, pkinst
->privGiant
);
199 if(pkinst
->cp
->x1Minus
!= NULL
) {
200 set_priv_key_giant(pkinst
->minus
, pkinst
->privGiant
);
205 #endif /* ECDSA_VERIFY_ONLY */
208 * Init feePubKey from curve parameters matching existing oldKey.
210 feeReturn
feePubKeyInitFromKey(feePubKey pubKey
,
211 const unsigned char *privData
,
212 unsigned privDataLen
,
216 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
217 pubKeyInst
*oldInst
= (pubKeyInst
*) oldKey
;
221 dbgLog(("NULL existing key\n"));
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
) {
232 /* else this curve only usable for ECDSA */
234 pkinst
->plus
= new_public(pkinst
->cp
, CURVE_PLUS
);
235 if(pkinst
->plus
== NULL
) {
238 frtn
= feeGenPrivate(pkinst
, privData
, privDataLen
, hashPrivData
);
242 set_priv_key_giant(pkinst
->plus
, pkinst
->privGiant
);
243 if(pkinst
->cp
->x1Minus
!= NULL
) {
244 set_priv_key_giant(pkinst
->minus
, pkinst
->privGiant
);
249 dbgLog(("Bad Existing Public Key\n"));
254 *** Public KeyString support.
257 * Init feePubKey from a public key string.
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.
262 feeReturn
feePubKeyInitFromKeyString(feePubKey pubKey
,
266 unsigned char *blob
= NULL
;
270 blob
= dec64((unsigned char *)keyStr
, keyStrLen
, &blobLen
);
272 dbgLog(("Bad Public Key String (not enc64)\n"));
273 return FR_BadPubKeyString
;
275 frtn
= feePubKeyInitFromKeyBlob(pubKey
, blob
, blobLen
);
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
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.
288 feeReturn
feePubKeyCreateKeyString(feePubKey pubKey
,
289 char **pubKeyString
, /* RETURNED */
290 unsigned *pubKeyStringLen
) /* RETURNED */
295 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
297 /* get binary pub blob, encode the blob, free the blob */
298 frtn
= createKeyBlob(pkinst
,
306 *pubKeyString
= (char *)enc64(blob
, blobLen
, pubKeyStringLen
);
312 *** Native key blob support.
315 #ifndef ECDSA_VERIFY_ONLY
318 * Obtain portable public and private key blobs from a key.
320 feeReturn
feePubKeyCreatePubBlob(feePubKey pubKey
,
321 unsigned char **keyBlob
, // mallocd and RETURNED
322 unsigned *keyBlobLen
) // RETURNED
324 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
326 return createKeyBlob(pkinst
,
332 feeReturn
feePubKeyCreatePrivBlob(feePubKey pubKey
,
333 unsigned char **keyBlob
, // mallocd and RETURNED
334 unsigned *keyBlobLen
) // RETURNED
336 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
338 if(pkinst
->privGiant
== NULL
) {
339 return FR_IncompatibleKey
;
341 return createKeyBlob(pkinst
,
348 * Given private-capable privKey, initialize pubKey to be its corresponding
351 feeReturn
feePubKeyInitPubKeyFromPriv(feePubKey privKey
,
354 pubKeyInst
*privInst
= (pubKeyInst
*)privKey
;
355 pubKeyInst
*pubInst
= (pubKeyInst
*)pubKey
;
357 if((privInst
== NULL
) || (pubInst
== NULL
)) {
360 if(privInst
->privGiant
== NULL
) {
361 return FR_IncompatibleKey
;
363 pubInst
->cp
= curveParamsCopy(privInst
->cp
);
364 if(pubInst
== NULL
) {
367 pubInst
->plus
= new_public_with_key(privInst
->plus
, pubInst
->cp
);
368 if(pubInst
->plus
== NULL
) {
371 if(pubInst
->cp
->x1Minus
!= NULL
) {
372 pubInst
->minus
= new_public_with_key(privInst
->minus
, pubInst
->cp
);
373 if(pubInst
->minus
== NULL
) {
380 #endif /* ECDSA_VERIFY_ONLY */
383 * Returns non-zero if two keys are equivalent.
385 int feePubKeyIsEqual(feePubKey key1
, feePubKey key2
)
387 pubKeyInst
*pkinst1
= (pubKeyInst
*) key1
;
388 pubKeyInst
*pkinst2
= (pubKeyInst
*) key2
;
390 if ((pkinst1
== NULL
) || (pkinst2
== NULL
)) {
393 if((pkinst1
->minus
!= NULL
) && (pkinst2
->minus
!= NULL
)) {
394 if(key_equal(pkinst1
->minus
, pkinst2
->minus
) == 0) {
398 if(key_equal(pkinst1
->plus
, pkinst2
->plus
) == 0) {
405 * Returns non-zero if key is private-capable (i.e., capable of signing
408 int feePubKeyIsPrivate(feePubKey key
)
410 pubKeyInst
*myPkinst
= (pubKeyInst
*)key
;
412 return ((myPkinst
->privGiant
!= NULL
) ? 1 : 0);
415 #ifndef ECDSA_VERIFY_ONLY
417 #if CRYPTKIT_KEY_EXCHANGE
419 feeReturn
feePubKeyCreatePad(feePubKey myKey
,
421 unsigned char **padData
, /* RETURNED */
422 unsigned *padDataLen
) /* RETURNED padData length in bytes */
424 pubKeyInst
*myPkinst
= (pubKeyInst
*) myKey
;
425 pubKeyInst
*theirPkinst
= (pubKeyInst
*) theirKey
;
427 unsigned char *result
;
432 * Do some compatibility checking (myKey, theirKey) here...?
434 if(DEFAULT_CURVE
== CURVE_PLUS
) {
435 pkey
= theirPkinst
->plus
;
438 pkey
= theirPkinst
->minus
;
440 pad
= make_pad(myPkinst
->privGiant
, pkey
);
441 result
= mem_from_giant(pad
, &padLen
);
445 * Ensure we have a the minimum necessary for DES. A bit of a hack,
448 if(padLen
>= FEE_DES_MIN_STATE_SIZE
) {
450 *padDataLen
= padLen
;
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
);
462 #endif /* CRYPTKIT_KEY_EXCHANGE */
464 #if CRYPTKIT_HIGH_LEVEL_SIG
468 * Generate digital signature, ElGamal style.
470 feeReturn
feePubKeyCreateSignature(feePubKey pubKey
,
471 const unsigned char *data
,
473 unsigned char **signature
, /* fmalloc'd and RETURNED */
474 unsigned *signatureLen
) /* RETURNED */
476 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
479 unsigned char *Pm
= NULL
;
483 if(pkinst
->privGiant
== NULL
) {
484 dbgLog(("feePubKeyCreateSignature: Attempt to Sign without"
488 hash
= feeHashAlloc();
489 sig
= feeSigNewWithKey(pubKey
, NULL
, NULL
);
492 * Shouldn't happen, but...
499 * Get Pm to salt hash object
501 Pm
= feeSigPm(sig
, &PmLen
);
502 feeHashAddData(hash
, Pm
, PmLen
);
505 * Now hash the data proper, then sign the hash
507 feeHashAddData(hash
, data
, dataLen
);
508 frtn
= feeSigSign(sig
,
512 if(frtn
== FR_Success
) {
513 frtn
= feeSigData(sig
, signature
, signatureLen
);
522 * Verify digital signature, ElGamal style. If the signature is ECDSA,
523 * we'll use that format for compatibility.
525 feeReturn
feePubKeyVerifySignature(feePubKey pubKey
,
526 const unsigned char *data
,
528 const unsigned char *signature
,
529 unsigned signatureLen
)
533 unsigned char *Pm
= NULL
;
537 hash
= feeHashAlloc();
538 frtn
= feeSigParse(signature
, signatureLen
, &sig
);
541 #if CRYPTKIT_ECDSA_ENABLE
542 if(frtn
== FR_WrongSignatureType
) {
543 return feePubKeyVerifyECDSASignature(pubKey
,
549 #endif /* CRYPTKIT_ECDSA_ENABLE */
554 * Get PM as salt; eat salt, then hash data
556 Pm
= feeSigPm(sig
, &PmLen
);
557 feeHashAddData(hash
, Pm
, PmLen
);
558 feeHashAddData(hash
, data
, dataLen
);
559 frtn
= feeSigVerify(sig
,
570 #pragma mark --- ECDSA signature: high level routines ---
572 #if CRYPTKIT_ECDSA_ENABLE
574 * Generate digital signature, ECDSA style.
576 feeReturn
feePubKeyCreateECDSASignature(feePubKey pubKey
,
577 const unsigned char *data
,
579 unsigned char **signature
, /* fmalloc'd and RETURNED */
580 unsigned *signatureLen
) /* RETURNED */
582 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
586 if(pkinst
->privGiant
== NULL
) {
587 dbgLog(("feePubKeyCreateECDSASignature: Attempt to Sign "
588 "without private data\n"));
592 sha1AddData(sha1
, data
, dataLen
);
593 frtn
= feeECDSASign(pubKey
,
603 #endif /* CRYPTKIT_ECDSA_ENABLE */
604 #endif /* CRYPTKIT_HIGH_LEVEL_SIG */
605 #endif /* ECDSA_VERIFY_ONLY */
607 #if CRYPTKIT_HIGH_LEVEL_SIG
609 #if CRYPTKIT_ECDSA_ENABLE
612 * Verify digital signature, ECDSA style.
614 feeReturn
feePubKeyVerifyECDSASignature(feePubKey pubKey
,
615 const unsigned char *data
,
617 const unsigned char *signature
,
618 unsigned signatureLen
)
624 sha1AddData(sha1
, data
, dataLen
);
625 frtn
= feeECDSAVerify(signature
,
634 #endif /* CRYPTKIT_ECDSA_ENABLE */
636 #endif /* CRYPTKIT_HIGH_LEVEL_SIG */
638 #pragma mark --- ECDH ---
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.
647 feeReturn
feePubKeyECDH(
649 /* one of the following two is non-NULL */
651 const unsigned char *pubKeyStr
,
652 unsigned pubKeyStrLen
,
653 /* output fmallocd and RETURNED here */
654 unsigned char **output
,
657 feePubKey theirPub
= pubKey
;
658 feeReturn frtn
= FR_Success
;
659 pubKeyInst
*privInst
= (pubKeyInst
*) privKey
;
661 if(privInst
->privGiant
== NULL
) {
662 dbgLog(("feePubKeyECDH: privKey not a private key\n"));
663 return FR_IncompatibleKey
;
666 if(theirPub
== NULL
) {
667 if(pubKeyStr
== NULL
) {
668 return FR_IllegalArg
;
671 /* Cook up a public key with the same curveParams as the private key */
673 frtn
= curveParamsDepth(privInst
->cp
, &depth
);
677 theirPub
= feePubKeyAlloc();
678 if(theirPub
== NULL
) {
681 frtn
= feePubKeyInitFromECDSAPubBlob(theirPub
, pubKeyStr
, pubKeyStrLen
, depth
);
687 pubKeyInst
*pubInst
= (pubKeyInst
*) theirPub
;
689 giant outputGiant
= make_pad(privInst
->privGiant
, pubInst
->plus
);
690 if(outputGiant
== NULL
) {
691 dbgLog(("feePubKeyECDH: make_pad error\n"));
695 *outputLen
= (privInst
->cp
->q
+ 7) / 8;
696 *output
= (unsigned char *)fmalloc(*outputLen
);
697 if(*output
== NULL
) {
701 serializeGiant(outputGiant
, *output
, *outputLen
);
702 freeGiant(outputGiant
);
705 if((pubKey
== NULL
) && (theirPub
!= NULL
)) {
706 feePubKeyFree(theirPub
);
711 #pragma mark --- feePubKey data accessors ---
713 unsigned feePubKeyBitsize(feePubKey pubKey
)
715 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
716 switch(pkinst
->cp
->primeType
) {
717 case FPT_General
: /* cp->q is here for just this purpose */
719 return pkinst
->cp
->q
;
720 case FPT_FEE
: /* could be larger or smaller than 2^q-1 */
722 return bitlen(pkinst
->cp
->basePrime
);
732 key
feePubKeyPlusCurve(feePubKey pubKey
)
734 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
739 key
feePubKeyMinusCurve(feePubKey pubKey
)
741 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
743 return pkinst
->minus
;
746 curveParams
*feePubKeyCurveParams(feePubKey pubKey
)
748 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
753 giant
feePubKeyPrivData(feePubKey pubKey
)
755 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
757 return pkinst
->privGiant
;
760 const char *feePubKeyAlgorithmName(void)
762 return "Elliptic Curve - FEE by Apple Computer";
765 #pragma mark --- Private functions ---
768 * alloc, free pubKeyInst
770 static pubKeyInst
*pubKeyInstAlloc(void)
772 pubKeyInst
*pkinst
= (pubKeyInst
*) fmalloc(sizeof(pubKeyInst
));
774 bzero(pkinst
, sizeof(pubKeyInst
));
778 static void pubKeyInstFree(pubKeyInst
*pkinst
)
781 free_key(pkinst
->minus
);
784 free_key(pkinst
->plus
);
787 freeCurveParams(pkinst
->cp
);
789 if(pkinst
->privGiant
) {
791 * Zero out the private data...
793 clearGiant(pkinst
->privGiant
);
794 freeGiant(pkinst
->privGiant
);
799 #ifndef ECDSA_VERIFY_ONLY
802 * Create a pubKeyInst.privGiant given a password of
804 * Currently, the only error is "private data too short" (FR_IllegalArg).
807 #define NO_PRIV_MUNGE 0 /* skip this step */
809 static feeReturn
feeGenPrivate(pubKeyInst
*pkinst
,
810 const unsigned char *passwd
,
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;
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
828 * generate privData which is just larger than the smaller
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
834 corder
= lesserX1Order(pkinst
->cp
);
835 CKASSERT(!isZero(corder
));
836 privLen
= (bitlen(corder
) / 8) + 1;
840 * Caller trusts the incoming entropy. Verify it's big enough and proceed.
842 if(passwdLen
< privLen
) {
843 return FR_ShortPrivData
;
846 privData
= (unsigned char *)passwd
;
850 return FR_IllegalArg
;
855 * Calculate how many MD5 digests we'll generate.
857 if(privLen
> passwdLen
) {
858 dataSize
= passwdLen
;
863 digestLen
= feeHashDigestLen();
864 numDigests
= (dataSize
+ digestLen
- 1) / digestLen
;
866 hash
= (void**) fmalloc(numDigests
* sizeof(feeHash
));
867 for(i
=0; i
<numDigests
; i
++) {
868 hash
[i
] = feeHashAlloc();
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.
876 cp
= (unsigned char *)passwd
;
878 for(i
=0; i
<numDigests
; i
++) {
879 if(i
== (numDigests
- 1)) { // last digest
880 toMove
= passwdLen
- moved
;
885 feeHashAddData(hash
[i
], cp
, toMove
);
891 * copy digests to privData, up to privLen bytes. Pad with
892 * additional copies of digests if necessary.
894 privData
= (unsigned char*) fmalloc(privLen
);
897 i
= 0; // digest number
898 for(moved
=0; moved
<privLen
; ) {
899 if((moved
+ digestLen
) > privLen
) {
900 toMove
= privLen
- moved
;
905 digest
= feeHashDigest(hash
[i
++]);
906 bcopy(digest
, cp
, toMove
);
909 if(i
== numDigests
) {
910 i
= 0; // wrap to 0, start padding
916 * Convert to giant, justify result to within [2, lesserX1Order]
918 pkinst
->privGiant
= giant_with_data(privData
, privLen
);
921 if(isZero(pkinst
->privGiant
)) {
922 printf("feeGenPrivate: privData = 0!\n");
926 lesserX1OrderJustify(pkinst
->privGiant
, pkinst
->cp
);
928 memset(privData
, 0, privLen
);
930 for(i
=0; i
<numDigests
; i
++) {
931 feeHashFree(hash
[i
]);
938 #endif /* ECDSA_VERIFY_ONLY */
942 void printPubKey(feePubKey pubKey
)
944 pubKeyInst
*pkinst
= pubKey
;
946 printf("\ncurveParams:\n");
947 printCurveParams(pkinst
->cp
);
949 printKey(pkinst
->plus
);
951 printKey(pkinst
->minus
);
952 if(pkinst
->privGiant
!= NULL
) {
953 printf("privGiant : ");
954 printGiant(pkinst
->privGiant
);
959 void printPubKey(feePubKey pubKey
) {}
963 * Prime the curveParams and giants modules for quick allocs of giants.
967 static int giantsInitd
= 0;
969 static void feePubKeyInitGiants(void)
974 curveParamsInitGiants();
979 #pragma mark --- Native (custom) key blob formatting ---
982 * Exported key blob support. New, 23 Mar 1998.
984 * Convert to public or private key blob.
987 #ifndef ECDSA_VERIFY_ONLY
990 *** Common native blob support
992 static feeReturn
createKeyBlob(pubKeyInst
*pkinst
,
993 int isPrivate
, // 0 : public 1 : private
994 unsigned char **keyBlob
, // mallocd and RETURNED
995 unsigned *keyBlobLen
) // RETURNED
997 unsigned char *s
; // running ptr into *origS
1001 /* common blob elements */
1002 sLen
= (4 * sizeof(int)) + // magic, version, minVersion,
1004 lengthOfByteRepCurveParams(pkinst
->cp
);
1007 sLen
+= lengthOfByteRepGiant(pkinst
->privGiant
);
1008 magic
= PUBLIC_KEY_BLOB_MAGIC_PRIV
;
1012 sLen
+= (lengthOfByteRepKey(pkinst
->plus
) +
1013 lengthOfByteRepKey(pkinst
->minus
));
1014 magic
= PUBLIC_KEY_BLOB_MAGIC_PUB
;
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
);
1023 s
+= giantToByteRep(pkinst
->privGiant
, s
);
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
);
1033 dbgLog(("work needed here for blobs with no minus key\n"));
1040 #endif /* ECDSA_VERIFY_ONLY */
1043 * Init an empty feePubKey from a native blob (non-DER format).
1045 static feeReturn
feePubKeyInitFromKeyBlob(feePubKey pubKey
,
1046 unsigned char *keyBlob
,
1047 unsigned keyBlobLen
)
1049 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1050 unsigned char *s
; // running pointer
1051 unsigned sLen
; // bytes remaining in *s
1053 unsigned len
; // for length of individual components
1060 if(sLen
< (4 * sizeof(int))) { // magic, version, minVersion, spare
1062 * Too short for all the ints we need
1064 dbgLog(("feePublicKey: key blob (1)\n"));
1065 return FR_BadKeyBlob
;
1068 magic
= byteRepToInt(s
);
1070 sLen
-= sizeof(int);
1072 case PUBLIC_KEY_BLOB_MAGIC_PUB
:
1075 case PUBLIC_KEY_BLOB_MAGIC_PRIV
:
1079 dbgLog(("feePublicKey: Bad Public Key Magic Number\n"));
1080 return FR_BadKeyBlob
;
1084 * Switch on this for version-specific cases
1086 version
= byteRepToInt(s
);
1088 sLen
-= sizeof(int);
1090 minVersion
= byteRepToInt(s
);
1092 sLen
-= sizeof(int);
1093 if(minVersion
> PUBLIC_KEY_BLOB_VERSION
) {
1095 * old code, newer key blob - can't parse
1097 dbgLog(("feePublicKey: Incompatible Public Key (1)\n"));
1098 return FR_BadKeyBlob
;
1101 s
+= sizeof(int); // skip spare
1102 sLen
-= sizeof(int);
1104 pkinst
->cp
= byteRepToCurveParams(s
, sLen
, &len
);
1105 if(pkinst
->cp
== NULL
) {
1106 dbgLog(("feePublicKey: Bad Key Blob(2)\n"));
1107 return FR_BadKeyBlob
;
1113 * Private key blob: privGiant.
1114 * Public Key blob: plusX, minusX, plusY.
1117 pkinst
->privGiant
= byteRepToGiant(s
, sLen
, &len
);
1118 if(pkinst
->privGiant
== NULL
) {
1119 dbgLog(("feePublicKey: Bad Key Blob(3)\n"));
1120 return FR_BadKeyBlob
;
1126 /* this writes x and y */
1127 pkinst
->plus
= byteRepToKey(s
,
1129 CURVE_PLUS
, // twist
1132 if(pkinst
->plus
== NULL
) {
1133 dbgLog(("feePublicKey: Bad Key Blob(4)\n"));
1134 return FR_BadKeyBlob
;
1139 /* this only writes x */
1140 pkinst
->minus
= byteRepToKey(s
,
1142 CURVE_MINUS
, // twist
1145 if(pkinst
->minus
== NULL
) {
1146 dbgLog(("feePublicKey: Bad Key Blob(5)\n"));
1147 return FR_BadKeyBlob
;
1154 * One more thing: cook up public plusX and minusX for private key
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
);
1167 feeReturn
feePubKeyInitFromPubBlob(feePubKey pubKey
,
1168 unsigned char *keyBlob
,
1169 unsigned keyBlobLen
)
1171 return feePubKeyInitFromKeyBlob(pubKey
, keyBlob
, keyBlobLen
);
1174 #ifndef ECDSA_VERIFY_ONLY
1176 feeReturn
feePubKeyInitFromPrivBlob(feePubKey pubKey
,
1177 unsigned char *keyBlob
,
1178 unsigned keyBlobLen
)
1180 return feePubKeyInitFromKeyBlob(pubKey
, keyBlob
, keyBlobLen
);
1183 #endif /* ECDSA_VERIFY_ONLY */
1185 #if CRYPTKIT_DER_ENABLE
1186 #ifndef ECDSA_VERIFY_ONLY
1189 * DER format support.
1190 * Obtain portable public and private DER-encoded key blobs from a key.
1192 feeReturn
feePubKeyCreateDERPubBlob(feePubKey pubKey
,
1193 unsigned char **keyBlob
, // mallocd and RETURNED
1194 unsigned *keyBlobLen
) // RETURNED
1196 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1198 if(pkinst
== NULL
) {
1199 return FR_BadPubKey
;
1201 if(pkinst
->minus
== NULL
) {
1202 /* Only ECDSA key formats supported */
1203 return FR_IncompatibleKey
;
1205 return feeDEREncodePublicKey(PUBLIC_DER_KEY_BLOB_VERSION
,
1209 isZero(pkinst
->plus
->y
) ? NULL
: pkinst
->plus
->y
,
1214 feeReturn
feePubKeyCreateDERPrivBlob(feePubKey pubKey
,
1215 unsigned char **keyBlob
, // mallocd and RETURNED
1216 unsigned *keyBlobLen
) // RETURNED
1218 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1220 if(pkinst
== NULL
) {
1221 return FR_BadPubKey
;
1223 if(pkinst
->privGiant
== NULL
) {
1224 return FR_IncompatibleKey
;
1226 if(pkinst
->minus
== NULL
) {
1227 /* Only ECDSA key formats supported */
1228 return FR_IncompatibleKey
;
1230 return feeDEREncodePrivateKey(PUBLIC_DER_KEY_BLOB_VERSION
,
1237 #endif /* ECDSA_VERIFY_ONLY */
1240 * Init an empty feePubKey from a DER-encoded blob, public and private key versions.
1242 feeReturn
feePubKeyInitFromDERPubBlob(feePubKey pubKey
,
1243 unsigned char *keyBlob
,
1246 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1250 if(pkinst
== NULL
) {
1251 return FR_BadPubKey
;
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
)) {
1262 memset(pkinst
->plus
, 0, sizeof(keystruct
));
1263 memset(pkinst
->minus
, 0, sizeof(keystruct
));
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
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
;
1285 #ifndef ECDSA_VERIFY_ONLY
1287 feeReturn
feePubKeyInitFromDERPrivBlob(feePubKey pubKey
,
1288 unsigned char *keyBlob
,
1291 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1295 if(pkinst
== NULL
) {
1296 return FR_BadPubKey
;
1298 memset(pkinst
, 0, sizeof(pubKeyInst
));
1299 frtn
= feeDERDecodePrivateKey(keyBlob
,
1300 (unsigned)keyBlobLen
,
1301 &version
, // currently unused
1303 &pkinst
->privGiant
);
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
);
1316 #endif /* ECDSA_VERIFY_ONLY */
1318 #pragma mark --- X509 (public) and PKCS8 (private) key formatting ---
1320 feeReturn
feePubKeyCreateX509Blob(
1321 feePubKey pubKey
, // public key
1322 unsigned char **keyBlob
, // mallocd and RETURNED
1323 unsigned *keyBlobLen
) // RETURNED
1325 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1326 unsigned char *xyStr
= NULL
;
1327 unsigned xyStrLen
= 0;
1328 feeReturn frtn
= feeCreateECDSAPubBlob(pubKey
, &xyStr
, &xyStrLen
);
1332 frtn
= feeDEREncodeX509PublicKey(xyStr
, xyStrLen
, pkinst
->cp
, keyBlob
, keyBlobLen
);
1337 feeReturn
feePubKeyCreatePKCS8Blob(
1338 feePubKey pubKey
, // private key
1339 unsigned char **keyBlob
, // mallocd and RETURNED
1340 unsigned *keyBlobLen
) // RETURNED
1342 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1343 unsigned char *privStr
= NULL
;
1344 unsigned privStrLen
= 0;
1345 feeReturn frtn
= feeCreateECDSAPrivBlob(pubKey
, &privStr
, &privStrLen
);
1349 unsigned char *pubStr
= NULL
;
1350 unsigned pubStrLen
= 0;
1351 frtn
= feeCreateECDSAPubBlob(pubKey
, &pubStr
, &pubStrLen
);
1355 frtn
= feeDEREncodePKCS8PrivateKey(privStr
, privStrLen
,
1357 pkinst
->cp
, keyBlob
, keyBlobLen
);
1368 feeReturn
feePubKeyInitFromX509Blob(
1369 feePubKey pubKey
, // public key
1370 unsigned char *keyBlob
,
1374 unsigned char *xyStr
= NULL
;
1375 unsigned xyStrLen
= 0;
1377 /* obtain x/y and depth from X509 encoding */
1378 feeReturn frtn
= feeDERDecodeX509PublicKey(keyBlob
, (unsigned)keyBlobLen
, &depth
,
1384 frtn
= feePubKeyInitFromECDSAPubBlob(pubKey
, xyStr
, xyStrLen
, depth
);
1390 feeReturn
feePubKeyInitFromPKCS8Blob(
1391 feePubKey pubKey
, // private key
1392 unsigned char *keyBlob
,
1396 unsigned char *privStr
= NULL
;
1397 unsigned privStrLen
= 0;
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
);
1407 frtn
= feePubKeyInitFromECDSAPrivBlob(pubKey
, privStr
, privStrLen
, depth
);
1412 #pragma mark --- OpenSSL key formatting ---
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
1421 feeReturn
feePubKeyCreateOpenSSLBlob(
1422 feePubKey pubKey
, // private key
1423 unsigned char **keyBlob
, // mallocd and RETURNED
1424 unsigned *keyBlobLen
) // RETURNED
1426 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1427 unsigned char *privStr
= NULL
;
1428 unsigned privStrLen
= 0;
1429 feeReturn frtn
= feeCreateECDSAPrivBlob(pubKey
, &privStr
, &privStrLen
);
1433 unsigned char *pubStr
= NULL
;
1434 unsigned pubStrLen
= 0;
1435 frtn
= feeCreateECDSAPubBlob(pubKey
, &pubStr
, &pubStrLen
);
1439 frtn
= feeDEREncodeOpenSSLPrivateKey(privStr
, privStrLen
,
1441 pkinst
->cp
, keyBlob
, keyBlobLen
);
1452 feeReturn
feePubKeyInitFromOpenSSLBlob(
1453 feePubKey pubKey
, // private or public key
1455 unsigned char *keyBlob
,
1459 unsigned char *privStr
= NULL
;
1460 unsigned privStrLen
= 0;
1461 unsigned char *pubStr
= NULL
;
1462 unsigned pubStrLen
= 0;
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
);
1472 frtn
= feePubKeyInitFromECDSAPubBlob(pubKey
, pubStr
, pubStrLen
, depth
);
1475 frtn
= feePubKeyInitFromECDSAPrivBlob(pubKey
, privStr
, privStrLen
, depth
);
1486 #endif /* CRYPTKIT_DER_ENABLE */
1489 * ANSI X9.62/Certicom key support.
1490 * Public key is 04 || x || y
1491 * Private key is privData per Certicom SEC1 C.4.
1493 feeReturn
feeCreateECDSAPubBlob(feePubKey pubKey
,
1494 unsigned char **keyBlob
,
1495 unsigned *keyBlobLen
)
1497 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1498 if(pkinst
== NULL
) {
1499 return FR_BadPubKey
;
1502 unsigned giantBytes
= (pkinst
->cp
->q
+ 7) / 8;
1503 unsigned blobSize
= 1 + (2 * giantBytes
);
1504 unsigned char *blob
= fmalloc(blobSize
);
1509 serializeGiant(pkinst
->plus
->x
, blob
+1, giantBytes
);
1510 serializeGiant(pkinst
->plus
->y
, blob
+1+giantBytes
, giantBytes
);
1512 *keyBlobLen
= blobSize
;
1516 feeReturn
feeCreateECDSAPrivBlob(feePubKey pubKey
,
1517 unsigned char **keyBlob
,
1518 unsigned *keyBlobLen
)
1520 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1521 if(pkinst
== NULL
) {
1522 return FR_BadPubKey
;
1524 if(pkinst
->privGiant
== NULL
) {
1525 return FR_IncompatibleKey
;
1529 * Return the raw private key bytes padded with zeroes in
1530 * the m.s. end to fill exactly one prime-size byte array.
1532 unsigned giantBytes
= (pkinst
->cp
->q
+ 7) / 8;
1533 unsigned char *blob
= fmalloc(giantBytes
);
1537 serializeGiant(pkinst
->privGiant
, blob
, giantBytes
);
1539 *keyBlobLen
= giantBytes
;
1543 /* Caller determines depth from other sources (e.g. AlgId.Params) */
1544 feeReturn
feePubKeyInitFromECDSAPubBlob(feePubKey pubKey
,
1545 const unsigned char *keyBlob
,
1546 unsigned keyBlobLen
,
1549 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1550 if(pkinst
== NULL
) {
1551 return FR_BadPubKey
;
1553 curveParams
*cp
= curveParamsForDepth(depth
);
1555 return FR_IllegalDepth
;
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
;
1563 if(*keyBlob
!= 0x04) {
1564 dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blob leader\n"));
1565 return FR_BadKeyBlob
;
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
);
1575 feeReturn
feePubKeyInitFromECDSAPrivBlob(feePubKey pubKey
,
1576 const unsigned char *keyBlob
,
1577 unsigned keyBlobLen
,
1580 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1581 if(pkinst
== NULL
) {
1582 return FR_BadPubKey
;
1584 curveParams
*cp
= curveParamsForDepth(depth
);
1586 return FR_IllegalDepth
;
1588 unsigned giantDigits
= cp
->basePrime
->sign
;
1589 unsigned giantBytes
= (cp
->q
+ 7) / 8;
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
;
1600 /* cook up a new private giant */
1601 pkinst
->privGiant
= newGiant(giantDigits
);
1602 if(pkinst
->privGiant
== NULL
) {
1605 deserializeGiant(keyBlob
, pkinst
->privGiant
, keyBlobLen
);
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
);