[Patch] [LTC] ECC <= 112
- From: Nils Durner <ndr@xxxxxxxxxxxxxxxx>
- Date: Wed, 28 Jun 2006 15:02:02 GMT
Hi,
as I am not aware of a mailing list for LibTomCrypt, I post my patches here.
ecc112.diff:
adds support for ECC-112 (secp112r1), ECC-96, ECC-88 and
ECC-64 (non-standardized).
Please note that these short hash codes are NOT secure.
msvc-debug.diff:
adds support for debug builds (nmake /f makefile.msvc CFG=debug)
to the MSVC makefile
ecc_signraw.diff:
ecc_sign_hash() and ecc_verify_hash() read/write DER encoded
signatures. To keep signature size small (48 vs. 55 Bytes for ECC-192),
the new functions ecc_sign_hash_raw() and ecc_verify_hash_raw()
read/write raw unencoded data.
In case the attachments get stripped, they are also available from GNUnet (gnunet.org):
gnunet://ecrs/chk/N0R3MLTK4MQPQM8JPQ19NS3JUH9C5JHF7I68EV99OGGGV4MMI1BU1I43P3296SC1CTTEO1ACAT9QECHAJVQUBCTASJ659CEUDJUS69G.VFCJFO0VCMID74TK8GDQQVJD5OSQFEAB8KLBT1PO4HFIIOK6S8QQ21U4FA75H1I2M2POOIF27CT6J513DLHBDR8B0VF28B9JJAQU4A8.3343
All patches are against LibTomCrypt 1.13 and can be applied using
patch -p 0 < x.diff
Best regards,
Nils Durner Index: src/pk/ecc/ecc_sign_hash.c
===================================================================
--- src/pk/ecc/ecc_sign_hash.c (.../tags/vendor/libtomcrypt/libtomcrypt-1.13) (Revision 243)
+++ src/pk/ecc/ecc_sign_hash.c (.../) (Revision 243)
@@ -24,29 +24,24 @@
#ifdef MECC
/**
- Sign a message digest
+ Sign a message digest and return the signature components r and s
@param in The message digest to sign
@param inlen The length of the digest
- @param out [out] The destination for the signature
- @param outlen [in/out] The max size and resulting size of the signature
+ @param r [out] The r component of the signature
+ @param s [out] The s component of the signature
@param prng An active PRNG state
@param wprng The index of the PRNG you wish to use
@param key A private ECC key
@return CRYPT_OK if successful
*/
-int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
- unsigned char *out, unsigned long *outlen,
+int _ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ void **r, void **s,
prng_state *prng, int wprng, ecc_key *key)
{
ecc_key pubkey;
- void *r, *s, *e, *p;
+ void *e, *p, *r2, *s2;
int err;
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(out != NULL);
- LTC_ARGCHK(outlen != NULL);
- LTC_ARGCHK(key != NULL);
-
/* is this a private key? */
if (key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
@@ -63,10 +58,12 @@
/* get the hash and load it as a bignum into 'e' */
/* init the bignums */
- if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) {
+ if ((err = mp_init_multi(r, s, &p, &e, NULL)) != CRYPT_OK) {
ecc_free(&pubkey);
goto LBL_ERR;
}
+ r2 = *r;
+ s2 = *s;
if ((err = mp_read_radix(p, (char *)ltc_ecc_sets[key->idx].order, 16)) != CRYPT_OK) { goto error; }
if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; }
@@ -77,19 +74,19 @@
}
/* find r = x1 mod n */
- if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(pubkey.pubkey.x, p, r2)) != CRYPT_OK) { goto error; }
- if (mp_iszero(r)) {
+ if (mp_iszero(r2)) {
ecc_free(&pubkey);
} else {
/* find s = (e + xr)/k */
if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/k */
- if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */
- if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e + xr */
- if ((err = mp_mod(s, p, s)) != CRYPT_OK) { goto error; } /* s = e + xr */
- if ((err = mp_mulmod(s, pubkey.k, p, s)) != CRYPT_OK) { goto error; } /* s = (e + xr)/k */
+ if ((err = mp_mulmod(key->k, r2, p, s2)) != CRYPT_OK) { goto error; } /* s = xr */
+ if ((err = mp_add(e, s2, s2)) != CRYPT_OK) { goto error; } /* s = e + xr */
+ if ((err = mp_mod(s2, p, s2)) != CRYPT_OK) { goto error; } /* s = e + xr */
+ if ((err = mp_mulmod(s2, pubkey.k, p, s2)) != CRYPT_OK) { goto error; } /* s = (e + xr)/k */
- if (mp_iszero(s)) {
+ if (mp_iszero(s2)) {
ecc_free(&pubkey);
} else {
break;
@@ -97,6 +94,42 @@
}
}
+ goto LBL_ERR;
+error:
+LBL_ERR:
+ mp_clear_multi(p, e, NULL);
+ ecc_free(&pubkey);
+
+ return err;
+}
+
+/**
+ Sign a message digest
+ @param in The message digest to sign
+ @param inlen The length of the digest
+ @param out [out] The destination for the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param key A private ECC key
+ @return CRYPT_OK if successful
+*/
+int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, ecc_key *key)
+{
+ void *r, *s;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ err = _ecc_sign_hash(in, inlen, &r, &s, prng, wprng, key);
+ if (err != CRYPT_OK)
+ goto LBL_ERR;
+
/* store as SEQUENCE { r, s -- integer } */
err = der_encode_sequence_multi(out, outlen,
LTC_ASN1_INTEGER, 1UL, r,
@@ -105,12 +138,59 @@
goto LBL_ERR;
error:
LBL_ERR:
- mp_clear_multi(r, s, p, e, NULL);
- ecc_free(&pubkey);
+ mp_clear_multi(r, s, NULL);
return err;
}
+/**
+ Sign a message digest and return the signature in raw form
+ @param in The message digest to sign
+ @param inlen The length of the digest
+ @param out [out] The destination for the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param key A private ECC key
+ @return CRYPT_OK if successful
+*/
+int ecc_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, ecc_key *key)
+{
+ void *r, *s;
+ int err;
+ unsigned long rlen, slen;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ err = _ecc_sign_hash(in, inlen, &r, &s, prng, wprng, key);
+ if (err != CRYPT_OK)
+ goto quit;
+
+ /* store raw */
+ rlen = mp_unsigned_bin_size(r);
+ slen = mp_unsigned_bin_size(s);
+ if (rlen + slen > *outlen)
+ {
+ *outlen = rlen + slen;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto error;
+ }
+
+ mp_to_unsigned_bin(r, out);
+ mp_to_unsigned_bin(s, out + rlen);
+
+error:
+ mp_clear_multi(r, s, NULL);
+quit:
+
+ return err;
+}
+
#endif
/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sign_hash.c,v $ */
/* $Revision: 1.5 $ */
Index: src/pk/ecc/ecc_verify_hash.c
===================================================================
--- src/pk/ecc/ecc_verify_hash.c (.../tags/vendor/libtomcrypt/libtomcrypt-1.13) (Revision 243)
+++ src/pk/ecc/ecc_verify_hash.c (.../) (Revision 243)
@@ -35,28 +35,23 @@
/**
Verify an ECC signature
- @param sig The signature to verify
- @param siglen The length of the signature (octets)
+ @param r The r component of the signature
+ @param s The s component of the signature
@param hash The hash (message digest) that was signed
@param hashlen The length of the hash (octets)
@param stat Result of signature, 1==valid, 0==invalid
@param key The corresponding public ECC key
@return CRYPT_OK if successful (even if the signature is not valid)
*/
-int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+int _ecc_verify_hash(void *r, void *s,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key)
{
ecc_point *mG, *mQ;
- void *r, *s, *v, *w, *u1, *u2, *e, *p, *m;
+ void *v, *w, *u1, *u2, *e, *p, *m;
void *mp;
int err;
- LTC_ARGCHK(sig != NULL);
- LTC_ARGCHK(hash != NULL);
- LTC_ARGCHK(stat != NULL);
- LTC_ARGCHK(key != NULL);
-
/* default to invalid signature */
*stat = 0;
mp = NULL;
@@ -67,7 +62,7 @@
}
/* allocate ints */
- if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != CRYPT_OK) {
+ if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e, &m, NULL)) != CRYPT_OK) {
return CRYPT_MEM;
}
@@ -79,14 +74,6 @@
goto done;
}
- /* parse header */
- if ((err = der_decode_sequence_multi(sig, siglen,
- LTC_ASN1_INTEGER, 1UL, r,
- LTC_ASN1_INTEGER, 1UL, s,
- LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
- goto done;
- }
-
/* get the order */
if ((err = mp_read_radix(p, (char *)ltc_ecc_sets[key->idx].order, 16)) != CRYPT_OK) { goto error; }
@@ -146,13 +133,107 @@
done:
ltc_ecc_del_point(mG);
ltc_ecc_del_point(mQ);
- mp_clear_multi(r, s, v, w, u1, u2, p, e, m, NULL);
+ mp_clear_multi(v, w, u1, u2, p, e, m, NULL);
if (mp != NULL) {
mp_montgomery_free(mp);
}
return err;
}
+/**
+ Verify an ECC signature
+ @param sig The signature to verify
+ @param siglen The length of the signature (octets)
+ @param hash The hash (message digest) that was signed
+ @param hashlen The length of the hash (octets)
+ @param stat Result of signature, 1==valid, 0==invalid
+ @param key The corresponding public ECC key
+ @return CRYPT_OK if successful (even if the signature is not valid)
+*/
+int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key)
+{
+ void *r, *s;
+ int err;
+
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* allocate ints */
+ if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* parse header */
+ if ((err = der_decode_sequence_multi(sig, siglen,
+ LTC_ASN1_INTEGER, 1UL, r,
+ LTC_ASN1_INTEGER, 1UL, s,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto done;
+ }
+
+ /* verify */
+ err = _ecc_verify_hash(r, s, hash, hashlen, stat, key);
+
+ goto done;
+
+error:
+done:
+ mp_clear_multi(r, s, NULL);
+ return err;
+}
+
+/**
+ Verify an unencoded ECC signature
+ @param sig The signature to verify
+ @param siglen The length of the signature (octets)
+ @param hash The hash (message digest) that was signed
+ @param hashlen The length of the hash (octets)
+ @param stat Result of signature, 1==valid, 0==invalid
+ @param key The corresponding public ECC key
+ @return CRYPT_OK if successful (even if the signature is not valid)
+*/
+int ecc_verify_hash_raw(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key)
+{
+ void *r, *s;
+ int err;
+ unsigned long rlen;
+
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* allocate ints */
+ if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* get r and s component */
+ if (siglen % 2 != 0) {
+ err = CRYPT_INVALID_KEYSIZE;
+ goto error;
+ }
+ rlen = siglen / 2;
+ mp_read_unsigned_bin(r, sig, rlen);
+ mp_read_unsigned_bin(s, sig + rlen, rlen);
+
+ /* verify */
+ err = _ecc_verify_hash(r, s, hash, hashlen, stat, key);
+
+ goto done;
+
+error:
+done:
+ mp_clear_multi(r, s, NULL);
+ return err;
+}
+
#endif
/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_verify_hash.c,v $ */
/* $Revision: 1.7 $ */
Index: src/headers/tomcrypt_pk.h
===================================================================
--- src/headers/tomcrypt_pk.h (.../tags/vendor/libtomcrypt/libtomcrypt-1.13) (Revision 243)
+++ src/headers/tomcrypt_pk.h (.../) (Revision 243)
@@ -217,10 +217,18 @@
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, ecc_key *key);
+int ecc_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, ecc_key *key);
+
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key);
+int ecc_verify_hash_raw(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key);
+
/* low level functions */
ecc_point *ltc_ecc_new_point(void);
void ltc_ecc_del_point(ecc_point *p);
Index: makefile.msvc
===================================================================
--- makefile.msvc (.../tags/vendor/libtomcrypt/libtomcrypt-1.13) (Revision 243)
+++ makefile.msvc (.../) (Revision 243)
@@ -1,7 +1,10 @@
#MSVC Makefile [tested with MSVC 6.00 with SP5]
#
#Tom St Denis
-CFLAGS = /Isrc/headers/ /Itestprof/ /Ox /DWIN32 /DLTC_SOURCE /W3 /Fo$@ $(CF)
+CFLAGS = /Isrc/headers/ /Itestprof/ /Ox /DWIN32 /DLTC_SOURCE /W3 /Fo$@ $(CF)
+!IF "$(CFG)" == "debug"
+CFLAGS = /Isrc/headers/ /Itestprof/ /MDd /Od /Gm /Zi /D_DEBUG /GZ /GR /DWIN32 /DLTC_SOURCE /W3 /Fo$@ $(CF)
+!ENDIF
#START_INS
OBJECTS=src/ciphers/aes/aes_enc.obj src/ciphers/aes/aes.obj src/ciphers/anubis.obj src/ciphers/blowfish.obj \
Index: src/pk/ecc/ecc.c
===================================================================
--- src/pk/ecc/ecc.c (.../tags/vendor/libtomcrypt/libtomcrypt-1.13) (Revision 243)
+++ src/pk/ecc/ecc.c (.../) (Revision 243)
@@ -25,6 +25,42 @@
/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
const ltc_ecc_set_type ltc_ecc_sets[] = {
+{
+ 8,
+ "ECC-64",
+ "FFFFFFFFFFFFFFC5",
+ "000000000000016B",
+ "FFFFFFFF3FC141C5",
+ "794200BF343FC8EB",
+ "B0B1FDB6ADAC0FD2",
+},
+{
+ 11,
+ "ECC-88",
+ "FFFFFFFFFFFFFFFFFFFED5",
+ "000000000000000000001D",
+ "FFFFFFFFFFFC062B93471D",
+ "5A2902A206AFCCEB34BC91",
+ "51CB5596E3287387B8589C",
+},
+{
+ 12,
+ "ECC-96",
+ "FFFFFFFFFFFFFFFFFFFFFFEF",
+ "000000000000000000000002",
+ "FFFFFFFFFFFFC9E15E67DB59",
+ "BFF9F8B8706AAA8FDE0B032C",
+ "74BF03B170864B519BF59ACE",
+},
+{
+ 14,
+ "ECC-112",
+ "DB7C2ABF62E35E668076BEAD208B",
+ "DB7C2ABF62E35E668076BEAD2088",
+ "659EF8BA043916EEDE8911702B22",
+ "0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500",
+ "DB7C2ABF62E35E7628DFAC6561C5",
+},
#ifdef ECC192
{
24,
- Follow-Ups:
- Re: [LTC] ECC <= 112
- From: Tom St Denis
- Re: [LTC] ECC <= 112
- From: Tom St Denis
- Re: [LTC] ECC <= 112
- Prev by Date: Re: ECC point compression trick
- Next by Date: Re: [LTC] ECC <= 112
- Previous by thread: ECC point compression trick
- Next by thread: Re: [LTC] ECC <= 112
- Index(es):
Relevant Pages
|
|