1*f0865ec9SKyle Evans /*
2*f0865ec9SKyle Evans * Copyright (C) 2017 - This file is part of libecc project
3*f0865ec9SKyle Evans *
4*f0865ec9SKyle Evans * Authors:
5*f0865ec9SKyle Evans * Ryad BENADJILA <ryadbenadjila@gmail.com>
6*f0865ec9SKyle Evans * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7*f0865ec9SKyle Evans * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8*f0865ec9SKyle Evans *
9*f0865ec9SKyle Evans * Contributors:
10*f0865ec9SKyle Evans * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11*f0865ec9SKyle Evans * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12*f0865ec9SKyle Evans *
13*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license.
14*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project.
15*f0865ec9SKyle Evans */
16*f0865ec9SKyle Evans #include <libecc/lib_ecc_config.h>
17*f0865ec9SKyle Evans #if defined(WITH_SIG_ECDSA) && defined(USE_CRYPTOFUZZ)
18*f0865ec9SKyle Evans
19*f0865ec9SKyle Evans #include <libecc/nn/nn_rand.h>
20*f0865ec9SKyle Evans #include <libecc/nn/nn_mul.h>
21*f0865ec9SKyle Evans #include <libecc/nn/nn_logical.h>
22*f0865ec9SKyle Evans
23*f0865ec9SKyle Evans #include <libecc/sig/sig_algs_internal.h>
24*f0865ec9SKyle Evans #include <libecc/sig/ec_key.h>
25*f0865ec9SKyle Evans #include <libecc/utils/utils.h>
26*f0865ec9SKyle Evans #ifdef VERBOSE_INNER_VALUES
27*f0865ec9SKyle Evans #define EC_SIG_ALG "ECDSA"
28*f0865ec9SKyle Evans #endif
29*f0865ec9SKyle Evans #include <libecc/utils/dbg_sig.h>
30*f0865ec9SKyle Evans
31*f0865ec9SKyle Evans /* NOTE: the following versions of ECDSA are "raw" with
32*f0865ec9SKyle Evans * no hash functions and nonce override. They are DANGEROUS and
33*f0865ec9SKyle Evans * should NOT be used in production mode! They are however useful
34*f0865ec9SKyle Evans * for corner cases tests and fuzzing.
35*f0865ec9SKyle Evans */
36*f0865ec9SKyle Evans
37*f0865ec9SKyle Evans #define ECDSA_SIGN_MAGIC ((word_t)(0x80299a2bf630945bULL))
38*f0865ec9SKyle Evans #define ECDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \
39*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == ECDSA_SIGN_MAGIC), ret, err)
40*f0865ec9SKyle Evans
ecdsa_sign_raw(struct ec_sign_context * ctx,const u8 * input,u8 inputlen,u8 * sig,u8 siglen,const u8 * nonce,u8 noncelen)41*f0865ec9SKyle Evans int ecdsa_sign_raw(struct ec_sign_context *ctx, const u8 *input, u8 inputlen, u8 *sig, u8 siglen, const u8 *nonce, u8 noncelen)
42*f0865ec9SKyle Evans {
43*f0865ec9SKyle Evans const ec_priv_key *priv_key;
44*f0865ec9SKyle Evans prj_pt_src_t G;
45*f0865ec9SKyle Evans /* NOTE: hash here is not really a hash ... */
46*f0865ec9SKyle Evans u8 hash[LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8))];
47*f0865ec9SKyle Evans bitcnt_t rshift, q_bit_len;
48*f0865ec9SKyle Evans prj_pt kG;
49*f0865ec9SKyle Evans nn_src_t q, x;
50*f0865ec9SKyle Evans u8 hsize, q_len;
51*f0865ec9SKyle Evans int ret, iszero, cmp;
52*f0865ec9SKyle Evans nn k, r, e, tmp, s, kinv;
53*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
54*f0865ec9SKyle Evans /* b is the blinding mask */
55*f0865ec9SKyle Evans nn b;
56*f0865ec9SKyle Evans b.magic = WORD(0);
57*f0865ec9SKyle Evans #endif
58*f0865ec9SKyle Evans k.magic = r.magic = e.magic = WORD(0);
59*f0865ec9SKyle Evans tmp.magic = s.magic = kinv.magic = WORD(0);
60*f0865ec9SKyle Evans kG.magic = WORD(0);
61*f0865ec9SKyle Evans
62*f0865ec9SKyle Evans /*
63*f0865ec9SKyle Evans * First, verify context has been initialized and private
64*f0865ec9SKyle Evans * part too. This guarantees the context is an ECDSA
65*f0865ec9SKyle Evans * signature one and we do not finalize() before init().
66*f0865ec9SKyle Evans */
67*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err);
68*f0865ec9SKyle Evans ECDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecdsa), ret, err);
69*f0865ec9SKyle Evans MUST_HAVE((input != NULL) && (sig != NULL), ret, err);
70*f0865ec9SKyle Evans
71*f0865ec9SKyle Evans /* Zero init out poiny */
72*f0865ec9SKyle Evans ret = local_memset(&kG, 0, sizeof(prj_pt)); EG(ret, err);
73*f0865ec9SKyle Evans
74*f0865ec9SKyle Evans /* Make things more readable */
75*f0865ec9SKyle Evans priv_key = &(ctx->key_pair->priv_key);
76*f0865ec9SKyle Evans q = &(priv_key->params->ec_gen_order);
77*f0865ec9SKyle Evans q_bit_len = priv_key->params->ec_gen_order_bitlen;
78*f0865ec9SKyle Evans G = &(priv_key->params->ec_gen);
79*f0865ec9SKyle Evans q_len = (u8)BYTECEIL(q_bit_len);
80*f0865ec9SKyle Evans x = &(priv_key->x);
81*f0865ec9SKyle Evans hsize = inputlen;
82*f0865ec9SKyle Evans
83*f0865ec9SKyle Evans dbg_nn_print("p", &(priv_key->params->ec_fp.p));
84*f0865ec9SKyle Evans dbg_nn_print("q", &(priv_key->params->ec_gen_order));
85*f0865ec9SKyle Evans dbg_priv_key_print("x", priv_key);
86*f0865ec9SKyle Evans dbg_ec_point_print("G", &(priv_key->params->ec_gen));
87*f0865ec9SKyle Evans dbg_pub_key_print("Y", &(ctx->key_pair->pub_key));
88*f0865ec9SKyle Evans
89*f0865ec9SKyle Evans /* Check given signature buffer length has the expected size */
90*f0865ec9SKyle Evans MUST_HAVE((siglen == ECDSA_SIGLEN(q_bit_len)), ret, err);
91*f0865ec9SKyle Evans
92*f0865ec9SKyle Evans /* 1. Compute h = H(m) */
93*f0865ec9SKyle Evans /* NOTE: here we have raw ECDSA, this is the raw input */
94*f0865ec9SKyle Evans /* NOTE: the MUST_HAVE is protected by a preprocessing check
95*f0865ec9SKyle Evans * to avoid -Werror=type-limits errors:
96*f0865ec9SKyle Evans * "error: comparison is always true due to limited range of data type"
97*f0865ec9SKyle Evans */
98*f0865ec9SKyle Evans #if LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8)) < 255
99*f0865ec9SKyle Evans MUST_HAVE(((u32)inputlen <= sizeof(hash)), ret, err);
100*f0865ec9SKyle Evans #endif
101*f0865ec9SKyle Evans ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
102*f0865ec9SKyle Evans ret = local_memcpy(hash, input, hsize); EG(ret, err);
103*f0865ec9SKyle Evans
104*f0865ec9SKyle Evans dbg_buf_print("h", hash, hsize);
105*f0865ec9SKyle Evans
106*f0865ec9SKyle Evans /*
107*f0865ec9SKyle Evans * 2. If |h| > bitlen(q), set h to bitlen(q)
108*f0865ec9SKyle Evans * leftmost bits of h.
109*f0865ec9SKyle Evans *
110*f0865ec9SKyle Evans * Note that it's easier to check if the truncation has
111*f0865ec9SKyle Evans * to be done here but only implement it using a logical
112*f0865ec9SKyle Evans * shift at the beginning of step 3. below once the hash
113*f0865ec9SKyle Evans * has been converted to an integer.
114*f0865ec9SKyle Evans */
115*f0865ec9SKyle Evans rshift = 0;
116*f0865ec9SKyle Evans if ((hsize * 8) > q_bit_len) {
117*f0865ec9SKyle Evans rshift = (bitcnt_t)((hsize * 8) - q_bit_len);
118*f0865ec9SKyle Evans }
119*f0865ec9SKyle Evans
120*f0865ec9SKyle Evans /*
121*f0865ec9SKyle Evans * 3. Compute e = OS2I(h) mod q, i.e. by converting h to an
122*f0865ec9SKyle Evans * integer and reducing it mod q
123*f0865ec9SKyle Evans */
124*f0865ec9SKyle Evans ret = nn_init_from_buf(&e, hash, hsize); EG(ret, err);
125*f0865ec9SKyle Evans ret = local_memset(hash, 0, hsize); EG(ret, err);
126*f0865ec9SKyle Evans dbg_nn_print("h initial import as nn", &e);
127*f0865ec9SKyle Evans if (rshift) {
128*f0865ec9SKyle Evans ret = nn_rshift_fixedlen(&e, &e, rshift); EG(ret, err);
129*f0865ec9SKyle Evans }
130*f0865ec9SKyle Evans dbg_nn_print("h final import as nn", &e);
131*f0865ec9SKyle Evans ret = nn_mod(&e, &e, q); EG(ret, err);
132*f0865ec9SKyle Evans dbg_nn_print("e", &e);
133*f0865ec9SKyle Evans
134*f0865ec9SKyle Evans /*
135*f0865ec9SKyle Evans NOTE: the restart label is removed in CRYPTOFUZZ mode as
136*f0865ec9SKyle Evans we trigger MUST_HAVE instead of restarting in this mode.
137*f0865ec9SKyle Evans restart:
138*f0865ec9SKyle Evans */
139*f0865ec9SKyle Evans /* 4. get a random value k in ]0,q[ */
140*f0865ec9SKyle Evans /* NOTE: copy our input nonce if not NULL */
141*f0865ec9SKyle Evans if(nonce != NULL){
142*f0865ec9SKyle Evans MUST_HAVE((noncelen <= (u8)(BYTECEIL(q_bit_len))), ret, err);
143*f0865ec9SKyle Evans ret = nn_init_from_buf(&k, nonce, noncelen); EG(ret, err);
144*f0865ec9SKyle Evans }
145*f0865ec9SKyle Evans else{
146*f0865ec9SKyle Evans ret = ctx->rand(&k, q); EG(ret, err);
147*f0865ec9SKyle Evans }
148*f0865ec9SKyle Evans dbg_nn_print("k", &k);
149*f0865ec9SKyle Evans
150*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
151*f0865ec9SKyle Evans /* Note: if we use blinding, r and e are multiplied by
152*f0865ec9SKyle Evans * a random value b in ]0,q[ */
153*f0865ec9SKyle Evans ret = nn_get_random_mod(&b, q); EG(ret, err);
154*f0865ec9SKyle Evans dbg_nn_print("b", &b);
155*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */
156*f0865ec9SKyle Evans
157*f0865ec9SKyle Evans
158*f0865ec9SKyle Evans /* 5. Compute W = (W_x,W_y) = kG */
159*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
160*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err);
161*f0865ec9SKyle Evans #else
162*f0865ec9SKyle Evans ret = prj_pt_mul(&kG, &k, G); EG(ret, err);
163*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */
164*f0865ec9SKyle Evans ret = prj_pt_unique(&kG, &kG); EG(ret, err);
165*f0865ec9SKyle Evans
166*f0865ec9SKyle Evans dbg_nn_print("W_x", &(kG.X.fp_val));
167*f0865ec9SKyle Evans dbg_nn_print("W_y", &(kG.Y.fp_val));
168*f0865ec9SKyle Evans
169*f0865ec9SKyle Evans /* 6. Compute r = W_x mod q */
170*f0865ec9SKyle Evans ret = nn_mod(&r, &(kG.X.fp_val), q); EG(ret, err);
171*f0865ec9SKyle Evans dbg_nn_print("r", &r);
172*f0865ec9SKyle Evans
173*f0865ec9SKyle Evans /* 7. If r is 0, restart the process at step 4. */
174*f0865ec9SKyle Evans /* NOTE: for the CRYPTOFUZZ mode, we do not restart
175*f0865ec9SKyle Evans * the procedure but throw an assert exception instead.
176*f0865ec9SKyle Evans */
177*f0865ec9SKyle Evans ret = nn_iszero(&r, &iszero); EG(ret, err);
178*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err);
179*f0865ec9SKyle Evans
180*f0865ec9SKyle Evans /* Export r */
181*f0865ec9SKyle Evans ret = nn_export_to_buf(sig, q_len, &r); EG(ret, err);
182*f0865ec9SKyle Evans
183*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
184*f0865ec9SKyle Evans /* Blind r with b */
185*f0865ec9SKyle Evans ret = nn_mod_mul(&r, &r, &b, q); EG(ret, err);
186*f0865ec9SKyle Evans
187*f0865ec9SKyle Evans /* Blind the message e */
188*f0865ec9SKyle Evans ret = nn_mod_mul(&e, &e, &b, q); EG(ret, err);
189*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */
190*f0865ec9SKyle Evans
191*f0865ec9SKyle Evans /* tmp = xr mod q */
192*f0865ec9SKyle Evans ret = nn_mod_mul(&tmp, x, &r, q); EG(ret, err);
193*f0865ec9SKyle Evans dbg_nn_print("x*r mod q", &tmp);
194*f0865ec9SKyle Evans
195*f0865ec9SKyle Evans /* 8. If e == rx, restart the process at step 4. */
196*f0865ec9SKyle Evans /* NOTE: for the CRYPTOFUZZ mode, we do not restart
197*f0865ec9SKyle Evans * the procedure but throw an assert exception instead.
198*f0865ec9SKyle Evans */
199*f0865ec9SKyle Evans ret = nn_cmp(&e, &tmp, &cmp); EG(ret, err);
200*f0865ec9SKyle Evans MUST_HAVE(cmp, ret, err);
201*f0865ec9SKyle Evans
202*f0865ec9SKyle Evans /* 9. Compute s = k^-1 * (xr + e) mod q */
203*f0865ec9SKyle Evans
204*f0865ec9SKyle Evans /* tmp2 = (e + xr) mod q */
205*f0865ec9SKyle Evans ret = nn_mod_add(&tmp, &tmp, &e, q); EG(ret, err);
206*f0865ec9SKyle Evans dbg_nn_print("(xr + e) mod q", &tmp);
207*f0865ec9SKyle Evans
208*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
209*f0865ec9SKyle Evans /* In case of blinding, we compute (b*k)^-1, and
210*f0865ec9SKyle Evans * b^-1 will automatically unblind (r*x) in the following
211*f0865ec9SKyle Evans */
212*f0865ec9SKyle Evans ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err);
213*f0865ec9SKyle Evans #endif
214*f0865ec9SKyle Evans /* Compute k^-1 mod q */
215*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for
216*f0865ec9SKyle Evans * constant time here. This is possible since q is prime.
217*f0865ec9SKyle Evans */
218*f0865ec9SKyle Evans ret = nn_modinv_fermat(&kinv, &k, q); EG(ret, err);
219*f0865ec9SKyle Evans
220*f0865ec9SKyle Evans dbg_nn_print("k^-1 mod q", &kinv);
221*f0865ec9SKyle Evans
222*f0865ec9SKyle Evans /* s = k^-1 * tmp2 mod q */
223*f0865ec9SKyle Evans ret = nn_mod_mul(&s, &tmp, &kinv, q); EG(ret, err);
224*f0865ec9SKyle Evans
225*f0865ec9SKyle Evans dbg_nn_print("s", &s);
226*f0865ec9SKyle Evans
227*f0865ec9SKyle Evans /* 10. If s is 0, restart the process at step 4. */
228*f0865ec9SKyle Evans /* NOTE: for the CRYPTOFUZZ mode, we do not restart
229*f0865ec9SKyle Evans * the procedure but throw an assert exception instead.
230*f0865ec9SKyle Evans */
231*f0865ec9SKyle Evans ret = nn_iszero(&s, &iszero); EG(ret, err);
232*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err);
233*f0865ec9SKyle Evans
234*f0865ec9SKyle Evans /* 11. return (r,s) */
235*f0865ec9SKyle Evans ret = nn_export_to_buf(sig + q_len, q_len, &s);
236*f0865ec9SKyle Evans
237*f0865ec9SKyle Evans err:
238*f0865ec9SKyle Evans
239*f0865ec9SKyle Evans nn_uninit(&r);
240*f0865ec9SKyle Evans nn_uninit(&s);
241*f0865ec9SKyle Evans nn_uninit(&e);
242*f0865ec9SKyle Evans nn_uninit(&tmp);
243*f0865ec9SKyle Evans nn_uninit(&k);
244*f0865ec9SKyle Evans nn_uninit(&kinv);
245*f0865ec9SKyle Evans prj_pt_uninit(&kG);
246*f0865ec9SKyle Evans
247*f0865ec9SKyle Evans /*
248*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear
249*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context.
250*f0865ec9SKyle Evans */
251*f0865ec9SKyle Evans if(ctx != NULL){
252*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->sign_data.ecdsa), 0, sizeof(ecdsa_sign_data)));
253*f0865ec9SKyle Evans }
254*f0865ec9SKyle Evans
255*f0865ec9SKyle Evans /* Clean what remains on the stack */
256*f0865ec9SKyle Evans PTR_NULLIFY(priv_key);
257*f0865ec9SKyle Evans PTR_NULLIFY(G);
258*f0865ec9SKyle Evans PTR_NULLIFY(q);
259*f0865ec9SKyle Evans PTR_NULLIFY(x);
260*f0865ec9SKyle Evans VAR_ZEROIFY(q_len);
261*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len);
262*f0865ec9SKyle Evans VAR_ZEROIFY(rshift);
263*f0865ec9SKyle Evans VAR_ZEROIFY(hsize);
264*f0865ec9SKyle Evans
265*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
266*f0865ec9SKyle Evans nn_uninit(&b);
267*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */
268*f0865ec9SKyle Evans
269*f0865ec9SKyle Evans return ret;
270*f0865ec9SKyle Evans }
271*f0865ec9SKyle Evans
272*f0865ec9SKyle Evans /******************************/
273*f0865ec9SKyle Evans #define ECDSA_VERIFY_MAGIC ((word_t)(0x5155fe73e7fd51beULL))
274*f0865ec9SKyle Evans #define ECDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \
275*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == ECDSA_VERIFY_MAGIC), ret, err)
276*f0865ec9SKyle Evans
ecdsa_verify_raw(struct ec_verify_context * ctx,const u8 * input,u8 inputlen)277*f0865ec9SKyle Evans int ecdsa_verify_raw(struct ec_verify_context *ctx, const u8 *input, u8 inputlen)
278*f0865ec9SKyle Evans {
279*f0865ec9SKyle Evans prj_pt uG, vY;
280*f0865ec9SKyle Evans prj_pt_t W_prime;
281*f0865ec9SKyle Evans nn e, sinv, uv, r_prime;
282*f0865ec9SKyle Evans prj_pt_src_t G, Y;
283*f0865ec9SKyle Evans /* NOTE: hash here is not really a hash ... */
284*f0865ec9SKyle Evans u8 hash[LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8))];
285*f0865ec9SKyle Evans bitcnt_t rshift, q_bit_len;
286*f0865ec9SKyle Evans nn_src_t q;
287*f0865ec9SKyle Evans nn *s, *r;
288*f0865ec9SKyle Evans u8 hsize;
289*f0865ec9SKyle Evans int ret, iszero, cmp;
290*f0865ec9SKyle Evans
291*f0865ec9SKyle Evans e.magic = sinv.magic = uv.magic = r_prime.magic = WORD(0);
292*f0865ec9SKyle Evans uG.magic = vY.magic = WORD(0);
293*f0865ec9SKyle Evans
294*f0865ec9SKyle Evans /* NOTE: we reuse uG for W_prime to optimize local variables */
295*f0865ec9SKyle Evans W_prime = &uG;
296*f0865ec9SKyle Evans
297*f0865ec9SKyle Evans /*
298*f0865ec9SKyle Evans * First, verify context has been initialized and public
299*f0865ec9SKyle Evans * part too. This guarantees the context is an ECDSA
300*f0865ec9SKyle Evans * verification one and we do not finalize() before init().
301*f0865ec9SKyle Evans */
302*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err);
303*f0865ec9SKyle Evans ECDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecdsa), ret, err);
304*f0865ec9SKyle Evans MUST_HAVE((input != NULL), ret, err);
305*f0865ec9SKyle Evans
306*f0865ec9SKyle Evans /* Zero init points */
307*f0865ec9SKyle Evans ret = local_memset(&uG, 0, sizeof(prj_pt)); EG(ret, err);
308*f0865ec9SKyle Evans ret = local_memset(&vY, 0, sizeof(prj_pt)); EG(ret, err);
309*f0865ec9SKyle Evans
310*f0865ec9SKyle Evans /* Make things more readable */
311*f0865ec9SKyle Evans G = &(ctx->pub_key->params->ec_gen);
312*f0865ec9SKyle Evans Y = &(ctx->pub_key->y);
313*f0865ec9SKyle Evans q = &(ctx->pub_key->params->ec_gen_order);
314*f0865ec9SKyle Evans q_bit_len = ctx->pub_key->params->ec_gen_order_bitlen;
315*f0865ec9SKyle Evans hsize = inputlen;
316*f0865ec9SKyle Evans r = &(ctx->verify_data.ecdsa.r);
317*f0865ec9SKyle Evans s = &(ctx->verify_data.ecdsa.s);
318*f0865ec9SKyle Evans
319*f0865ec9SKyle Evans /* 2. Compute h = H(m) */
320*f0865ec9SKyle Evans /* NOTE: here we have raw ECDSA, this is the raw input */
321*f0865ec9SKyle Evans MUST_HAVE((input != NULL), ret, err);
322*f0865ec9SKyle Evans /* NOTE: the MUST_HAVE is protected by a preprocessing check
323*f0865ec9SKyle Evans * to avoid -Werror=type-limits errors:
324*f0865ec9SKyle Evans * "error: comparison is always true due to limited range of data type"
325*f0865ec9SKyle Evans */
326*f0865ec9SKyle Evans #if LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8)) < 255
327*f0865ec9SKyle Evans MUST_HAVE(((u32)inputlen <= sizeof(hash)), ret, err);
328*f0865ec9SKyle Evans #endif
329*f0865ec9SKyle Evans
330*f0865ec9SKyle Evans ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
331*f0865ec9SKyle Evans ret = local_memcpy(hash, input, hsize); EG(ret, err);
332*f0865ec9SKyle Evans
333*f0865ec9SKyle Evans dbg_buf_print("h = H(m)", hash, hsize);
334*f0865ec9SKyle Evans
335*f0865ec9SKyle Evans /*
336*f0865ec9SKyle Evans * 3. If |h| > bitlen(q), set h to bitlen(q)
337*f0865ec9SKyle Evans * leftmost bits of h.
338*f0865ec9SKyle Evans *
339*f0865ec9SKyle Evans * Note that it's easier to check here if the truncation
340*f0865ec9SKyle Evans * needs to be done but implement it using a logical
341*f0865ec9SKyle Evans * shift at the beginning of step 3. below once the hash
342*f0865ec9SKyle Evans * has been converted to an integer.
343*f0865ec9SKyle Evans */
344*f0865ec9SKyle Evans rshift = 0;
345*f0865ec9SKyle Evans if ((hsize * 8) > q_bit_len) {
346*f0865ec9SKyle Evans rshift = (bitcnt_t)((hsize * 8) - q_bit_len);
347*f0865ec9SKyle Evans }
348*f0865ec9SKyle Evans
349*f0865ec9SKyle Evans /*
350*f0865ec9SKyle Evans * 4. Compute e = OS2I(h) mod q, by converting h to an integer
351*f0865ec9SKyle Evans * and reducing it mod q
352*f0865ec9SKyle Evans */
353*f0865ec9SKyle Evans ret = nn_init_from_buf(&e, hash, hsize); EG(ret, err);
354*f0865ec9SKyle Evans ret = local_memset(hash, 0, hsize); EG(ret, err);
355*f0865ec9SKyle Evans dbg_nn_print("h initial import as nn", &e);
356*f0865ec9SKyle Evans if (rshift) {
357*f0865ec9SKyle Evans ret = nn_rshift_fixedlen(&e, &e, rshift); EG(ret, err);
358*f0865ec9SKyle Evans }
359*f0865ec9SKyle Evans dbg_nn_print("h final import as nn", &e);
360*f0865ec9SKyle Evans
361*f0865ec9SKyle Evans ret = nn_mod(&e, &e, q); EG(ret, err);
362*f0865ec9SKyle Evans dbg_nn_print("e", &e);
363*f0865ec9SKyle Evans
364*f0865ec9SKyle Evans /* Compute s^-1 mod q */
365*f0865ec9SKyle Evans ret = nn_modinv(&sinv, s, q); EG(ret, err);
366*f0865ec9SKyle Evans dbg_nn_print("s", s);
367*f0865ec9SKyle Evans dbg_nn_print("sinv", &sinv);
368*f0865ec9SKyle Evans nn_uninit(s);
369*f0865ec9SKyle Evans
370*f0865ec9SKyle Evans /* 5. Compute u = (s^-1)e mod q */
371*f0865ec9SKyle Evans ret = nn_mod_mul(&uv, &e, &sinv, q); EG(ret, err);
372*f0865ec9SKyle Evans dbg_nn_print("u = (s^-1)e mod q", &uv);
373*f0865ec9SKyle Evans ret = prj_pt_mul(&uG, &uv, G); EG(ret, err);
374*f0865ec9SKyle Evans
375*f0865ec9SKyle Evans /* 6. Compute v = (s^-1)r mod q */
376*f0865ec9SKyle Evans ret = nn_mod_mul(&uv, r, &sinv, q); EG(ret, err);
377*f0865ec9SKyle Evans dbg_nn_print("v = (s^-1)r mod q", &uv);
378*f0865ec9SKyle Evans ret = prj_pt_mul(&vY, &uv, Y); EG(ret, err);
379*f0865ec9SKyle Evans
380*f0865ec9SKyle Evans /* 7. Compute W' = uG + vY */
381*f0865ec9SKyle Evans ret = prj_pt_add(W_prime, &uG, &vY); EG(ret, err);
382*f0865ec9SKyle Evans
383*f0865ec9SKyle Evans /* 8. If W' is the point at infinity, reject the signature. */
384*f0865ec9SKyle Evans ret = prj_pt_iszero(W_prime, &iszero); EG(ret, err);
385*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err);
386*f0865ec9SKyle Evans
387*f0865ec9SKyle Evans /* 9. Compute r' = W'_x mod q */
388*f0865ec9SKyle Evans ret = prj_pt_unique(W_prime, W_prime); EG(ret, err);
389*f0865ec9SKyle Evans dbg_nn_print("W'_x", &(W_prime->X.fp_val));
390*f0865ec9SKyle Evans dbg_nn_print("W'_y", &(W_prime->Y.fp_val));
391*f0865ec9SKyle Evans ret = nn_mod(&r_prime, &(W_prime->X.fp_val), q); EG(ret, err);
392*f0865ec9SKyle Evans
393*f0865ec9SKyle Evans /* 10. Accept the signature if and only if r equals r' */
394*f0865ec9SKyle Evans ret = nn_cmp(&r_prime, r, &cmp); EG(ret, err);
395*f0865ec9SKyle Evans ret = (cmp != 0) ? -1 : 0;
396*f0865ec9SKyle Evans
397*f0865ec9SKyle Evans err:
398*f0865ec9SKyle Evans nn_uninit(&r_prime);
399*f0865ec9SKyle Evans nn_uninit(&uv);
400*f0865ec9SKyle Evans nn_uninit(&e);
401*f0865ec9SKyle Evans nn_uninit(&sinv);
402*f0865ec9SKyle Evans prj_pt_uninit(&uG);
403*f0865ec9SKyle Evans prj_pt_uninit(&vY);
404*f0865ec9SKyle Evans
405*f0865ec9SKyle Evans /*
406*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear
407*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context.
408*f0865ec9SKyle Evans */
409*f0865ec9SKyle Evans if(ctx != NULL){
410*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->verify_data.ecdsa), 0, sizeof(ecdsa_verify_data)));
411*f0865ec9SKyle Evans }
412*f0865ec9SKyle Evans
413*f0865ec9SKyle Evans /* Clean what remains on the stack */
414*f0865ec9SKyle Evans PTR_NULLIFY(W_prime);
415*f0865ec9SKyle Evans PTR_NULLIFY(G);
416*f0865ec9SKyle Evans PTR_NULLIFY(Y);
417*f0865ec9SKyle Evans VAR_ZEROIFY(rshift);
418*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len);
419*f0865ec9SKyle Evans PTR_NULLIFY(q);
420*f0865ec9SKyle Evans PTR_NULLIFY(s);
421*f0865ec9SKyle Evans PTR_NULLIFY(r);
422*f0865ec9SKyle Evans VAR_ZEROIFY(hsize);
423*f0865ec9SKyle Evans
424*f0865ec9SKyle Evans return ret;
425*f0865ec9SKyle Evans }
426*f0865ec9SKyle Evans
427*f0865ec9SKyle Evans
428*f0865ec9SKyle Evans #else /* WITH_SIG_ECDSA && USE_CRYPTOFUZZ */
429*f0865ec9SKyle Evans
430*f0865ec9SKyle Evans /*
431*f0865ec9SKyle Evans * Dummy definition to avoid the empty translation unit ISO C warning
432*f0865ec9SKyle Evans */
433*f0865ec9SKyle Evans typedef int dummy;
434*f0865ec9SKyle Evans #endif /* WITH_SIG_ECDSA */
435