From 5613baeaafa9584ed02364c5dc12ae180461dbee Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Sun, 14 Oct 2018 14:34:34 +0200 Subject: [PATCH] refactor ecc_verify_hash_ex --- src/headers/tomcrypt_pk.h | 20 ++- src/headers/tomcrypt_private.h | 4 + src/pk/ecc/ecc_verify_hash.c | 186 ++------------------------ src/pk/ecc/ecc_verify_hash_eth27.c | 64 +++++++++ src/pk/ecc/ecc_verify_hash_internal.c | 143 ++++++++++++++++++++ src/pk/ecc/ecc_verify_hash_rfc5656.c | 68 ++++++++++ src/pk/ecc/ecc_verify_hash_rfc7518.c | 62 +++++++++ tests/ecc_test.c | 4 +- 8 files changed, 370 insertions(+), 181 deletions(-) create mode 100644 src/pk/ecc/ecc_verify_hash_eth27.c create mode 100644 src/pk/ecc/ecc_verify_hash_internal.c create mode 100644 src/pk/ecc/ecc_verify_hash_rfc5656.c create mode 100644 src/pk/ecc/ecc_verify_hash_rfc7518.c diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index a598d845b..b077af392 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -319,15 +319,21 @@ int ecc_sign_hash_eth27(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, const ecc_key *key); -#define ecc_verify_hash_rfc7518(sig_, siglen_, hash_, hashlen_, stat_, key_) \ - ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_RFC7518, stat_, key_) +int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key); + +int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key); -#define ecc_verify_hash(sig_, siglen_, hash_, hashlen_, stat_, key_) \ - ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_ANSIX962, stat_, key_) +int ecc_verify_hash_rfc5656(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key); -int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - ecc_signature_type sigformat, int *stat, const ecc_key *key); +int ecc_verify_hash_eth27(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key); int ecc_recover_key(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index e312cc7eb..df86edde3 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -230,6 +230,10 @@ int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen, void *r, void *s, prng_state *prng, int wprng, int *recid, const ecc_key *key); +int ecc_verify_hash_internal(void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key); + #ifdef LTC_SSH int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key); #endif diff --git a/src/pk/ecc/ecc_verify_hash.c b/src/pk/ecc/ecc_verify_hash.c index ec9e7f101..9e5ad2035 100644 --- a/src/pk/ecc/ecc_verify_hash.c +++ b/src/pk/ecc/ecc_verify_hash.c @@ -17,194 +17,36 @@ */ /** - Verify an ECC signature in RFC7518 format + Verify an ECC signature (ANSI X9.62 format) @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 sigformat The format of the signature (ecc_signature_type) - @param stat Result of signature, 1==valid, 0==invalid + @param stat [out] 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_ex(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - ecc_signature_type sigformat, int *stat, const ecc_key *key) +int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key) { - ecc_point *mG = NULL, *mQ = NULL; - void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3; - void *mu = NULL, *ma = NULL; - void *mp = NULL; - int err; - unsigned long pbits, pbytes, i, shift_right; - unsigned char ch, buf[MAXBLOCKSIZE]; + void *r, *s; + int err; - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(hash != NULL); - LTC_ARGCHK(stat != NULL); - LTC_ARGCHK(key != NULL); + LTC_ARGCHK(sig != NULL); - /* default to invalid signature */ - *stat = 0; + if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) return err; - /* allocate ints */ - if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, NULL)) != CRYPT_OK) { - return err; - } - - p = key->dp.order; - m = key->dp.prime; - a = key->dp.A; - if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { - goto error; - } - - /* allocate points */ - mG = ltc_ecc_new_point(); - mQ = ltc_ecc_new_point(); - if (mQ == NULL || mG == NULL) { - err = CRYPT_MEM; - goto error; - } - - if (sigformat == LTC_ECCSIG_ANSIX962) { - /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ - if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, + /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ + if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; } - } - else if (sigformat == LTC_ECCSIG_RFC7518) { - /* RFC7518 format - raw (r,s) */ - i = mp_unsigned_bin_size(key->dp.order); - if (siglen != (2 * i)) { - err = CRYPT_INVALID_PACKET; - goto error; - } - if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; } - if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; } - } - else if (sigformat == LTC_ECCSIG_ETH27) { - /* Ethereum (v,r,s) format */ - if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { - /* Only valid for secp256k1 - OID 1.3.132.0.10 */ - err = CRYPT_ERROR; goto error; - } - if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */ - err = CRYPT_INVALID_PACKET; - goto error; - } - if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) { goto error; } - if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+32, 32)) != CRYPT_OK) { goto error; } - } -#ifdef LTC_SSH - else if (sigformat == LTC_ECCSIG_RFC5656) { - char name[64], name2[64]; - unsigned long namelen = sizeof(name2); - - /* Decode as SSH data sequence, per RFC4251 */ - if ((err = ssh_decode_sequence_multi(sig, siglen, - LTC_SSHDATA_STRING, name, 64, - LTC_SSHDATA_MPINT, r, - LTC_SSHDATA_MPINT, s, - LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; } - - - /* Check curve matches identifier string */ - if ((err = ecc_ssh_ecdsa_encode_name(name2, &namelen, key)) != CRYPT_OK) { goto error; } - if (XSTRCMP(name,name2) != 0) { - err = CRYPT_INVALID_ARG; - goto error; - } - } -#endif - else { - /* Unknown signature format */ - err = CRYPT_ERROR; - goto error; - } - - /* check for zero */ - if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || - mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { - err = CRYPT_INVALID_PACKET; - goto error; - } - - /* read hash - truncate if needed */ - pbits = mp_count_bits(p); - pbytes = (pbits+7) >> 3; - if (pbits > hashlen*8) { - if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } - } - else if (pbits % 8 == 0) { - if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } - } - else { - shift_right = 8 - pbits % 8; - for (i=0, ch=0; i> shift_right); - } - if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } - } - - /* w = s^-1 mod n */ - if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } - - /* u1 = ew */ - if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; } - - /* u2 = rw */ - if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; } - - /* find mG and mQ */ - if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } - if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) { goto error; } - - /* find the montgomery mp */ - if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } - - /* for curves with a == -3 keep ma == NULL */ - if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { - if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) { goto error; } - if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } - if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } - } - - /* compute u1*mG + u2*mQ = mG */ - if (ltc_mp.ecc_mul2add == NULL) { - if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; } - if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; } - - /* add them */ - if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; } - - /* reduce */ - if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; } - } else { - /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */ - if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; } - } - - /* v = X_x1 mod n */ - if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; } + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) goto error; - /* does v == r */ - if (mp_cmp(v, r) == LTC_MP_EQ) { - *stat = 1; - } + err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); - /* clear up and return */ - err = CRYPT_OK; error: - if (mG != NULL) ltc_ecc_del_point(mG); - if (mQ != NULL) ltc_ecc_del_point(mQ); - if (mu != NULL) mp_clear(mu); - if (ma != NULL) mp_clear(ma); - mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, NULL); - if (mp != NULL) mp_montgomery_free(mp); + mp_clear_multi(r, s, NULL); return err; } diff --git a/src/pk/ecc/ecc_verify_hash_eth27.c b/src/pk/ecc/ecc_verify_hash_eth27.c new file mode 100644 index 000000000..41eb9e1cc --- /dev/null +++ b/src/pk/ecc/ecc_verify_hash_eth27.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** + @file ecc_verify_hash.c + ECC Crypto, Tom St Denis +*/ + +/** + Verify an ECC signature (Ethereum format with recovery_id+27) + @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 [out] 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_eth27(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key) +{ + void *r, *s; + int err; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) return err; + + /* Only valid for secp256k1 - OID 1.3.132.0.10 */ + if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { + err = CRYPT_ERROR; + goto error; + } + if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */ + err = CRYPT_INVALID_PACKET; + goto error; + } + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) goto error; + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig + 32, 32)) != CRYPT_OK) goto error; + + err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); + +error: + mp_clear_multi(r, s, NULL); + return err; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/pk/ecc/ecc_verify_hash_internal.c b/src/pk/ecc/ecc_verify_hash_internal.c new file mode 100644 index 000000000..d35ad556e --- /dev/null +++ b/src/pk/ecc/ecc_verify_hash_internal.c @@ -0,0 +1,143 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +int ecc_verify_hash_internal(void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key) +{ + ecc_point *mG = NULL, *mQ = NULL; + void *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3; + void *mu = NULL, *ma = NULL; + void *mp = NULL; + int err; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; + + LTC_ARGCHK(r != NULL); + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* default to invalid signature */ + *stat = 0; + + /* allocate ints */ + if ((err = mp_init_multi(&v, &w, &u1, &u2, &e, &a_plus3, NULL)) != CRYPT_OK) { + return err; + } + + p = key->dp.order; + m = key->dp.prime; + a = key->dp.A; + if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { + goto error; + } + + /* allocate points */ + mG = ltc_ecc_new_point(); + mQ = ltc_ecc_new_point(); + if (mQ == NULL || mG == NULL) { + err = CRYPT_MEM; + goto error; + } + + /* check for zero */ + if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || + mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* read hash - truncate if needed */ + pbits = mp_count_bits(p); + pbytes = (pbits+7) >> 3; + if (pbits > hashlen*8) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } + } + else if (pbits % 8 == 0) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } + } + else { + shift_right = 8 - pbits % 8; + for (i=0, ch=0; i> shift_right); + } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } + } + + /* w = s^-1 mod n */ + if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } + + /* u1 = ew */ + if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; } + + /* u2 = rw */ + if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; } + + /* find mG and mQ */ + if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) { goto error; } + + /* find the montgomery mp */ + if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } + + /* for curves with a == -3 keep ma == NULL */ + if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { + if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) { goto error; } + if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } + } + + /* compute u1*mG + u2*mQ = mG */ + if (ltc_mp.ecc_mul2add == NULL) { + if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; } + if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; } + + /* add them */ + if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; } + + /* reduce */ + if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; } + } else { + /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */ + if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; } + } + + /* v = X_x1 mod n */ + if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; } + + /* does v == r */ + if (mp_cmp(v, r) == LTC_MP_EQ) { + *stat = 1; + } + + /* clear up and return */ + err = CRYPT_OK; +error: + if (mG != NULL) ltc_ecc_del_point(mG); + if (mQ != NULL) ltc_ecc_del_point(mQ); + if (mu != NULL) mp_clear(mu); + if (ma != NULL) mp_clear(ma); + mp_clear_multi(v, w, u1, u2, e, a_plus3, NULL); + if (mp != NULL) mp_montgomery_free(mp); + return err; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/pk/ecc/ecc_verify_hash_rfc5656.c b/src/pk/ecc/ecc_verify_hash_rfc5656.c new file mode 100644 index 000000000..0acd779b1 --- /dev/null +++ b/src/pk/ecc/ecc_verify_hash_rfc5656.c @@ -0,0 +1,68 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt_private.h" + +#if defined(LTC_MECC) && defined(LTC_SSH) + +/** + @file ecc_verify_hash.c + ECC Crypto, Tom St Denis +*/ + +/** + Verify an ECC signature (RFC5656 / SSH format) + @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 [out] 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_rfc5656(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key) +{ + void *r, *s; + int err; + char name[64], name2[64]; + unsigned long namelen = sizeof(name2); + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) return err; + + /* Decode as SSH data sequence, per RFC4251 */ + if ((err = ssh_decode_sequence_multi(sig, siglen, + LTC_SSHDATA_STRING, name, 64, + LTC_SSHDATA_MPINT, r, + LTC_SSHDATA_MPINT, s, + LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) goto error; + + /* Check curve matches identifier string */ + if ((err = ecc_ssh_ecdsa_encode_name(name2, &namelen, key)) != CRYPT_OK) goto error; + if (XSTRCMP(name,name2) != 0) { + err = CRYPT_INVALID_ARG; + goto error; + } + + err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); + +error: + mp_clear_multi(r, s, NULL); + return err; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/pk/ecc/ecc_verify_hash_rfc7518.c b/src/pk/ecc/ecc_verify_hash_rfc7518.c new file mode 100644 index 000000000..2b0717dfa --- /dev/null +++ b/src/pk/ecc/ecc_verify_hash_rfc7518.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** + @file ecc_verify_hash.c + ECC Crypto, Tom St Denis +*/ + +/** + Verify an ECC signature (RFC7518 format) + @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 [out] 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_rfc7518(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key) +{ + void *r, *s; + int err; + unsigned long i; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) return err; + + /* RFC7518 format - raw (r,s) */ + i = mp_unsigned_bin_size(key->dp.order); + if (siglen != (2 * i)) { + err = CRYPT_INVALID_PACKET; + goto error; + } + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) goto error; + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig + i, i)) != CRYPT_OK) goto error; + + err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); + +error: + mp_clear_multi(r, s, NULL); + return err; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/tests/ecc_test.c b/tests/ecc_test.c index 630bf72a9..bceda639b 100644 --- a/tests/ecc_test.c +++ b/tests/ecc_test.c @@ -585,7 +585,7 @@ static int _ecc_new_api(void) len = sizeof(buf); DO(ecc_sign_hash_rfc5656(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &privkey)); stat = 0; - DO(ecc_verify_hash_ex(buf, len, data16, 16, LTC_ECCSIG_RFC5656, &stat, &pubkey)); + DO(ecc_verify_hash_rfc5656(buf, len, data16, 16, &stat, &pubkey)); if (stat != 1) return CRYPT_FAIL_TESTVECTOR; #endif @@ -1575,7 +1575,7 @@ static int _ecc_test_recovery(void) /* test verification */ stat = 0; - DO(ecc_verify_hash_ex(buf, len, data16, 16, LTC_ECCSIG_RFC7518, &stat, &pubkey)); + DO(ecc_verify_hash_rfc7518(buf, len, data16, 16, &stat, &pubkey)); if (stat != 1) return CRYPT_FAIL_TESTVECTOR; /* test recovery */