Skip to content

Commit 6561b37

Browse files
karel-msjaeckel
authored andcommitted
refactor ecc_verify_hash_ex
1 parent 0ee3bb5 commit 6561b37

8 files changed

Lines changed: 339 additions & 181 deletions

src/headers/tomcrypt_pk.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,21 @@ int ecc_sign_hash_eth27(const unsigned char *in, unsigned long inlen,
358358
unsigned char *out, unsigned long *outlen,
359359
prng_state *prng, int wprng, const ecc_key *key);
360360

361-
#define ecc_verify_hash_rfc7518(sig_, siglen_, hash_, hashlen_, stat_, key_) \
362-
ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_RFC7518, stat_, key_)
361+
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
362+
const unsigned char *hash, unsigned long hashlen,
363+
int *stat, const ecc_key *key);
364+
365+
int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen,
366+
const unsigned char *hash, unsigned long hashlen,
367+
int *stat, const ecc_key *key);
363368

364-
#define ecc_verify_hash(sig_, siglen_, hash_, hashlen_, stat_, key_) \
365-
ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_ANSIX962, stat_, key_)
369+
int ecc_verify_hash_rfc5656(const unsigned char *sig, unsigned long siglen,
370+
const unsigned char *hash, unsigned long hashlen,
371+
int *stat, const ecc_key *key);
366372

367-
int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
368-
const unsigned char *hash, unsigned long hashlen,
369-
ecc_signature_type sigformat, int *stat, const ecc_key *key);
373+
int ecc_verify_hash_eth27(const unsigned char *sig, unsigned long siglen,
374+
const unsigned char *hash, unsigned long hashlen,
375+
int *stat, const ecc_key *key);
370376

371377
int ecc_recover_key(const unsigned char *sig, unsigned long siglen,
372378
const unsigned char *hash, unsigned long hashlen,

src/headers/tomcrypt_private.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,10 @@ int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen,
424424
void *r, void *s, prng_state *prng, int wprng,
425425
int *recid, const ecc_key *key);
426426

427+
int ecc_verify_hash_internal(void *r, void *s,
428+
const unsigned char *hash, unsigned long hashlen,
429+
int *stat, const ecc_key *key);
430+
427431
#ifdef LTC_SSH
428432
int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key);
429433
#endif

src/pk/ecc/ecc_verify_hash.c

Lines changed: 13 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -11,195 +11,36 @@
1111
*/
1212

1313
/**
14-
Verify an ECC signature in RFC7518 format
14+
Verify an ECC signature (ANSI X9.62 format)
1515
@param sig The signature to verify
1616
@param siglen The length of the signature (octets)
1717
@param hash The hash (message digest) that was signed
1818
@param hashlen The length of the hash (octets)
19-
@param sigformat The format of the signature (ecc_signature_type)
20-
@param stat Result of signature, 1==valid, 0==invalid
19+
@param stat [out] Result of signature, 1==valid, 0==invalid
2120
@param key The corresponding public ECC key
2221
@return CRYPT_OK if successful (even if the signature is not valid)
2322
*/
24-
int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
25-
const unsigned char *hash, unsigned long hashlen,
26-
ecc_signature_type sigformat, int *stat, const ecc_key *key)
23+
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
24+
const unsigned char *hash, unsigned long hashlen,
25+
int *stat, const ecc_key *key)
2726
{
28-
ecc_point *mG = NULL, *mQ = NULL;
29-
void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3;
30-
void *mu = NULL, *ma = NULL;
31-
void *mp = NULL;
32-
int err;
33-
unsigned long pbits, pbytes, i, shift_right;
34-
unsigned char ch, buf[MAXBLOCKSIZE];
27+
void *r, *s;
28+
int err;
3529

36-
LTC_ARGCHK(sig != NULL);
37-
LTC_ARGCHK(hash != NULL);
38-
LTC_ARGCHK(stat != NULL);
39-
LTC_ARGCHK(key != NULL);
30+
LTC_ARGCHK(sig != NULL);
4031

41-
/* default to invalid signature */
42-
*stat = 0;
32+
if ((err = ltc_mp_init_multi(&r, &s, NULL)) != CRYPT_OK) return err;
4333

44-
/* allocate ints */
45-
if ((err = ltc_mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, LTC_NULL)) != CRYPT_OK) {
46-
return err;
47-
}
48-
49-
p = key->dp.order;
50-
m = key->dp.prime;
51-
a = key->dp.A;
52-
if ((err = ltc_mp_add_d(a, 3, a_plus3)) != CRYPT_OK) {
53-
goto error;
54-
}
55-
56-
/* allocate points */
57-
mG = ltc_ecc_new_point();
58-
mQ = ltc_ecc_new_point();
59-
if (mQ == NULL || mG == NULL) {
60-
err = CRYPT_MEM;
61-
goto error;
62-
}
63-
64-
if (sigformat == LTC_ECCSIG_ANSIX962) {
65-
/* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */
66-
if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT,
34+
/* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */
35+
if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT,
6736
LTC_ASN1_INTEGER, 1UL, r,
6837
LTC_ASN1_INTEGER, 1UL, s,
6938
LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; }
70-
}
71-
else if (sigformat == LTC_ECCSIG_RFC7518) {
72-
/* RFC7518 format - raw (r,s) */
73-
i = ltc_mp_unsigned_bin_size(key->dp.order);
74-
if (siglen != (2 * i)) {
75-
err = CRYPT_INVALID_PACKET;
76-
goto error;
77-
}
78-
if ((err = ltc_mp_read_unsigned_bin(r, sig, i)) != CRYPT_OK) { goto error; }
79-
if ((err = ltc_mp_read_unsigned_bin(s, sig+i, i)) != CRYPT_OK) { goto error; }
80-
}
81-
else if (sigformat == LTC_ECCSIG_ETH27) {
82-
/* Ethereum (v,r,s) format */
83-
if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) {
84-
/* Only valid for secp256k1 - OID 1.3.132.0.10 */
85-
err = CRYPT_ERROR; goto error;
86-
}
87-
if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */
88-
err = CRYPT_INVALID_PACKET;
89-
goto error;
90-
}
91-
if ((err = ltc_mp_read_unsigned_bin(r, sig, 32)) != CRYPT_OK) { goto error; }
92-
if ((err = ltc_mp_read_unsigned_bin(s, sig+32, 32)) != CRYPT_OK) { goto error; }
93-
}
94-
#ifdef LTC_SSH
95-
else if (sigformat == LTC_ECCSIG_RFC5656) {
96-
char name[64], name2[64];
97-
unsigned long namelen = sizeof(name);
98-
unsigned long name2len = sizeof(name2);
99-
100-
/* Decode as SSH data sequence, per RFC4251 */
101-
if ((err = ssh_decode_sequence_multi(sig, &siglen,
102-
LTC_SSHDATA_STRING, name, &namelen,
103-
LTC_SSHDATA_MPINT, r,
104-
LTC_SSHDATA_MPINT, s,
105-
LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; }
106-
107-
108-
/* Check curve matches identifier string */
109-
if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; }
110-
if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) {
111-
err = CRYPT_INVALID_ARG;
112-
goto error;
113-
}
114-
}
115-
#endif
116-
else {
117-
/* Unknown signature format */
118-
err = CRYPT_ERROR;
119-
goto error;
120-
}
121-
122-
/* check for zero */
123-
if (ltc_mp_cmp_d(r, 0) != LTC_MP_GT || ltc_mp_cmp_d(s, 0) != LTC_MP_GT ||
124-
ltc_mp_cmp(r, p) != LTC_MP_LT || ltc_mp_cmp(s, p) != LTC_MP_LT) {
125-
err = CRYPT_INVALID_PACKET;
126-
goto error;
127-
}
128-
129-
/* read hash - truncate if needed */
130-
pbits = ltc_mp_count_bits(p);
131-
pbytes = (pbits+7) >> 3;
132-
if (pbits > hashlen*8) {
133-
if ((err = ltc_mp_read_unsigned_bin(e, hash, hashlen)) != CRYPT_OK) { goto error; }
134-
}
135-
else if (pbits % 8 == 0) {
136-
if ((err = ltc_mp_read_unsigned_bin(e, hash, pbytes)) != CRYPT_OK) { goto error; }
137-
}
138-
else {
139-
shift_right = 8 - pbits % 8;
140-
for (i=0, ch=0; i<pbytes; i++) {
141-
buf[i] = ch;
142-
ch = (hash[i] << (8-shift_right));
143-
buf[i] = buf[i] ^ (hash[i] >> shift_right);
144-
}
145-
if ((err = ltc_mp_read_unsigned_bin(e, buf, pbytes)) != CRYPT_OK) { goto error; }
146-
}
147-
148-
/* w = s^-1 mod n */
149-
if ((err = ltc_mp_invmod(s, p, w)) != CRYPT_OK) { goto error; }
150-
151-
/* u1 = ew */
152-
if ((err = ltc_mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; }
153-
154-
/* u2 = rw */
155-
if ((err = ltc_mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
156-
157-
/* find mG and mQ */
158-
if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; }
159-
if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) { goto error; }
160-
161-
/* find the montgomery mp */
162-
if ((err = ltc_mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
163-
164-
/* for curves with a == -3 keep ma == NULL */
165-
if (ltc_mp_cmp(a_plus3, m) != LTC_MP_EQ) {
166-
if ((err = ltc_mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; }
167-
if ((err = ltc_mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; }
168-
if ((err = ltc_mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; }
169-
}
170-
171-
/* compute u1*mG + u2*mQ = mG */
172-
if (ltc_mp.ecc_mul2add == NULL) {
173-
if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; }
174-
if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; }
175-
176-
/* add them */
177-
if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; }
178-
179-
/* reduce */
180-
if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; }
181-
} else {
182-
/* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
183-
if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; }
184-
}
185-
186-
/* v = X_x1 mod n */
187-
if ((err = ltc_mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; }
18839

189-
/* does v == r */
190-
if (ltc_mp_cmp(v, r) == LTC_MP_EQ) {
191-
*stat = 1;
192-
}
40+
err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key);
19341

194-
/* clear up and return */
195-
err = CRYPT_OK;
19642
error:
197-
if (mG != NULL) ltc_ecc_del_point(mG);
198-
if (mQ != NULL) ltc_ecc_del_point(mQ);
199-
if (mu != NULL) ltc_mp_clear(mu);
200-
if (ma != NULL) ltc_mp_clear(ma);
201-
ltc_mp_deinit_multi(r, s, v, w, u1, u2, e, a_plus3, LTC_NULL);
202-
if (mp != NULL) ltc_mp_montgomery_free(mp);
43+
ltc_mp_deinit_multi(r, s, LTC_NULL);
20344
return err;
20445
}
20546

src/pk/ecc/ecc_verify_hash_eth27.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2+
/* SPDX-License-Identifier: Unlicense */
3+
4+
#include "tomcrypt_private.h"
5+
6+
#ifdef LTC_MECC
7+
8+
/**
9+
@file ecc_verify_hash.c
10+
ECC Crypto, Tom St Denis
11+
*/
12+
13+
/**
14+
Verify an ECC signature (Ethereum format with recovery_id+27)
15+
@param sig The signature to verify
16+
@param siglen The length of the signature (octets)
17+
@param hash The hash (message digest) that was signed
18+
@param hashlen The length of the hash (octets)
19+
@param stat [out] Result of signature, 1==valid, 0==invalid
20+
@param key The corresponding public ECC key
21+
@return CRYPT_OK if successful (even if the signature is not valid)
22+
*/
23+
int ecc_verify_hash_eth27(const unsigned char *sig, unsigned long siglen,
24+
const unsigned char *hash, unsigned long hashlen,
25+
int *stat, const ecc_key *key)
26+
{
27+
void *r, *s;
28+
int err;
29+
30+
LTC_ARGCHK(sig != NULL);
31+
LTC_ARGCHK(key != NULL);
32+
33+
/* Only valid for secp256k1 - OID 1.3.132.0.10 */
34+
if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) {
35+
return CRYPT_ERROR;
36+
}
37+
/* Only secp256k1 curves uses this format, so must be 65 bytes long */
38+
if (siglen != 65) {
39+
return CRYPT_INVALID_PACKET;
40+
}
41+
42+
if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err;
43+
if ((err = ltc_mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) goto error;
44+
if ((err = ltc_mp_read_unsigned_bin(s, (unsigned char *)sig + 32, 32)) != CRYPT_OK) goto error;
45+
46+
err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key);
47+
48+
error:
49+
ltc_mp_deinit_multi(r, s, LTC_NULL);
50+
return err;
51+
}
52+
53+
#endif

0 commit comments

Comments
 (0)