From 3605983f09ba47db64cbfa38464f9e36cd91cd0d Mon Sep 17 00:00:00 2001 From: Pascal Brand Date: Tue, 30 Jun 2015 15:52:38 +0200 Subject: [PATCH] Introduce ECC raw algorithms for sign and verify As it is performed on dsa, raw sign and verify on ECC are introduced. Signed-off-by: Pascal Brand --- src/headers/tomcrypt_pk.h | 8 ++++ src/pk/ecc/ecc_sign_hash.c | 81 +++++++++++++++++++++++++--------- src/pk/ecc/ecc_verify_hash.c | 85 ++++++++++++++++++++++++++---------- 3 files changed, 129 insertions(+), 45 deletions(-) diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index a474646..5b3525e 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -301,10 +301,18 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, ecc_key *key); +int ecc_sign_hash_raw(const unsigned char *in, unsigned long inlen, + void *r, void *s, + prng_state *prng, int wprng, ecc_key *key); + 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); +int ecc_verify_hash_raw( void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, 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); diff --git a/src/pk/ecc/ecc_sign_hash.c b/src/pk/ecc/ecc_sign_hash.c index a01dfad..5975781 100644 --- a/src/pk/ecc/ecc_sign_hash.c +++ b/src/pk/ecc/ecc_sign_hash.c @@ -24,28 +24,28 @@ #ifdef LTC_MECC /** - 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 + Sign a hash with ECC + @param in The hash to sign + @param inlen The length of the hash to sign + @param r The "r" integer of the signature (caller must initialize with mp_init() first) + @param s The "s" integer of the signature (caller must initialize with mp_init() first) + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @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) +int ecc_sign_hash_raw(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; int err; - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(r != NULL); + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(key != NULL); /* is this a private key? */ if (key->type != PK_PRIVATE) { @@ -63,7 +63,7 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen, /* 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(&p, &e, NULL)) != CRYPT_OK) { return err; } if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; } @@ -94,16 +94,55 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen, } } + err = CRYPT_OK; + goto errnokey; + +error: + ecc_free(&pubkey); +errnokey: + mp_clear_multi(p, e, NULL); + 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); + + if (mp_init_multi(&r, &s, NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + if ((err = ecc_sign_hash_raw(in, inlen, r, s, prng, wprng, key)) != CRYPT_OK) { + goto error; + } + /* store as SEQUENCE { r, s -- integer } */ err = der_encode_sequence_multi(out, outlen, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, LTC_ASN1_EOL, 0UL, NULL); - goto errnokey; + error: - ecc_free(&pubkey); -errnokey: - mp_clear_multi(r, s, p, e, NULL); + mp_clear_multi(r, s, NULL); return err; } diff --git a/src/pk/ecc/ecc_verify_hash.c b/src/pk/ecc/ecc_verify_hash.c index ba7bba5..afa7f39 100644 --- a/src/pk/ecc/ecc_verify_hash.c +++ b/src/pk/ecc/ecc_verify_hash.c @@ -34,25 +34,26 @@ */ /** - 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) + Verify a ECC signature + @param r ECC "r" parameter + @param s ECC "s" parameter + @param hash The hash that was signed + @param hashlen The length of the hash that was signed + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param key The corresponding public DH key + @return CRYPT_OK if successful (even if the signature is invalid) */ -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( 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 *mp; + void *v, *w, *u1, *u2, *e, *p, *m; + void *mp = NULL; int err; - LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(r != NULL); + LTC_ARGCHK(s != NULL); LTC_ARGCHK(hash != NULL); LTC_ARGCHK(stat != NULL); LTC_ARGCHK(key != NULL); @@ -67,7 +68,7 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, } /* 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 +80,6 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, goto error; } - /* 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 error; - } - /* get the order */ if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto error; } @@ -151,13 +144,57 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, error: 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 error; + } + + /* do the op */ + err = ecc_verify_hash_raw(r, s, hash, hashlen, stat, key); + +error: + mp_clear_multi(r, s, NULL); + return err; +} + #endif /* $Source$ */ /* $Revision$ */