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
467 * Generate digital signature, ElGamal style.
469 feeReturn
feePubKeyCreateSignature(feePubKey pubKey
,
470 const unsigned char *data
,
472 unsigned char **signature
, /* fmalloc'd and RETURNED */
473 unsigned *signatureLen
) /* RETURNED */
475 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
478 unsigned char *Pm
= NULL
;
482 if(pkinst
->privGiant
== NULL
) {
483 dbgLog(("feePubKeyCreateSignature: Attempt to Sign without"
487 hash
= feeHashAlloc();
488 sig
= feeSigNewWithKey(pubKey
, NULL
, NULL
);
491 * Shouldn't happen, but...
498 * Get Pm to salt hash object
500 Pm
= feeSigPm(sig
, &PmLen
);
501 feeHashAddData(hash
, Pm
, PmLen
);
504 * Now hash the data proper, then sign the hash
506 feeHashAddData(hash
, data
, dataLen
);
507 frtn
= feeSigSign(sig
,
511 if(frtn
== FR_Success
) {
512 frtn
= feeSigData(sig
, signature
, signatureLen
);
521 * Verify digital signature, ElGamal style. If the signature is ECDSA,
522 * we'll use that format for compatibility.
524 feeReturn
feePubKeyVerifySignature(feePubKey pubKey
,
525 const unsigned char *data
,
527 const unsigned char *signature
,
528 unsigned signatureLen
)
532 unsigned char *Pm
= NULL
;
536 hash
= feeHashAlloc();
537 frtn
= feeSigParse(signature
, signatureLen
, &sig
);
540 #if CRYPTKIT_ECDSA_ENABLE
541 if(frtn
== FR_WrongSignatureType
) {
542 return feePubKeyVerifyECDSASignature(pubKey
,
548 #endif /* CRYPTKIT_ECDSA_ENABLE */
553 * Get PM as salt; eat salt, then hash data
555 Pm
= feeSigPm(sig
, &PmLen
);
556 feeHashAddData(hash
, Pm
, PmLen
);
557 feeHashAddData(hash
, data
, dataLen
);
558 frtn
= feeSigVerify(sig
,
569 #pragma mark --- ECDSA signature: high level routines ---
571 #if CRYPTKIT_ECDSA_ENABLE
573 * Generate digital signature, ECDSA style.
575 feeReturn
feePubKeyCreateECDSASignature(feePubKey pubKey
,
576 const unsigned char *data
,
578 unsigned char **signature
, /* fmalloc'd and RETURNED */
579 unsigned *signatureLen
) /* RETURNED */
581 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
585 if(pkinst
->privGiant
== NULL
) {
586 dbgLog(("feePubKeyCreateECDSASignature: Attempt to Sign "
587 "without private data\n"));
591 sha1AddData(sha1
, data
, dataLen
);
592 frtn
= feeECDSASign(pubKey
,
602 #endif /* CRYPTKIT_ECDSA_ENABLE */
603 #endif /* ECDSA_VERIFY_ONLY */
605 #if CRYPTKIT_ECDSA_ENABLE
608 * Verify digital signature, ECDSA style.
610 feeReturn
feePubKeyVerifyECDSASignature(feePubKey pubKey
,
611 const unsigned char *data
,
613 const unsigned char *signature
,
614 unsigned signatureLen
)
620 sha1AddData(sha1
, data
, dataLen
);
621 frtn
= feeECDSAVerify(signature
,
630 #endif /* CRYPTKIT_ECDSA_ENABLE */
632 #endif /* CRYPTKIT_HIGH_LEVEL_SIG */
634 #pragma mark --- ECDH ---
637 * Diffie-Hellman. Public key is specified either as a feePubKey or
638 * a ANSI X9.62 format public key string (0x04 | x | y). In either case
639 * the caller must ensure that the two keys are on the same curve.
640 * Output data is fmalloc'd here; caller must free. Output data is
641 * exactly the size of the curve's modulus in bytes.
643 feeReturn
feePubKeyECDH(
645 /* one of the following two is non-NULL */
647 const unsigned char *pubKeyStr
,
648 unsigned pubKeyStrLen
,
649 /* output fmallocd and RETURNED here */
650 unsigned char **output
,
653 feePubKey theirPub
= pubKey
;
654 feeReturn frtn
= FR_Success
;
655 pubKeyInst
*privInst
= (pubKeyInst
*) privKey
;
657 if(privInst
->privGiant
== NULL
) {
658 dbgLog(("feePubKeyECDH: privKey not a private key\n"));
659 return FR_IncompatibleKey
;
662 if(theirPub
== NULL
) {
663 if(pubKeyStr
== NULL
) {
664 return FR_IllegalArg
;
667 /* Cook up a public key with the same curveParams as the private key */
669 frtn
= curveParamsDepth(privInst
->cp
, &depth
);
673 theirPub
= feePubKeyAlloc();
674 if(theirPub
== NULL
) {
677 frtn
= feePubKeyInitFromECDSAPubBlob(theirPub
, pubKeyStr
, pubKeyStrLen
, depth
);
683 pubKeyInst
*pubInst
= (pubKeyInst
*) theirPub
;
685 giant outputGiant
= make_pad(privInst
->privGiant
, pubInst
->plus
);
686 if(outputGiant
== NULL
) {
687 dbgLog(("feePubKeyECDH: make_pad error\n"));
691 *outputLen
= (privInst
->cp
->q
+ 7) / 8;
692 *output
= (unsigned char *)fmalloc(*outputLen
);
693 if(*output
== NULL
) {
697 serializeGiant(outputGiant
, *output
, *outputLen
);
698 freeGiant(outputGiant
);
701 if((pubKey
== NULL
) && (theirPub
!= NULL
)) {
702 feePubKeyFree(theirPub
);
707 #pragma mark --- feePubKey data accessors ---
709 unsigned feePubKeyBitsize(feePubKey pubKey
)
711 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
712 switch(pkinst
->cp
->primeType
) {
713 case FPT_General
: /* cp->q is here for just this purpose */
715 return pkinst
->cp
->q
;
716 case FPT_FEE
: /* could be larger or smaller than 2^q-1 */
718 return bitlen(pkinst
->cp
->basePrime
);
728 key
feePubKeyPlusCurve(feePubKey pubKey
)
730 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
735 key
feePubKeyMinusCurve(feePubKey pubKey
)
737 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
739 return pkinst
->minus
;
742 curveParams
*feePubKeyCurveParams(feePubKey pubKey
)
744 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
749 giant
feePubKeyPrivData(feePubKey pubKey
)
751 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
753 return pkinst
->privGiant
;
756 const char *feePubKeyAlgorithmName(void)
758 return "Elliptic Curve - FEE by Apple Computer";
761 #pragma mark --- Private functions ---
764 * alloc, free pubKeyInst
766 static pubKeyInst
*pubKeyInstAlloc(void)
768 pubKeyInst
*pkinst
= (pubKeyInst
*) fmalloc(sizeof(pubKeyInst
));
770 bzero(pkinst
, sizeof(pubKeyInst
));
774 static void pubKeyInstFree(pubKeyInst
*pkinst
)
777 free_key(pkinst
->minus
);
780 free_key(pkinst
->plus
);
783 freeCurveParams(pkinst
->cp
);
785 if(pkinst
->privGiant
) {
787 * Zero out the private data...
789 clearGiant(pkinst
->privGiant
);
790 freeGiant(pkinst
->privGiant
);
795 #ifndef ECDSA_VERIFY_ONLY
798 * Create a pubKeyInst.privGiant given a password of
800 * Currently, the only error is "private data too short" (FR_IllegalArg).
803 #define NO_PRIV_MUNGE 0 /* skip this step */
805 static feeReturn
feeGenPrivate(pubKeyInst
*pkinst
,
806 const unsigned char *passwd
,
810 unsigned privLen
; // desired size of pkinst->privData
811 feeHash
*hash
= NULL
; // a malloc'd array
812 unsigned digestLen
; // size of MD5 digest
813 unsigned dataSize
; // min(privLen, passwdLen)
814 unsigned numDigests
= 0;
817 unsigned toMove
; // for this digest
818 unsigned moved
; // total digested
819 unsigned char *digest
= NULL
;
820 unsigned char *privData
= NULL
; // temp, before modg(curveOrder)
821 giant corder
; // lesser of two curve orders
824 * generate privData which is just larger than the smaller
826 * We'll take the result mod the curve order when we're done.
827 * Note we do *not* have to free corder - it's a pointer to a giant
830 corder
= lesserX1Order(pkinst
->cp
);
831 CKASSERT(!isZero(corder
));
832 privLen
= (bitlen(corder
) / 8) + 1;
836 * Caller trusts the incoming entropy. Verify it's big enough and proceed.
838 if(passwdLen
< privLen
) {
839 return FR_ShortPrivData
;
842 privData
= (unsigned char *)passwd
;
846 return FR_IllegalArg
;
851 * Calculate how many MD5 digests we'll generate.
853 if(privLen
> passwdLen
) {
854 dataSize
= passwdLen
;
859 digestLen
= feeHashDigestLen();
860 numDigests
= (dataSize
+ digestLen
- 1) / digestLen
;
862 hash
= (void**) fmalloc(numDigests
* sizeof(feeHash
));
863 for(i
=0; i
<numDigests
; i
++) {
864 hash
[i
] = feeHashAlloc();
868 * fill digests with passwd data, digestLen (or resid length)
869 * at a time. If (passwdLen > privLen), last digest will hash all
870 * remaining passwd data.
872 cp
= (unsigned char *)passwd
;
874 for(i
=0; i
<numDigests
; i
++) {
875 if(i
== (numDigests
- 1)) { // last digest
876 toMove
= passwdLen
- moved
;
881 feeHashAddData(hash
[i
], cp
, toMove
);
887 * copy digests to privData, up to privLen bytes. Pad with
888 * additional copies of digests if necessary.
890 privData
= (unsigned char*) fmalloc(privLen
);
893 i
= 0; // digest number
894 for(moved
=0; moved
<privLen
; ) {
895 if((moved
+ digestLen
) > privLen
) {
896 toMove
= privLen
- moved
;
901 digest
= feeHashDigest(hash
[i
++]);
902 bcopy(digest
, cp
, toMove
);
905 if(i
== numDigests
) {
906 i
= 0; // wrap to 0, start padding
912 * Convert to giant, justify result to within [2, lesserX1Order]
914 pkinst
->privGiant
= giant_with_data(privData
, privLen
);
917 if(isZero(pkinst
->privGiant
)) {
918 printf("feeGenPrivate: privData = 0!\n");
922 lesserX1OrderJustify(pkinst
->privGiant
, pkinst
->cp
);
924 memset(privData
, 0, privLen
);
926 for(i
=0; i
<numDigests
; i
++) {
927 feeHashFree(hash
[i
]);
934 #endif /* ECDSA_VERIFY_ONLY */
938 void printPubKey(feePubKey pubKey
)
940 pubKeyInst
*pkinst
= pubKey
;
942 printf("\ncurveParams:\n");
943 printCurveParams(pkinst
->cp
);
945 printKey(pkinst
->plus
);
947 printKey(pkinst
->minus
);
948 if(pkinst
->privGiant
!= NULL
) {
949 printf("privGiant : ");
950 printGiant(pkinst
->privGiant
);
955 void printPubKey(feePubKey pubKey
) {}
959 * Prime the curveParams and giants modules for quick allocs of giants.
963 static int giantsInitd
= 0;
965 static void feePubKeyInitGiants(void)
970 curveParamsInitGiants();
975 #pragma mark --- Native (custom) key blob formatting ---
978 * Exported key blob support. New, 23 Mar 1998.
980 * Convert to public or private key blob.
983 #ifndef ECDSA_VERIFY_ONLY
986 *** Common native blob support
988 static feeReturn
createKeyBlob(pubKeyInst
*pkinst
,
989 int isPrivate
, // 0 : public 1 : private
990 unsigned char **keyBlob
, // mallocd and RETURNED
991 unsigned *keyBlobLen
) // RETURNED
993 unsigned char *s
; // running ptr into *origS
997 /* common blob elements */
998 sLen
= (4 * sizeof(int)) + // magic, version, minVersion,
1000 lengthOfByteRepCurveParams(pkinst
->cp
);
1003 sLen
+= lengthOfByteRepGiant(pkinst
->privGiant
);
1004 magic
= PUBLIC_KEY_BLOB_MAGIC_PRIV
;
1008 sLen
+= (lengthOfByteRepKey(pkinst
->plus
) +
1009 lengthOfByteRepKey(pkinst
->minus
));
1010 magic
= PUBLIC_KEY_BLOB_MAGIC_PUB
;
1012 *keyBlob
= s
= (unsigned char*) fmalloc(sLen
);
1013 s
+= intToByteRep(magic
, s
);
1014 s
+= intToByteRep(PUBLIC_KEY_BLOB_VERSION
, s
);
1015 s
+= intToByteRep(PUBLIC_KEY_BLOB_MINVERSION
, s
);
1016 s
+= intToByteRep(0, s
); // spare
1017 s
+= curveParamsToByteRep(pkinst
->cp
, s
);
1019 s
+= giantToByteRep(pkinst
->privGiant
, s
);
1022 /* keyToByteRep writes y for plus curve only */
1023 s
+= keyToByteRep(pkinst
->plus
, s
);
1024 if(pkinst
->minus
!= NULL
) {
1025 s
+= keyToByteRep(pkinst
->minus
, s
);
1029 dbgLog(("work needed here for blobs with no minus key\n"));
1036 #endif /* ECDSA_VERIFY_ONLY */
1039 * Init an empty feePubKey from a native blob (non-DER format).
1041 static feeReturn
feePubKeyInitFromKeyBlob(feePubKey pubKey
,
1042 unsigned char *keyBlob
,
1043 unsigned keyBlobLen
)
1045 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1046 unsigned char *s
; // running pointer
1047 unsigned sLen
; // bytes remaining in *s
1049 unsigned len
; // for length of individual components
1056 if(sLen
< (4 * sizeof(int))) { // magic, version, minVersion, spare
1058 * Too short for all the ints we need
1060 dbgLog(("feePublicKey: key blob (1)\n"));
1061 return FR_BadKeyBlob
;
1064 magic
= byteRepToInt(s
);
1066 sLen
-= sizeof(int);
1068 case PUBLIC_KEY_BLOB_MAGIC_PUB
:
1071 case PUBLIC_KEY_BLOB_MAGIC_PRIV
:
1075 dbgLog(("feePublicKey: Bad Public Key Magic Number\n"));
1076 return FR_BadKeyBlob
;
1080 * Switch on this for version-specific cases
1082 version
= byteRepToInt(s
);
1084 sLen
-= sizeof(int);
1086 minVersion
= byteRepToInt(s
);
1088 sLen
-= sizeof(int);
1089 if(minVersion
> PUBLIC_KEY_BLOB_VERSION
) {
1091 * old code, newer key blob - can't parse
1093 dbgLog(("feePublicKey: Incompatible Public Key (1)\n"));
1094 return FR_BadKeyBlob
;
1097 s
+= sizeof(int); // skip spare
1098 sLen
-= sizeof(int);
1100 pkinst
->cp
= byteRepToCurveParams(s
, sLen
, &len
);
1101 if(pkinst
->cp
== NULL
) {
1102 dbgLog(("feePublicKey: Bad Key Blob(2)\n"));
1103 return FR_BadKeyBlob
;
1109 * Private key blob: privGiant.
1110 * Public Key blob: plusX, minusX, plusY.
1113 pkinst
->privGiant
= byteRepToGiant(s
, sLen
, &len
);
1114 if(pkinst
->privGiant
== NULL
) {
1115 dbgLog(("feePublicKey: Bad Key Blob(3)\n"));
1116 return FR_BadKeyBlob
;
1122 /* this writes x and y */
1123 pkinst
->plus
= byteRepToKey(s
,
1125 CURVE_PLUS
, // twist
1128 if(pkinst
->plus
== NULL
) {
1129 dbgLog(("feePublicKey: Bad Key Blob(4)\n"));
1130 return FR_BadKeyBlob
;
1135 /* this only writes x */
1136 pkinst
->minus
= byteRepToKey(s
,
1138 CURVE_MINUS
, // twist
1141 if(pkinst
->minus
== NULL
) {
1142 dbgLog(("feePublicKey: Bad Key Blob(5)\n"));
1143 return FR_BadKeyBlob
;
1150 * One more thing: cook up public plusX and minusX for private key
1154 pkinst
->plus
= new_public(pkinst
->cp
, CURVE_PLUS
);
1155 pkinst
->minus
= new_public(pkinst
->cp
, CURVE_MINUS
);
1156 set_priv_key_giant(pkinst
->plus
, pkinst
->privGiant
);
1157 set_priv_key_giant(pkinst
->minus
, pkinst
->privGiant
);
1163 feeReturn
feePubKeyInitFromPubBlob(feePubKey pubKey
,
1164 unsigned char *keyBlob
,
1165 unsigned keyBlobLen
)
1167 return feePubKeyInitFromKeyBlob(pubKey
, keyBlob
, keyBlobLen
);
1170 #ifndef ECDSA_VERIFY_ONLY
1172 feeReturn
feePubKeyInitFromPrivBlob(feePubKey pubKey
,
1173 unsigned char *keyBlob
,
1174 unsigned keyBlobLen
)
1176 return feePubKeyInitFromKeyBlob(pubKey
, keyBlob
, keyBlobLen
);
1179 #endif /* ECDSA_VERIFY_ONLY */
1181 #if CRYPTKIT_DER_ENABLE
1182 #ifndef ECDSA_VERIFY_ONLY
1185 * DER format support.
1186 * Obtain portable public and private DER-encoded key blobs from a key.
1188 feeReturn
feePubKeyCreateDERPubBlob(feePubKey pubKey
,
1189 unsigned char **keyBlob
, // mallocd and RETURNED
1190 unsigned *keyBlobLen
) // RETURNED
1192 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1194 if(pkinst
== NULL
) {
1195 return FR_BadPubKey
;
1197 if(pkinst
->minus
== NULL
) {
1198 /* Only ECDSA key formats supported */
1199 return FR_IncompatibleKey
;
1201 return feeDEREncodePublicKey(PUBLIC_DER_KEY_BLOB_VERSION
,
1205 isZero(pkinst
->plus
->y
) ? NULL
: pkinst
->plus
->y
,
1210 feeReturn
feePubKeyCreateDERPrivBlob(feePubKey pubKey
,
1211 unsigned char **keyBlob
, // mallocd and RETURNED
1212 unsigned *keyBlobLen
) // RETURNED
1214 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1216 if(pkinst
== NULL
) {
1217 return FR_BadPubKey
;
1219 if(pkinst
->privGiant
== NULL
) {
1220 return FR_IncompatibleKey
;
1222 if(pkinst
->minus
== NULL
) {
1223 /* Only ECDSA key formats supported */
1224 return FR_IncompatibleKey
;
1226 return feeDEREncodePrivateKey(PUBLIC_DER_KEY_BLOB_VERSION
,
1233 #endif /* ECDSA_VERIFY_ONLY */
1236 * Init an empty feePubKey from a DER-encoded blob, public and private key versions.
1238 feeReturn
feePubKeyInitFromDERPubBlob(feePubKey pubKey
,
1239 unsigned char *keyBlob
,
1242 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1246 if(pkinst
== NULL
) {
1247 return FR_BadPubKey
;
1250 /* kind of messy, maybe we should clean this up. But new_public() does too
1251 * much - e.g., it allocates the x and y which we really don't want */
1252 memset(pkinst
, 0, sizeof(pubKeyInst
));
1253 pkinst
->plus
= (key
) fmalloc(sizeof(keystruct
));
1254 pkinst
->minus
= (key
) fmalloc(sizeof(keystruct
));
1255 if((pkinst
->plus
== NULL
) || (pkinst
->minus
== NULL
)) {
1258 memset(pkinst
->plus
, 0, sizeof(keystruct
));
1259 memset(pkinst
->minus
, 0, sizeof(keystruct
));
1261 pkinst
->privGiant
= NULL
;
1262 pkinst
->plus
->twist
= CURVE_PLUS
;
1263 pkinst
->minus
->twist
= CURVE_MINUS
;
1264 frtn
= feeDERDecodePublicKey(keyBlob
,
1266 &version
, // currently unused
1274 /* minus curve, y is not used */
1275 pkinst
->minus
->y
= newGiant(1);
1276 int_to_giant(0, pkinst
->minus
->y
);
1277 pkinst
->plus
->cp
= pkinst
->minus
->cp
= pkinst
->cp
;
1281 #ifndef ECDSA_VERIFY_ONLY
1283 feeReturn
feePubKeyInitFromDERPrivBlob(feePubKey pubKey
,
1284 unsigned char *keyBlob
,
1287 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1291 if(pkinst
== NULL
) {
1292 return FR_BadPubKey
;
1294 memset(pkinst
, 0, sizeof(pubKeyInst
));
1295 frtn
= feeDERDecodePrivateKey(keyBlob
,
1297 &version
, // currently unused
1299 &pkinst
->privGiant
);
1304 /* since this blob only had the private data, infer the remaining fields */
1305 pkinst
->plus
= new_public(pkinst
->cp
, CURVE_PLUS
);
1306 pkinst
->minus
= new_public(pkinst
->cp
, CURVE_MINUS
);
1307 set_priv_key_giant(pkinst
->plus
, pkinst
->privGiant
);
1308 set_priv_key_giant(pkinst
->minus
, pkinst
->privGiant
);
1312 #endif /* ECDSA_VERIFY_ONLY */
1314 #pragma mark --- X509 (public) and PKCS8 (private) key formatting ---
1316 feeReturn
feePubKeyCreateX509Blob(
1317 feePubKey pubKey
, // public key
1318 unsigned char **keyBlob
, // mallocd and RETURNED
1319 unsigned *keyBlobLen
) // RETURNED
1321 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1322 unsigned char *xyStr
= NULL
;
1323 unsigned xyStrLen
= 0;
1324 feeReturn frtn
= feeCreateECDSAPubBlob(pubKey
, &xyStr
, &xyStrLen
);
1328 frtn
= feeDEREncodeX509PublicKey(xyStr
, xyStrLen
, pkinst
->cp
, keyBlob
, keyBlobLen
);
1333 feeReturn
feePubKeyCreatePKCS8Blob(
1334 feePubKey pubKey
, // private key
1335 unsigned char **keyBlob
, // mallocd and RETURNED
1336 unsigned *keyBlobLen
) // RETURNED
1338 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1339 unsigned char *privStr
= NULL
;
1340 unsigned privStrLen
= 0;
1341 feeReturn frtn
= feeCreateECDSAPrivBlob(pubKey
, &privStr
, &privStrLen
);
1345 unsigned char *pubStr
= NULL
;
1346 unsigned pubStrLen
= 0;
1347 frtn
= feeCreateECDSAPubBlob(pubKey
, &pubStr
, &pubStrLen
);
1351 frtn
= feeDEREncodePKCS8PrivateKey(privStr
, privStrLen
,
1353 pkinst
->cp
, keyBlob
, keyBlobLen
);
1364 feeReturn
feePubKeyInitFromX509Blob(
1365 feePubKey pubKey
, // public key
1366 unsigned char *keyBlob
,
1370 unsigned char *xyStr
= NULL
;
1371 unsigned xyStrLen
= 0;
1373 /* obtain x/y and depth from X509 encoding */
1374 feeReturn frtn
= feeDERDecodeX509PublicKey(keyBlob
, keyBlobLen
, &depth
,
1380 frtn
= feePubKeyInitFromECDSAPubBlob(pubKey
, xyStr
, xyStrLen
, depth
);
1386 feeReturn
feePubKeyInitFromPKCS8Blob(
1387 feePubKey pubKey
, // private key
1388 unsigned char *keyBlob
,
1392 unsigned char *privStr
= NULL
;
1393 unsigned privStrLen
= 0;
1395 /* obtain x/y and depth from PKCS8 encoding */
1396 /* For now we ignore the possible public key string */
1397 feeReturn frtn
= feeDERDecodePKCS8PrivateKey(keyBlob
, keyBlobLen
, &depth
,
1398 &privStr
, &privStrLen
, NULL
, NULL
);
1403 frtn
= feePubKeyInitFromECDSAPrivBlob(pubKey
, privStr
, privStrLen
, depth
);
1408 #pragma mark --- OpenSSL key formatting ---
1411 * The native OpenSSL ECDSA key format contains both the private and public
1412 * components in one blob. This throws a bit of a monkey wrench into the API
1413 * here, as we only have one encoder - which requires a private key - and one
1414 * decoder, which can result in the decoding of either a public or a private
1417 feeReturn
feePubKeyCreateOpenSSLBlob(
1418 feePubKey pubKey
, // private key
1419 unsigned char **keyBlob
, // mallocd and RETURNED
1420 unsigned *keyBlobLen
) // RETURNED
1422 pubKeyInst
*pkinst
= (pubKeyInst
*) pubKey
;
1423 unsigned char *privStr
= NULL
;
1424 unsigned privStrLen
= 0;
1425 feeReturn frtn
= feeCreateECDSAPrivBlob(pubKey
, &privStr
, &privStrLen
);
1429 unsigned char *pubStr
= NULL
;
1430 unsigned pubStrLen
= 0;
1431 frtn
= feeCreateECDSAPubBlob(pubKey
, &pubStr
, &pubStrLen
);
1435 frtn
= feeDEREncodeOpenSSLPrivateKey(privStr
, privStrLen
,
1437 pkinst
->cp
, keyBlob
, keyBlobLen
);
1448 feeReturn
feePubKeyInitFromOpenSSLBlob(
1449 feePubKey pubKey
, // private or public key
1451 unsigned char *keyBlob
,
1455 unsigned char *privStr
= NULL
;
1456 unsigned privStrLen
= 0;
1457 unsigned char *pubStr
= NULL
;
1458 unsigned pubStrLen
= 0;
1460 /* obtain x/y, public bit string, and depth from PKCS8 encoding */
1461 feeReturn frtn
= feeDERDecodeOpenSSLKey(keyBlob
, keyBlobLen
, &depth
,
1462 &privStr
, &privStrLen
, &pubStr
, &pubStrLen
);
1468 frtn
= feePubKeyInitFromECDSAPubBlob(pubKey
, pubStr
, pubStrLen
, depth
);
1471 frtn
= feePubKeyInitFromECDSAPrivBlob(pubKey
, privStr
, privStrLen
, depth
);
1482 #endif /* CRYPTKIT_DER_ENABLE */
1485 * ANSI X9.62/Certicom key support.
1486 * Public key is 04 || x || y
1487 * Private key is privData per Certicom SEC1 C.4.
1489 feeReturn
feeCreateECDSAPubBlob(feePubKey pubKey
,
1490 unsigned char **keyBlob
,
1491 unsigned *keyBlobLen
)
1493 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1494 if(pkinst
== NULL
) {
1495 return FR_BadPubKey
;
1498 unsigned giantBytes
= (pkinst
->cp
->q
+ 7) / 8;
1499 unsigned blobSize
= 1 + (2 * giantBytes
);
1500 unsigned char *blob
= fmalloc(blobSize
);
1505 serializeGiant(pkinst
->plus
->x
, blob
+1, giantBytes
);
1506 serializeGiant(pkinst
->plus
->y
, blob
+1+giantBytes
, giantBytes
);
1508 *keyBlobLen
= blobSize
;
1512 feeReturn
feeCreateECDSAPrivBlob(feePubKey pubKey
,
1513 unsigned char **keyBlob
,
1514 unsigned *keyBlobLen
)
1516 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1517 if(pkinst
== NULL
) {
1518 return FR_BadPubKey
;
1520 if(pkinst
->privGiant
== NULL
) {
1521 return FR_IncompatibleKey
;
1525 * Return the raw private key bytes padded with zeroes in
1526 * the m.s. end to fill exactly one prime-size byte array.
1528 unsigned giantBytes
= (pkinst
->cp
->q
+ 7) / 8;
1529 unsigned char *blob
= fmalloc(giantBytes
);
1533 serializeGiant(pkinst
->privGiant
, blob
, giantBytes
);
1535 *keyBlobLen
= giantBytes
;
1539 /* Caller determines depth from other sources (e.g. AlgId.Params) */
1540 feeReturn
feePubKeyInitFromECDSAPubBlob(feePubKey pubKey
,
1541 const unsigned char *keyBlob
,
1542 unsigned keyBlobLen
,
1545 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1546 if(pkinst
== NULL
) {
1547 return FR_BadPubKey
;
1549 curveParams
*cp
= curveParamsForDepth(depth
);
1551 return FR_IllegalDepth
;
1553 unsigned giantBytes
= (cp
->q
+ 7) / 8;
1554 unsigned blobSize
= 1 + (2 * giantBytes
);
1555 if(keyBlobLen
!= blobSize
) {
1556 dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blobLen\n"));
1557 return FR_BadKeyBlob
;
1559 if(*keyBlob
!= 0x04) {
1560 dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blob leader\n"));
1561 return FR_BadKeyBlob
;
1565 pkinst
->plus
= new_public(cp
, CURVE_PLUS
);
1566 deserializeGiant(keyBlob
+1, pkinst
->plus
->x
, giantBytes
);
1567 deserializeGiant(keyBlob
+1+giantBytes
, pkinst
->plus
->y
, giantBytes
);
1571 feeReturn
feePubKeyInitFromECDSAPrivBlob(feePubKey pubKey
,
1572 const unsigned char *keyBlob
,
1573 unsigned keyBlobLen
,
1576 pubKeyInst
*pkinst
= (pubKeyInst
*)pubKey
;
1577 if(pkinst
== NULL
) {
1578 return FR_BadPubKey
;
1580 curveParams
*cp
= curveParamsForDepth(depth
);
1582 return FR_IllegalDepth
;
1584 unsigned giantDigits
= cp
->basePrime
->sign
;
1585 unsigned giantBytes
= (cp
->q
+ 7) / 8;
1588 * The specified private key can be one byte smaller than the modulus */
1589 if((keyBlobLen
> giantBytes
) || (keyBlobLen
< (giantBytes
- 1))) {
1590 dbgLog(("feePubKeyInitFromECDSAPrivBlob: bad blobLen\n"));
1591 return FR_BadKeyBlob
;
1596 /* cook up a new private giant */
1597 pkinst
->privGiant
= newGiant(giantDigits
);
1598 if(pkinst
->privGiant
== NULL
) {
1601 deserializeGiant(keyBlob
, pkinst
->privGiant
, keyBlobLen
);
1603 /* since this blob only had the private data, infer the remaining fields */
1604 pkinst
->plus
= new_public(pkinst
->cp
, CURVE_PLUS
);
1605 set_priv_key_giant(pkinst
->plus
, pkinst
->privGiant
);