/ external / libecc / src / sig / ecgdsa.c
ecgdsa.c
  1  /*
  2   *  Copyright (C) 2017 - This file is part of libecc project
  3   *
  4   *  Authors:
  5   *	Ryad BENADJILA <ryadbenadjila@gmail.com>
  6   *	Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
  7   *	Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
  8   *
  9   *  Contributors:
 10   *	Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
 11   *	Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
 12   *
 13   *  This software is licensed under a dual BSD and GPL v2 license.
 14   *  See LICENSE file at the root folder of the project.
 15   */
 16  #include <libecc/lib_ecc_config.h>
 17  #ifdef WITH_SIG_ECGDSA
 18  
 19  #include <libecc/nn/nn.h>
 20  #include <libecc/nn/nn_rand.h>
 21  #include <libecc/nn/nn_mul_public.h>
 22  #include <libecc/nn/nn_logical.h>
 23  
 24  #include <libecc/sig/sig_algs_internal.h>
 25  #include <libecc/sig/ec_key.h>
 26  #ifdef VERBOSE_INNER_VALUES
 27  #define EC_SIG_ALG "ECGDSA"
 28  #endif
 29  #include <libecc/utils/dbg_sig.h>
 30  
 31  int ecgdsa_init_pub_key(ec_pub_key *out_pub, const ec_priv_key *in_priv)
 32  {
 33  	prj_pt_src_t G;
 34  	nn_src_t q;
 35  	nn xinv;
 36  	int ret, cmp;
 37  	xinv.magic = WORD(0);
 38  
 39  	MUST_HAVE((out_pub != NULL), ret, err);
 40  
 41  	/* Zero init public key to be generated */
 42  	ret = local_memset(out_pub, 0, sizeof(ec_pub_key)); EG(ret, err);
 43  
 44  	ret = priv_key_check_initialized_and_type(in_priv, ECGDSA); EG(ret, err);
 45  	q = &(in_priv->params->ec_gen_order);
 46  
 47  	/* Sanity check on key */
 48  	MUST_HAVE((!nn_cmp(&(in_priv->x), q, &cmp)) && (cmp < 0), ret, err);
 49  
 50  	/* Y = (x^-1)G */
 51  	G = &(in_priv->params->ec_gen);
 52  	/* NOTE: we use Fermat's little theorem inversion for
 53  	 * constant time here. This is possible since q is prime.
 54  	 */
 55  	ret = nn_modinv_fermat(&xinv, &(in_priv->x), &(in_priv->params->ec_gen_order)); EG(ret, err);
 56  	/* Use blinding with scalar_b when computing point scalar multiplication */
 57  	ret = prj_pt_mul_blind(&(out_pub->y), &xinv, G); EG(ret, err);
 58  
 59  	out_pub->key_type = ECGDSA;
 60  	out_pub->params = in_priv->params;
 61  	out_pub->magic = PUB_KEY_MAGIC;
 62  
 63  err:
 64  	nn_uninit(&xinv);
 65  
 66  	return ret;
 67  }
 68  
 69  int ecgdsa_siglen(u16 p_bit_len, u16 q_bit_len, u8 hsize, u8 blocksize, u8 *siglen)
 70  {
 71  	int ret;
 72  
 73  	MUST_HAVE((siglen != NULL), ret, err);
 74  	MUST_HAVE((p_bit_len <= CURVES_MAX_P_BIT_LEN) &&
 75  		  (q_bit_len <= CURVES_MAX_Q_BIT_LEN) &&
 76  		  (hsize <= MAX_DIGEST_SIZE) && (blocksize <= MAX_BLOCK_SIZE), ret, err);
 77  
 78  	(*siglen) = (u8)ECGDSA_SIGLEN(q_bit_len);
 79  
 80  	ret = 0;
 81  
 82  err:
 83  	return ret;
 84  }
 85  
 86  /*
 87   * Generic *internal* EC-GDSA signature functions (init, update and finalize).
 88   * Their purpose is to allow passing a specific hash function (along with
 89   * its output size) and the random ephemeral key k, so that compliance
 90   * tests against test vectors can be made without ugly hack in the code
 91   * itself.
 92   *
 93   * Global EC-GDSA signature process is as follows (I,U,F provides
 94   * information in which function(s) (init(), update() or finalize())
 95   * a specific step is performed):
 96   *
 97   *| IUF - EC-GDSA signature
 98   *|
 99   *|  UF 1. Compute h = H(m). If |h| > bitlen(q), set h to bitlen(q)
100   *|	   leftmost (most significant) bits of h
101   *|   F 2. Compute e = - OS2I(h) mod q
102   *|   F 3. Get a random value k in ]0,q[
103   *|   F 4. Compute W = (W_x,W_y) = kG
104   *|   F 5. Compute r = W_x mod q
105   *|   F 6. If r is 0, restart the process at step 4.
106   *|   F 7. Compute s = x(kr + e) mod q
107   *|   F 8. If s is 0, restart the process at step 4.
108   *|   F 9. Return (r,s)
109   *
110   * Implementation notes:
111   *
112   * a) Usually (this is for instance the case in ISO 14888-3 and X9.62), the
113   *    process starts with steps 4 to 7 and is followed by steps 1 to 3.
114   *    The order is modified here w/o impact on the result and the security
115   *    in order to allow the algorithm to be compatible with an
116   *    init/update/finish API. More explicitly, the generation of k, which
117   *    may later result in a (unlikely) restart of the whole process is
118   *    postponed until the hash of the message has been computed.
119   * b) sig is built as the concatenation of r and s. Both r and s are
120   *    encoded on ceil(bitlen(q)/8) bytes.
121   * c) in EC-GDSA, the public part of the key is not needed per se during the
122   *    signature but - as it is needed in other signature algs implemented
123   *    in the library - the whole key pair is passed instead of just the
124   *    private key.
125   */
126  
127  #define ECGDSA_SIGN_MAGIC ((word_t)(0xe2f60ea3353ecc9eULL))
128  #define ECGDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \
129  	MUST_HAVE((((void *)(A)) != NULL) && \
130  		  ((A)->magic == ECGDSA_SIGN_MAGIC), ret, err)
131  
132  int _ecgdsa_sign_init(struct ec_sign_context *ctx)
133  {
134  	int ret;
135  
136  	/* First, verify context has been initialized */
137  	ret = sig_sign_check_initialized(ctx); EG(ret, err);
138  
139  	/* Additional sanity checks on input params from context */
140  	ret = key_pair_check_initialized_and_type(ctx->key_pair, ECGDSA); EG(ret, err);
141  	MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) &&
142  		  (ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err);
143  
144  	/*
145  	 * Initialize hash context stored in our private part of context
146  	 * and record data init has been done
147  	 */
148  	/* Since we call a callback, sanity check our mapping */
149  	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
150  	ret = ctx->h->hfunc_init(&(ctx->sign_data.ecgdsa.h_ctx)); EG(ret, err);
151  
152  	ctx->sign_data.ecgdsa.magic = ECGDSA_SIGN_MAGIC;
153  
154  err:
155  	return ret;
156  }
157  
158  int _ecgdsa_sign_update(struct ec_sign_context *ctx,
159  			const u8 *chunk, u32 chunklen)
160  {
161  	int ret;
162  
163  	/*
164  	 * First, verify context has been initialized and private
165  	 * part too. This guarantees the context is an EC-GDSA
166  	 * signature one and we do not update() or finalize()
167  	 * before init().
168  	 */
169  	ret = sig_sign_check_initialized(ctx); EG(ret, err);
170  	ECGDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecgdsa), ret, err);
171  
172  	/* 1. Compute h = H(m) */
173  	/* Since we call a callback, sanity check our mapping */
174  	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
175  	ret = ctx->h->hfunc_update(&(ctx->sign_data.ecgdsa.h_ctx), chunk, chunklen);
176  
177  err:
178  	return ret;
179  }
180  
181  int _ecgdsa_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen)
182  {
183  	nn_src_t q, x;
184  	u8 e_buf[MAX_DIGEST_SIZE];
185  	const ec_priv_key *priv_key;
186  	prj_pt_src_t G;
187  	u8 hsize, r_len, s_len;
188  	bitcnt_t q_bit_len, p_bit_len, rshift;
189  	prj_pt kG;
190  	int ret, cmp, iszero;
191  	nn tmp, s, e, kr, k, r;
192  #ifdef USE_SIG_BLINDING
193  	/* b is the blinding mask */
194  	nn b, binv;
195  	b.magic = binv.magic = WORD(0);
196  #endif
197  
198  	tmp.magic = s.magic = e.magic = WORD(0);
199  	kr.magic = k.magic = r.magic = WORD(0);
200  	kG.magic = WORD(0);
201  
202  	/*
203  	 * First, verify context has been initialized and private
204  	 * part too. This guarantees the context is an EC-GDSA
205  	 * signature one and we do not finalize() before init().
206  	 */
207  	ret = sig_sign_check_initialized(ctx); EG(ret, err);
208  	ECGDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecgdsa), ret, err);
209  	MUST_HAVE((sig != NULL), ret, err);
210  
211  	/* Zero init points */
212  	ret = local_memset(&kG, 0, sizeof(prj_pt)); EG(ret, err);
213  
214  	/* Make things more readable */
215  	priv_key = &(ctx->key_pair->priv_key);
216  	G = &(priv_key->params->ec_gen);
217  	q = &(priv_key->params->ec_gen_order);
218  	x = &(priv_key->x);
219  	q_bit_len = priv_key->params->ec_gen_order_bitlen;
220  	p_bit_len = priv_key->params->ec_fp.p_bitlen;
221  	MUST_HAVE(((u32)BYTECEIL(p_bit_len) <= NN_MAX_BYTE_LEN), ret, err);
222  	r_len = (u8)ECGDSA_R_LEN(q_bit_len);
223  	s_len = (u8)ECGDSA_S_LEN(q_bit_len);
224  	hsize = ctx->h->digest_size;
225  
226  	/* Sanity check */
227  	ret = nn_cmp(x, q, &cmp); EG(ret, err);
228  	/* This should not happen and means that our
229  	 * private key is not compliant!
230  	 */
231  	MUST_HAVE((cmp < 0), ret, err);
232  
233  	MUST_HAVE((siglen == ECGDSA_SIGLEN(q_bit_len)), ret, err);
234  
235  	dbg_nn_print("p", &(priv_key->params->ec_fp.p));
236  	dbg_nn_print("q", q);
237  	dbg_priv_key_print("x", priv_key);
238  	dbg_ec_point_print("G", G);
239  	dbg_pub_key_print("Y", &(ctx->key_pair->pub_key));
240  
241  	/* 1. Compute h = H(m) */
242  	ret = local_memset(e_buf, 0, hsize); EG(ret, err);
243  	/* Since we call a callback, sanity check our mapping */
244  	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
245  	ret = ctx->h->hfunc_finalize(&(ctx->sign_data.ecgdsa.h_ctx), e_buf); EG(ret, err);
246  	dbg_buf_print("H(m)", e_buf, hsize);
247  
248  	/*
249  	 * If |h| > bitlen(q), set h to bitlen(q)
250  	 * leftmost bits of h.
251  	 *
252  	 */
253  	rshift = 0;
254  	if ((hsize * 8) > q_bit_len) {
255  		rshift = (bitcnt_t)((hsize * 8) - q_bit_len);
256  	}
257  	ret = nn_init_from_buf(&tmp, e_buf, hsize); EG(ret, err);
258  	ret = local_memset(e_buf, 0, hsize); EG(ret, err);
259  	if (rshift) {
260  		ret = nn_rshift_fixedlen(&tmp, &tmp, rshift); EG(ret, err);
261  	}
262  	dbg_nn_print("H(m) truncated as nn", &tmp);
263  
264  	/*
265  	 * 2. Convert h to an integer and then compute e = -h mod q,
266  	 *    i.e. compute e = - OS2I(h) mod q
267  	 *
268  	 * Because we only support positive integers, we compute
269  	 * e = q - (h mod q) (except when h is 0).
270  	 */
271  	ret = nn_mod(&tmp, &tmp, q); EG(ret, err);
272  	ret = nn_mod_neg(&e, &tmp, q); EG(ret, err);
273  
274   restart:
275  	/* 3. Get a random value k in ]0,q[ */
276  #ifdef NO_KNOWN_VECTORS
277  	/* NOTE: when we do not need self tests for known vectors,
278  	 * we can be strict about random function handler!
279  	 * This allows us to avoid the corruption of such a pointer.
280  	 */
281  	/* Sanity check on the handler before calling it */
282  	MUST_HAVE(ctx->rand == nn_get_random_mod, ret, err);
283  #endif
284  	MUST_HAVE(ctx->rand != NULL, ret, err);
285  
286  	ret = ctx->rand(&k, q); EG(ret, err);
287  
288  #ifdef USE_SIG_BLINDING
289  	/* Note: if we use blinding, e and e are multiplied by
290  	 * a random value b in ]0,q[ */
291  	ret = nn_get_random_mod(&b, q); EG(ret, err);
292  	dbg_nn_print("b", &b);
293  #endif /* USE_SIG_BLINDING */
294  
295  	/* 4. Compute W = kG = (Wx, Wy) */
296  #ifdef USE_SIG_BLINDING
297  	/* We use blinding for the scalar multiplication */
298  	ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err);
299  #else
300  	ret = prj_pt_mul(&kG, &k, G); EG(ret, err);
301  #endif /* USE_SIG_BLINDING */
302  	ret = prj_pt_unique(&kG, &kG); EG(ret, err);
303  
304  	dbg_nn_print("W_x", &(kG.X.fp_val));
305  	dbg_nn_print("W_y", &(kG.Y.fp_val));
306  
307  	/* 5. Compute r = Wx mod q */
308  	ret = nn_mod(&r, &(kG.X.fp_val), q); EG(ret, err);
309  	dbg_nn_print("r", &r);
310  
311  	/* 6. If r is 0, restart the process at step 4. */
312  	ret = nn_iszero(&r, &iszero); EG(ret, err);
313  	if (iszero) {
314  		goto restart;
315  	}
316  
317  	/* Export r */
318  	ret = nn_export_to_buf(sig, r_len, &r); EG(ret, err);
319  
320  #ifdef USE_SIG_BLINDING
321  	/* Blind e and r with b */
322  	ret = nn_mod_mul(&e, &e, &b, q); EG(ret, err);
323  	ret = nn_mod_mul(&r, &r, &b, q); EG(ret, err);
324  #endif /* USE_SIG_BLINDING */
325  	/* 7. Compute s = x(kr + e) mod q */
326  	ret = nn_mod_mul(&kr, &k, &r, q); EG(ret, err);
327  	ret = nn_mod_add(&tmp, &kr, &e, q); EG(ret, err);
328  	ret = nn_mod_mul(&s, x, &tmp, q); EG(ret, err);
329  #ifdef USE_SIG_BLINDING
330  	/* Unblind s */
331  	/* NOTE: we use Fermat's little theorem inversion for
332  	 * constant time here. This is possible since q is prime.
333  	 */
334  	ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err);
335  	ret = nn_mod_mul(&s, &s, &binv, q); EG(ret, err);
336  #endif
337  	dbg_nn_print("s", &s);
338  
339  	/* 8. If s is 0, restart the process at step 4. */
340  	ret = nn_iszero(&s, &iszero); EG(ret, err);
341  	if (iszero) {
342  		goto restart;
343  	}
344  
345  	/* 9. Return (r,s) */
346  	ret = nn_export_to_buf(sig + r_len, s_len, &s);
347  
348   err:
349  	nn_uninit(&tmp);
350  	nn_uninit(&s);
351  	nn_uninit(&e);
352  	nn_uninit(&kr);
353  	nn_uninit(&k);
354  	nn_uninit(&r);
355  	prj_pt_uninit(&kG);
356  #ifdef USE_SIG_BLINDING
357  	nn_uninit(&b);
358  	nn_uninit(&binv);
359  #endif
360  
361  	/*
362  	 * We can now clear data part of the context. This will clear
363  	 * magic and avoid further reuse of the whole context.
364  	 */
365  	if(ctx != NULL){
366  		IGNORE_RET_VAL(local_memset(&(ctx->sign_data.ecgdsa), 0, sizeof(ecgdsa_sign_data)));
367  	}
368  
369  	/* Clean what remains on the stack */
370  	VAR_ZEROIFY(q_bit_len);
371  	VAR_ZEROIFY(p_bit_len);
372  	VAR_ZEROIFY(r_len);
373  	VAR_ZEROIFY(s_len);
374  	VAR_ZEROIFY(hsize);
375  	PTR_NULLIFY(q);
376  	PTR_NULLIFY(x);
377  	PTR_NULLIFY(priv_key);
378  	PTR_NULLIFY(G);
379  
380  	return ret;
381  }
382  
383  /*
384   * Generic *internal* EC-GDSA verification functions (init, update and finalize).
385   * Their purpose is to allow passing a specific hash function (along with
386   * their output size) and the random ephemeral key k, so that compliance
387   * tests against test vectors can be made without ugly hack in the code
388   * itself.
389   *
390   * Global EC-GDSA verification process is as follows (I,U,F provides
391   * information in which function(s) (init(), update() or finalize())
392   * a specific step is performed):
393   *
394   *| IUF - EC-GDSA verification
395   *|
396   *| I	1. Reject the signature if r or s is 0.
397   *|  UF 2. Compute h = H(m). If |h| > bitlen(q), set h to bitlen(q)
398   *|	   leftmost (most significant) bits of h
399   *|   F 3. Compute e = OS2I(h) mod q
400   *|   F 4. Compute u = ((r^-1)e mod q)
401   *|   F 5. Compute v = ((r^-1)s mod q)
402   *|   F 6. Compute W' = uG + vY
403   *|   F 7. Compute r' = W'_x mod q
404   *|   F 8. Accept the signature if and only if r equals r'
405   *
406   */
407  
408  #define ECGDSA_VERIFY_MAGIC ((word_t)(0xd4da37527288d1b6ULL))
409  #define ECGDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \
410  	MUST_HAVE((((void *)(A)) != NULL) && \
411  		  ((A)->magic == ECGDSA_VERIFY_MAGIC), ret, err)
412  
413  int _ecgdsa_verify_init(struct ec_verify_context *ctx,
414  			const u8 *sig, u8 siglen)
415  {
416  	u8 r_len, s_len;
417  	bitcnt_t q_bit_len;
418  	nn_src_t q;
419  	nn *s, *r;
420  	int ret, iszero1, iszero2, cmp1, cmp2;
421  
422  	/* First, verify context has been initialized */
423  	ret = sig_verify_check_initialized(ctx); EG(ret, err);
424  
425  	/* Do some sanity checks on input params */
426  	ret = pub_key_check_initialized_and_type(ctx->pub_key, ECGDSA); EG(ret, err);
427  	MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) &&
428  		(ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err);
429  	MUST_HAVE((sig != NULL), ret, err);
430  
431  	/* Make things more readable */
432  	q = &(ctx->pub_key->params->ec_gen_order);
433  	q_bit_len = ctx->pub_key->params->ec_gen_order_bitlen;
434  	r = &(ctx->verify_data.ecgdsa.r);
435  	s = &(ctx->verify_data.ecgdsa.s);
436  	r_len = (u8)ECGDSA_R_LEN(q_bit_len);
437  	s_len = (u8)ECGDSA_S_LEN(q_bit_len);
438  
439  	/* Check given signature length is the expected one */
440  	MUST_HAVE((siglen == ECGDSA_SIGLEN(q_bit_len)), ret, err);
441  
442  	/* 1. Reject the signature if r or s is 0. */
443  
444  	/* Let's first import r, the x coordinates of the point reduced mod q */
445  	ret = nn_init_from_buf(r, sig, r_len); EG(ret, err);
446  
447  	/* Import s as a nn */
448  	ret = nn_init_from_buf(s, sig + r_len, s_len); EG(ret, err);
449  
450  	/* Check that r and s are both in ]0,q[ */
451  	ret = nn_iszero(s, &iszero1); EG(ret, err);
452  	ret = nn_iszero(r, &iszero2); EG(ret, err);
453  	ret = nn_cmp(s, q, &cmp1); EG(ret, err);
454  	ret = nn_cmp(r, q, &cmp2); EG(ret, err);
455  
456  	MUST_HAVE((!iszero1) && (cmp1 < 0) && (!iszero2) && (cmp2 < 0), ret, err);
457  
458  	/* Initialize the remaining of verify context */
459  	/* Since we call a callback, sanity check our mapping */
460  	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
461  	ret = ctx->h->hfunc_init(&(ctx->verify_data.ecgdsa.h_ctx)); EG(ret, err);
462  
463  	ctx->verify_data.ecgdsa.magic = ECGDSA_VERIFY_MAGIC;
464  
465   err:
466  	VAR_ZEROIFY(q_bit_len);
467  	VAR_ZEROIFY(r_len);
468  	VAR_ZEROIFY(s_len);
469  	PTR_NULLIFY(q);
470  	PTR_NULLIFY(s);
471  	PTR_NULLIFY(r);
472  
473  	return ret;
474  }
475  
476  int _ecgdsa_verify_update(struct ec_verify_context *ctx,
477  			  const u8 *chunk, u32 chunklen)
478  {
479  	int ret;
480  
481  	/*
482  	 * First, verify context has been initialized and public
483  	 * part too. This guarantees the context is an EC-GDSA
484  	 * verification one and we do not update() or finalize()
485  	 * before init().
486  	 */
487  	ret = sig_verify_check_initialized(ctx); EG(ret, err);
488  	ECGDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecgdsa), ret, err);
489  
490  	/* 2. Compute h = H(m) */
491  	/* Since we call a callback, sanity check our mapping */
492  	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
493  	ret = ctx->h->hfunc_update(&(ctx->verify_data.ecgdsa.h_ctx), chunk,
494  			     chunklen);
495  
496  err:
497  	return ret;
498  }
499  
500  int _ecgdsa_verify_finalize(struct ec_verify_context *ctx)
501  {
502  	nn e, r_prime, rinv, uv, *r, *s;
503  	prj_pt uG, vY;
504  	prj_pt_t Wprime;
505  	prj_pt_src_t G, Y;
506  	u8 e_buf[MAX_DIGEST_SIZE];
507  	nn_src_t q;
508  	u8 hsize;
509  	bitcnt_t q_bit_len, rshift;
510  	int ret, cmp;
511  
512  	e.magic = r_prime.magic = WORD(0);
513  	rinv.magic = uv.magic = WORD(0);
514  	uG.magic = vY.magic = WORD(0);
515  
516  	/* NOTE: we reuse uG for Wprime to optimize local variables */
517  	Wprime = &uG;
518  
519  	/*
520  	 * First, verify context has been initialized and public
521  	 * part too. This guarantees the context is an EC-GDSA
522  	 * verification one and we do not finalize() before init().
523  	 */
524  	ret = sig_verify_check_initialized(ctx); EG(ret, err);
525  	ECGDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecgdsa), ret, err);
526  
527  	/* Zero init points */
528  	ret = local_memset(&uG, 0, sizeof(prj_pt)); EG(ret, err);
529  	ret = local_memset(&vY, 0, sizeof(prj_pt)); EG(ret, err);
530  
531  	/* Make things more readable */
532  	G = &(ctx->pub_key->params->ec_gen);
533  	Y = &(ctx->pub_key->y);
534  	q = &(ctx->pub_key->params->ec_gen_order);
535  	r = &(ctx->verify_data.ecgdsa.r);
536  	s = &(ctx->verify_data.ecgdsa.s);
537  	q_bit_len = ctx->pub_key->params->ec_gen_order_bitlen;
538  	hsize = ctx->h->digest_size;
539  
540  	/* 2. Compute h = H(m) */
541  	/* Since we call a callback, sanity check our mapping */
542  	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
543  	ret = ctx->h->hfunc_finalize(&(ctx->verify_data.ecgdsa.h_ctx), e_buf); EG(ret, err);
544  	dbg_buf_print("H(m)", e_buf, hsize);
545  
546  	/*
547  	 * If |h| > bitlen(q), set h to bitlen(q)
548  	 * leftmost bits of h.
549  	 *
550  	 */
551  	rshift = 0;
552  	if ((hsize * 8) > q_bit_len) {
553  		rshift = (bitcnt_t)((hsize * 8) - q_bit_len);
554  	}
555  	ret = nn_init_from_buf(&e, e_buf, hsize); EG(ret, err);
556  	ret = local_memset(e_buf, 0, hsize); EG(ret, err);
557  	if (rshift) {
558  		ret = nn_rshift_fixedlen(&e, &e, rshift); EG(ret, err);
559  	}
560  	dbg_nn_print("H(m) truncated as nn", &e);
561  
562  	/* 3. Compute e by converting h to an integer and reducing it mod q */
563  	ret = nn_mod(&e, &e, q); EG(ret, err);
564  
565  	/* 4. Compute u = (r^-1)e mod q */
566  	ret = nn_modinv(&rinv, r, q); EG(ret, err); /* r^-1 */
567  	ret = nn_mod_mul(&uv, &rinv, &e, q); EG(ret, err);
568  	ret = prj_pt_mul(&uG, &uv, G); EG(ret, err);
569  
570  	/* 5. Compute v = (r^-1)s mod q */
571  	ret = nn_mod_mul(&uv, &rinv, s, q); EG(ret, err);
572  	ret = prj_pt_mul(&vY, &uv, Y); EG(ret, err);
573  
574  	/* 6. Compute W' = uG + vY */
575  	ret = prj_pt_add(Wprime, &uG, &vY); EG(ret, err);
576  
577  	/* 7. Compute r' = W'_x mod q */
578  	ret = prj_pt_unique(Wprime, Wprime); EG(ret, err);
579  	dbg_nn_print("W'_x", &(Wprime->X.fp_val));
580  	dbg_nn_print("W'_y", &(Wprime->Y.fp_val));
581  	ret = nn_mod(&r_prime, &(Wprime->X.fp_val), q); EG(ret, err);
582  
583  	/* 8. Accept the signature if and only if r equals r' */
584  	ret = nn_cmp(r, &r_prime, &cmp); EG(ret, err);
585  	ret = (cmp != 0) ? -1 : 0;
586  
587  err:
588  	nn_uninit(&e);
589  	nn_uninit(&r_prime);
590  	nn_uninit(&rinv);
591  	nn_uninit(&uv);
592  	prj_pt_uninit(&uG);
593  	prj_pt_uninit(&vY);
594  
595  	/*
596  	 * We can now clear data part of the context. This will clear
597  	 * magic and avoid further reuse of the whole context.
598  	 */
599  	if(ctx != NULL){
600  		IGNORE_RET_VAL(local_memset(&(ctx->verify_data.ecgdsa), 0,
601  			     sizeof(ecgdsa_verify_data)));
602  	}
603  
604  	PTR_NULLIFY(Wprime);
605  	PTR_NULLIFY(r);
606  	PTR_NULLIFY(s);
607  	PTR_NULLIFY(G);
608  	PTR_NULLIFY(Y);
609  	PTR_NULLIFY(q);
610  	VAR_ZEROIFY(hsize);
611  
612  	return ret;
613  }
614  
615  #else /* WITH_SIG_ECGDSA */
616  
617  /*
618   * Dummy definition to avoid the empty translation unit ISO C warning
619   */
620  typedef int dummy;
621  #endif /* WITH_SIG_ECGDSA */