xref: /freebsd/crypto/libecc/src/nn/nn_div.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
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/nn/nn_mul_public.h>
17 #include <libecc/nn/nn_logical.h>
18 #include <libecc/nn/nn_add.h>
19 #include <libecc/nn/nn.h>
20 /* Use internal API header */
21 #include "nn_div.h"
22 
23 /*
24  * Some helper functions to perform operations on an arbitrary part
25  * of a multiprecision number.
26  * This is exactly the same code as for operations on the least significant
27  * part of a multiprecision number except for the starting point in the
28  * array representing it.
29  * Done in *constant time*.
30  *
31  * Operations producing an output are in place.
32  */
33 
34 /*
35  * Compare all the bits of in2 with the same number of bits in in1 starting at
36  * 'shift' position in in1. in1 must be long enough for that purpose, i.e.
37  * in1->wlen >= (in2->wlen + shift). The comparison value is provided in
38  * 'cmp' parameter. The function returns 0 on success, -1 on error.
39  *
40  * The function is an internal helper; it expects initialized nn in1 and
41  * in2: it does not verify that.
42  */
_nn_cmp_shift(nn_src_t in1,nn_src_t in2,u8 shift,int * cmp)43 ATTRIBUTE_WARN_UNUSED_RET static int _nn_cmp_shift(nn_src_t in1, nn_src_t in2, u8 shift, int *cmp)
44 {
45 	int ret, mask, tmp;
46 	u8 i;
47 
48 	MUST_HAVE((in1->wlen >= (in2->wlen + shift)), ret, err);
49 	MUST_HAVE((cmp != NULL), ret, err);
50 
51 	tmp = 0;
52 	for (i = in2->wlen; i > 0; i--) {
53 		mask = (!(tmp & 0x1));
54 		tmp += ((in1->val[shift + i - 1] > in2->val[i - 1]) & mask);
55 		tmp -= ((in1->val[shift + i - 1] < in2->val[i - 1]) & mask);
56 	}
57 	(*cmp) = tmp;
58 	ret = 0;
59 
60 err:
61 	return ret;
62 }
63 
64 /*
65  * Conditionally subtract a shifted version of in from out, i.e.:
66  *   - if cnd == 1, out <- out - (in << shift)
67  *   - if cnd == 0, out <- out
68  * The function returns 0 on success, -1 on error. On success, 'borrow'
69  * provides the possible borrow resulting from the subtraction. 'borrow'
70  * is not meaningful on error.
71  *
72  * The function is an internal helper; it expects initialized nn out and
73  * in: it does not verify that.
74  */
_nn_cnd_sub_shift(int cnd,nn_t out,nn_src_t in,u8 shift,word_t * borrow)75 ATTRIBUTE_WARN_UNUSED_RET static int _nn_cnd_sub_shift(int cnd, nn_t out, nn_src_t in,
76 			    u8 shift, word_t *borrow)
77 {
78 	word_t tmp, borrow1, borrow2, _borrow = WORD(0);
79 	word_t mask = WORD_MASK_IFNOTZERO(cnd);
80 	int ret;
81 	u8 i;
82 
83 	MUST_HAVE((out->wlen >= (in->wlen + shift)), ret, err);
84 	MUST_HAVE((borrow != NULL), ret, err);
85 
86 	/*
87 	 *  Perform subtraction one word at a time,
88 	 *  propagating the borrow.
89 	 */
90 	for (i = 0; i < in->wlen; i++) {
91 		tmp = (word_t)(out->val[shift + i] - (in->val[i] & mask));
92 		borrow1 = (word_t)(tmp > out->val[shift + i]);
93 		out->val[shift + i] = (word_t)(tmp - _borrow);
94 		borrow2 = (word_t)(out->val[shift + i] > tmp);
95 		/* There is at most one borrow going out. */
96 		_borrow = (word_t)(borrow1 | borrow2);
97 	}
98 
99 	(*borrow) = _borrow;
100 	ret = 0;
101 
102 err:
103 	return ret;
104 }
105 
106 /*
107  * Subtract a shifted version of 'in' multiplied by 'w' from 'out' and return
108  * borrow. The function returns 0 on success, -1 on error. 'borrow' is
109  * meaningful only on success.
110  *
111  * The function is an internal helper; it expects initialized nn out and
112  * in: it does not verify that.
113  */
_nn_submul_word_shift(nn_t out,nn_src_t in,word_t w,u8 shift,word_t * borrow)114 ATTRIBUTE_WARN_UNUSED_RET static int _nn_submul_word_shift(nn_t out, nn_src_t in, word_t w, u8 shift,
115 				word_t *borrow)
116 {
117 	word_t _borrow = WORD(0), prod_high, prod_low, tmp;
118 	int ret;
119 	u8 i;
120 
121 	MUST_HAVE((out->wlen >= (in->wlen + shift)), ret, err);
122 	MUST_HAVE((borrow != NULL), ret, err);
123 
124 	for (i = 0; i < in->wlen; i++) {
125 		/*
126 		 * Compute the result of the multiplication of
127 		 * two words.
128 		 */
129 		WORD_MUL(prod_high, prod_low, in->val[i], w);
130 
131 		/*
132 		 * And add previous borrow.
133 		 */
134 		prod_low = (word_t)(prod_low + _borrow);
135 		prod_high = (word_t)(prod_high + (prod_low < _borrow));
136 
137 		/*
138 		 * Subtract computed word at current position in result.
139 		 */
140 		tmp = (word_t)(out->val[shift + i] - prod_low);
141 		_borrow = (word_t)(prod_high + (tmp > out->val[shift + i]));
142 		out->val[shift + i] = tmp;
143 	}
144 
145 	(*borrow) = _borrow;
146 	ret = 0;
147 
148 err:
149 	return ret;
150 }
151 
152 /*
153  * Compute quotient 'q' and remainder 'r' of Euclidean division of 'a' by 'b'
154  * (i.e. q and r such that a = b*q + r). 'q' and 'r' are not normalized on
155  * return. * Computation are performed in *constant time*, only depending on
156  * the lengths of 'a' and 'b', but not on the values of 'a' and 'b'.
157  *
158  * This uses the above function to perform arithmetic on arbitrary parts
159  * of multiprecision numbers.
160  *
161  * The algorithm used is schoolbook division:
162  * + the quotient is computed word by word,
163  * + a small division of the MSW is performed to obtain an
164  *   approximation of the MSW of the quotient,
165  * + the approximation is corrected to obtain the correct
166  *   multiprecision MSW of the quotient,
167  * + the corresponding product is subtracted from the dividend,
168  * + the same procedure is used for the following word of the quotient.
169  *
170  * It is assumed that:
171  * + b is normalized: the MSB of its MSW is 1,
172  * + the most significant part of a is smaller than b,
173  * + a precomputed reciprocal
174  *     v = floor(B^3/(d+1)) - B
175  *   where d is the MSW of the (normalized) divisor
176  *   is given to perform the small 3-by-2 division.
177  * + using this reciprocal, the approximated quotient is always
178  *   too small and at most one multiprecision correction is needed.
179  *
180  * It returns 0 on sucess, -1 on error.
181  *
182  * CAUTION:
183  *
184  * - The function is expected to be used ONLY by the generic version
185  *   nn_divrem_normalized() defined later in the file.
186  * - All parameters must have been initialized. Unlike exported/public
187  *   functions, this internal helper does not verify that nn parameters
188  *   have been initialized. Again, this is expected from the caller
189  *   (nn_divrem_normalized()).
190  * - The function does not support aliasing of 'b' or 'q'. See
191  *   _nn_divrem_normalized_aliased() for such a wrapper.
192  *
193  */
_nn_divrem_normalized(nn_t q,nn_t r,nn_src_t a,nn_src_t b,word_t v)194 ATTRIBUTE_WARN_UNUSED_RET static int _nn_divrem_normalized(nn_t q, nn_t r,
195 				 nn_src_t a, nn_src_t b, word_t v)
196 {
197 	word_t borrow, qstar, qh, ql, rh, rl; /* for 3-by-2 div. */
198 	int _small, cmp, ret;
199 	u8 i;
200 
201 	MUST_HAVE(!(b->wlen <= 0), ret, err);
202 	MUST_HAVE(!(a->wlen <= b->wlen), ret, err);
203 	MUST_HAVE(!(!((b->val[b->wlen - 1] >> (WORD_BITS - 1)) == WORD(1))), ret, err);
204 	MUST_HAVE(!_nn_cmp_shift(a, b, (u8)(a->wlen - b->wlen), &cmp) && (cmp < 0), ret, err);
205 
206 	/* Handle trivial aliasing for a and r */
207 	if (r != a) {
208 		ret = nn_set_wlen(r, a->wlen); EG(ret, err);
209 		ret = nn_copy(r, a); EG(ret, err);
210 	}
211 
212 	ret = nn_set_wlen(q, (u8)(r->wlen - b->wlen)); EG(ret, err);
213 
214 	/*
215 	 * Compute subsequent words of the quotient one by one.
216 	 * Perform approximate 3-by-2 division using the precomputed
217 	 * reciprocal and correct afterward.
218 	 */
219 	for (i = r->wlen; i > b->wlen; i--) {
220 		u8 shift = (u8)(i - b->wlen - 1);
221 
222 		/*
223 		 * Perform 3-by-2 approximate division:
224 		 * <qstar, qh, ql> = <rh, rl> * (v + B)
225 		 * We are only interested in qstar.
226 		 */
227 		rh = r->val[i - 1];
228 		rl = r->val[i - 2];
229 		/* Perform 2-by-1 multiplication. */
230 		WORD_MUL(qh, ql, rl, v);
231 		WORD_MUL(qstar, ql, rh, v);
232 		/* And propagate carries. */
233 		qh = (word_t)(qh + ql);
234 		qstar = (word_t)(qstar + (qh < ql));
235 		qh = (word_t)(qh + rl);
236 		rh = (word_t)(rh + (qh < rl));
237 		qstar = (word_t)(qstar + rh);
238 
239 		/*
240 		 * Compute approximate quotient times divisor
241 		 * and subtract it from remainder:
242 		 * r = r - (b*qstar << B^shift)
243 		 */
244 		ret = _nn_submul_word_shift(r, b, qstar, shift, &borrow); EG(ret, err);
245 
246 		/* Check the approximate quotient was indeed not too large. */
247 		MUST_HAVE(!(r->val[i - 1] < borrow), ret, err);
248 		r->val[i - 1] = (word_t)(r->val[i - 1] - borrow);
249 
250 		/*
251 		 * Check whether the approximate quotient was too small or not.
252 		 * At most one multiprecision correction is needed.
253 		 */
254 		ret = _nn_cmp_shift(r, b, shift, &cmp); EG(ret, err);
255 		_small = ((!!(r->val[i - 1])) | (cmp >= 0));
256 		/* Perform conditional multiprecision correction. */
257 		ret = _nn_cnd_sub_shift(_small, r, b, shift, &borrow); EG(ret, err);
258 		MUST_HAVE(!(r->val[i - 1] != borrow), ret, err);
259 		r->val[i - 1] = (word_t)(r->val[i - 1] - borrow);
260 		/*
261 		 * Adjust the quotient if it was too small and set it in the
262 		 * multiprecision array.
263 		 */
264 		qstar = (word_t)(qstar + (word_t)_small);
265 		q->val[shift] = qstar;
266 		/*
267 		 * Check that the MSW of remainder was cancelled out and that
268 		 * we could not increase the quotient anymore.
269 		 */
270 		MUST_HAVE(!(r->val[r->wlen - 1] != WORD(0)), ret, err);
271 
272 		ret = _nn_cmp_shift(r, b, shift, &cmp); EG(ret, err);
273 		MUST_HAVE(!(cmp >= 0), ret, err);
274 
275 		ret = nn_set_wlen(r, (u8)(r->wlen - 1)); EG(ret, err);
276 	}
277 
278 err:
279 	return ret;
280 }
281 
282 /*
283  * Compute quotient 'q' and remainder 'r' of Euclidean division of 'a' by 'b'
284  * (i.e. q and r such that a = b*q + r). 'q' and 'r' are not normalized.
285  * Compared to _nn_divrem_normalized(), this internal version
286  * explicitly handle the case where 'b' and 'r' point to the same nn (i.e. 'r'
287  * result is stored in 'b' on success), hence the removal of 'r' parameter from
288  * function prototype compared to _nn_divrem_normalized().
289  *
290  * The computation is performed in *constant time*, see documentation of
291  * _nn_divrem_normalized().
292  *
293  * Assume that 'b' is normalized (the MSB of its MSW is set), that 'v' is the
294  * reciprocal of the MSW of 'b' and that the high part of 'a' is smaller than
295  * 'b'.
296  *
297  * The function returns 0 on success, -1 on error.
298  *
299  * CAUTION:
300  *
301  * - The function is expected to be used ONLY by the generic version
302  *   nn_divrem_normalized() defined later in the file.
303  * - All parameters must have been initialized. Unlike exported/public
304  *   functions, this internal helper does not verify that nn parameters
305  *   have been initialized. Again, this is expected from the caller
306  *   (nn_divrem_normalized()).
307  * - The function does not support aliasing of 'a' or 'q'.
308  *
309  */
_nn_divrem_normalized_aliased(nn_t q,nn_src_t a,nn_t b,word_t v)310 ATTRIBUTE_WARN_UNUSED_RET static int _nn_divrem_normalized_aliased(nn_t q, nn_src_t a, nn_t b, word_t v)
311 {
312 	int ret;
313 	nn r;
314 	r.magic = WORD(0);
315 
316 	ret = nn_init(&r, 0); EG(ret, err);
317 	ret = _nn_divrem_normalized(q, &r, a, b, v); EG(ret, err);
318 	ret = nn_copy(b, &r); EG(ret, err);
319 
320 err:
321 	nn_uninit(&r);
322 	return ret;
323 }
324 
325 /*
326  * Compute quotient and remainder of Euclidean division, and do not normalize
327  * them. Done in *constant time*, see documentation of _nn_divrem_normalized().
328  *
329  * Assume that 'b' is normalized (the MSB of its MSW is set), that 'v' is the
330  * reciprocal of the MSW of 'b' and that the high part of 'a' is smaller than
331  * 'b'.
332  *
333  * Aliasing is supported for 'r' only (with 'b'), i.e. 'r' and 'b' can point
334  * to the same nn.
335  *
336  * The function returns 0 on success, -1 on error.
337  */
nn_divrem_normalized(nn_t q,nn_t r,nn_src_t a,nn_src_t b,word_t v)338 int nn_divrem_normalized(nn_t q, nn_t r, nn_src_t a, nn_src_t b, word_t v)
339 {
340 	int ret;
341 
342 	ret = nn_check_initialized(a); EG(ret, err);
343 	ret = nn_check_initialized(q); EG(ret, err);
344 	ret = nn_check_initialized(r); EG(ret, err);
345 
346 	/* Unsupported aliasings */
347 	MUST_HAVE((q != r) && (q != a) && (q != b), ret, err);
348 
349 	if (r == b) {
350 		ret = _nn_divrem_normalized_aliased(q, a, r, v);
351 	} else {
352 		ret = nn_check_initialized(b); EG(ret, err);
353 		ret = _nn_divrem_normalized(q, r, a, b, v);
354 	}
355 
356 err:
357 	return ret;
358 }
359 
360 /*
361  * Compute remainder only and do not normalize it.
362  * Constant time, see documentation of _nn_divrem_normalized.
363  *
364  * Support aliasing of inputs and outputs.
365  *
366  * The function returns 0 on success, -1 on error.
367  */
nn_mod_normalized(nn_t r,nn_src_t a,nn_src_t b,word_t v)368 int nn_mod_normalized(nn_t r, nn_src_t a, nn_src_t b, word_t v)
369 {
370 	int ret;
371 	nn q;
372 	q.magic = WORD(0);
373 
374 	ret = nn_init(&q, 0); EG(ret, err);
375 	ret = nn_divrem_normalized(&q, r, a, b, v);
376 
377 err:
378 	nn_uninit(&q);
379 	return ret;
380 }
381 
382 /*
383  * Compute quotient and remainder of Euclidean division,
384  * and do not normalize them.
385  * Done in *constant time*,
386  * only depending on the lengths of 'a' and 'b' and the value of 'cnt',
387  * but not on the values of 'a' and 'b'.
388  *
389  * Assume that b has been normalized by a 'cnt' bit shift,
390  * that v is the reciprocal of the MSW of 'b',
391  * but a is not shifted yet.
392  * Useful when multiple multiplication by the same b are performed,
393  * e.g. at the fp level.
394  *
395  * All outputs MUST have been initialized. The function does not support
396  * aliasing of 'b' or 'q'. It returns 0 on success, -1 on error.
397  *
398  * CAUTION:
399  *
400  * - The function is expected to be used ONLY by the generic version
401  *   nn_divrem_normalized() defined later in the file.
402  * - All parameters must have been initialized. Unlike exported/public
403  *   functions, this internal helper does not verify that
404  *   have been initialized. Again, this is expected from the caller
405  *   (nn_divrem_unshifted()).
406  * - The function does not support aliasing. See
407  *   _nn_divrem_unshifted_aliased() for such a wrapper.
408  */
_nn_divrem_unshifted(nn_t q,nn_t r,nn_src_t a,nn_src_t b_norm,word_t v,bitcnt_t cnt)409 ATTRIBUTE_WARN_UNUSED_RET static int _nn_divrem_unshifted(nn_t q, nn_t r, nn_src_t a, nn_src_t b_norm,
410 				word_t v, bitcnt_t cnt)
411 {
412 	nn a_shift;
413 	u8 new_wlen, b_wlen;
414 	int larger, ret, cmp;
415 	word_t borrow;
416 	a_shift.magic = WORD(0);
417 
418 	/* Avoid overflow */
419 	MUST_HAVE(((a->wlen + BIT_LEN_WORDS(cnt)) < NN_MAX_WORD_LEN), ret, err);
420 
421 	/* We now know that new_wlen will fit in an u8 */
422 	new_wlen = (u8)(a->wlen + (u8)BIT_LEN_WORDS(cnt));
423 
424 	b_wlen = b_norm->wlen;
425 	if (new_wlen < b_wlen) { /* trivial case */
426 		ret = nn_copy(r, a); EG(ret, err);
427 		ret = nn_zero(q);
428 		goto err;
429 	}
430 
431 	/* Shift a. */
432 	ret = nn_init(&a_shift, (u16)(new_wlen * WORD_BYTES)); EG(ret, err);
433 	ret = nn_set_wlen(&a_shift, new_wlen); EG(ret, err);
434 	ret = nn_lshift_fixedlen(&a_shift, a, cnt); EG(ret, err);
435 	ret = nn_set_wlen(r, new_wlen); EG(ret, err);
436 
437 	if (new_wlen == b_wlen) {
438 		/* Ensure that a is smaller than b. */
439 		ret = nn_cmp(&a_shift, b_norm, &cmp); EG(ret, err);
440 		larger = (cmp >= 0);
441 		ret = nn_cnd_sub(larger, r, &a_shift, b_norm); EG(ret, err);
442 		MUST_HAVE(((!nn_cmp(r, b_norm, &cmp)) && (cmp < 0)), ret, err);
443 
444 		/* Set MSW of quotient. */
445 		ret = nn_set_wlen(q, (u8)(new_wlen - b_wlen + 1)); EG(ret, err);
446 		q->val[new_wlen - b_wlen] = (word_t) larger;
447 		/* And we are done as the quotient is 0 or 1. */
448 	} else if (new_wlen > b_wlen) {
449 		/* Ensure that most significant part of a is smaller than b. */
450 		ret = _nn_cmp_shift(&a_shift, b_norm, (u8)(new_wlen - b_wlen), &cmp); EG(ret, err);
451 		larger = (cmp >= 0);
452 		ret = _nn_cnd_sub_shift(larger, &a_shift, b_norm, (u8)(new_wlen - b_wlen), &borrow); EG(ret, err);
453 		MUST_HAVE(((!_nn_cmp_shift(&a_shift, b_norm, (u8)(new_wlen - b_wlen), &cmp)) && (cmp < 0)), ret, err);
454 
455 		/*
456 		 * Perform division with MSP of a smaller than b. This ensures
457 		 * that the quotient is of length a_len - b_len.
458 		 */
459 		ret = nn_divrem_normalized(q, r, &a_shift, b_norm, v); EG(ret, err);
460 
461 		/* Set MSW of quotient. */
462 		ret = nn_set_wlen(q, (u8)(new_wlen - b_wlen + 1)); EG(ret, err);
463 		q->val[new_wlen - b_wlen] = (word_t) larger;
464 	} /* else a is smaller than b... treated above. */
465 
466 	ret = nn_rshift_fixedlen(r, r, cnt); EG(ret, err);
467 	ret = nn_set_wlen(r, b_wlen);
468 
469 err:
470 	nn_uninit(&a_shift);
471 
472 	return ret;
473 }
474 
475 /*
476  * Same as previous but handling aliasing of 'r' with 'b_norm', i.e. on success,
477  * result 'r' is passed through 'b_norm'.
478  *
479  * CAUTION:
480  *
481  * - The function is expected to be used ONLY by the generic version
482  *   nn_divrem_normalized() defined later in the file.
483  * - All parameter must have been initialized. Unlike exported/public
484  *   functions, this internal helper does not verify that nn parameters
485  *   have been initialized. Again, this is expected from the caller
486  *   (nn_divrem_unshifted()).
487  */
_nn_divrem_unshifted_aliased(nn_t q,nn_src_t a,nn_t b_norm,word_t v,bitcnt_t cnt)488 ATTRIBUTE_WARN_UNUSED_RET static int _nn_divrem_unshifted_aliased(nn_t q, nn_src_t a, nn_t b_norm,
489 					word_t v, bitcnt_t cnt)
490 {
491 	int ret;
492 	nn r;
493 	r.magic = WORD(0);
494 
495 	ret = nn_init(&r, 0); EG(ret, err);
496 	ret = _nn_divrem_unshifted(q, &r, a, b_norm, v, cnt); EG(ret, err);
497 	ret = nn_copy(b_norm, &r); EG(ret, err);
498 
499 err:
500 	nn_uninit(&r);
501 	return ret;
502 }
503 
504 /*
505  * Compute quotient and remainder and do not normalize them.
506  * Constant time, see documentation of _nn_divrem_unshifted().
507  *
508  * Alias-supporting version of _nn_divrem_unshifted for 'r' only.
509  *
510  * The function returns 0 on success, -1 on error.
511  */
nn_divrem_unshifted(nn_t q,nn_t r,nn_src_t a,nn_src_t b,word_t v,bitcnt_t cnt)512 int nn_divrem_unshifted(nn_t q, nn_t r, nn_src_t a, nn_src_t b,
513 			word_t v, bitcnt_t cnt)
514 {
515 	int ret;
516 
517 	ret = nn_check_initialized(a); EG(ret, err);
518 	ret = nn_check_initialized(q); EG(ret, err);
519 	ret = nn_check_initialized(r); EG(ret, err);
520 
521 	/* Unsupported aliasings */
522 	MUST_HAVE((q != r) && (q != a) && (q != b), ret, err);
523 
524 	if (r == b) {
525 		ret = _nn_divrem_unshifted_aliased(q, a, r, v, cnt);
526 	} else {
527 		ret = nn_check_initialized(b); EG(ret, err);
528 		ret = _nn_divrem_unshifted(q, r, a, b, v, cnt);
529 	}
530 
531 err:
532 	return ret;
533 }
534 
535 /*
536  * Compute remainder only and do not normalize it.
537  * Constant time, see documentation of _nn_divrem_unshifted.
538  *
539  * Aliasing of inputs and outputs is possible.
540  *
541  * The function returns 0 on success, -1 on error.
542  */
nn_mod_unshifted(nn_t r,nn_src_t a,nn_src_t b,word_t v,bitcnt_t cnt)543 int nn_mod_unshifted(nn_t r, nn_src_t a, nn_src_t b, word_t v, bitcnt_t cnt)
544 {
545 	nn q;
546 	int ret;
547 	q.magic = WORD(0);
548 
549 	ret = nn_init(&q, 0); EG(ret, err);
550 	ret = nn_divrem_unshifted(&q, r, a, b, v, cnt);
551 
552 err:
553 	nn_uninit(&q);
554 
555 	return ret;
556 }
557 
558 /*
559  * Helper functions for arithmetic in 2-by-1 division
560  * used in the reciprocal computation.
561  *
562  * These are variations of the nn multiprecision functions
563  * acting on arrays of fixed length, in place,
564  * and returning carry/borrow.
565  *
566  * Done in constant time.
567  */
568 
569 /*
570  * Comparison of two limbs numbers. Internal helper.
571  * Checks left to the caller
572  */
_wcmp_22(word_t a[2],word_t b[2])573 ATTRIBUTE_WARN_UNUSED_RET static int _wcmp_22(word_t a[2], word_t b[2])
574 {
575 	int mask, ret = 0;
576 	ret += (a[1] > b[1]);
577 	ret -= (a[1] < b[1]);
578 	mask = !(ret & 0x1);
579 	ret += ((a[0] > b[0]) & mask);
580 	ret -= ((a[0] < b[0]) & mask);
581 	return ret;
582 }
583 
584 /*
585  * Addition of two limbs numbers with carry returned. Internal helper.
586  * Checks left to the caller.
587  */
_wadd_22(word_t a[2],word_t b[2])588 ATTRIBUTE_WARN_UNUSED_RET static word_t _wadd_22(word_t a[2], word_t b[2])
589 {
590 	word_t carry;
591 	a[0]  = (word_t)(a[0] + b[0]);
592 	carry = (word_t)(a[0] < b[0]);
593 	a[1]  = (word_t)(a[1] + carry);
594 	carry = (word_t)(a[1] < carry);
595 	a[1]  = (word_t)(a[1] + b[1]);
596 	carry = (word_t)(carry | (a[1] < b[1]));
597 	return carry;
598 }
599 
600 /*
601  * Subtraction of two limbs numbers with borrow returned. Internal helper.
602  * Checks left to the caller.
603  */
_wsub_22(word_t a[2],word_t b[2])604 ATTRIBUTE_WARN_UNUSED_RET static word_t _wsub_22(word_t a[2], word_t b[2])
605 {
606 	word_t borrow, tmp;
607 	tmp    = (word_t)(a[0] - b[0]);
608 	borrow = (word_t)(tmp > a[0]);
609 	a[0]   = tmp;
610 	tmp    = (word_t)(a[1] - borrow);
611 	borrow = (word_t)(tmp > a[1]);
612 	a[1]   = (word_t)(tmp - b[1]);
613 	borrow = (word_t)(borrow | (a[1] > tmp));
614 	return borrow;
615 }
616 
617 /*
618  * Helper macros for conditional subtraction in 2-by-1 division
619  * used in the reciprocal computation.
620  *
621  * Done in constant time.
622  */
623 
624 /* Conditional subtraction of a one limb number from a two limbs number. */
625 #define WORD_CND_SUB_21(cnd, ah, al, b) do {				\
626 		word_t tmp, mask;					\
627 		mask = WORD_MASK_IFNOTZERO((cnd));			\
628 		tmp  = (word_t)((al) - ((b) & mask));			\
629 		(ah) = (word_t)((ah) - (tmp > (al)));			\
630 		(al) = tmp;						\
631 	} while (0)
632 /* Conditional subtraction of a two limbs number from a two limbs number. */
633 #define WORD_CND_SUB_22(cnd, ah, al, bh, bl) do {			\
634 		word_t tmp, mask;					\
635 		mask = WORD_MASK_IFNOTZERO((cnd));			\
636 		tmp  = (word_t)((al) - ((bl) & mask));			\
637 		(ah) = (word_t)((ah) - (tmp > (al)));			\
638 		(al) = tmp;						\
639 		(ah) = (word_t)((ah) - ((bh) & mask));			\
640 	} while (0)
641 
642 /*
643  * divide two words by a normalized word using schoolbook division on half
644  * words. This is only used below in the reciprocal computation. No checks
645  * are performed on inputs. This is expected to be done by the caller.
646  *
647  * Returns 0 on success, -1 on error.
648  */
_word_divrem(word_t * q,word_t * r,word_t ah,word_t al,word_t b)649 ATTRIBUTE_WARN_UNUSED_RET static int _word_divrem(word_t *q, word_t *r, word_t ah, word_t al, word_t b)
650 {
651 	word_t bh, bl, qh, ql, rm, rhl[2], phl[2];
652 	int larger, ret;
653 	u8 j;
654 
655 	MUST_HAVE((WRSHIFT((b), (WORD_BITS - 1)) == WORD(1)), ret, err);
656 	bh = WRSHIFT((b), HWORD_BITS);
657 	bl = WLSHIFT((b), HWORD_BITS);
658 	rhl[1] = ah;
659 	rhl[0] = al;
660 
661 	/*
662 	 * Compute high part of the quotient. We know from
663 	 * MUST_HAVE() check above that bh (a word_t) is not 0
664 	 */
665 
666 	KNOWN_FACT(bh != 0, ret, err);
667 	qh = (rhl[1] / bh);
668 	qh = WORD_MIN(qh, HWORD_MASK);
669 	WORD_MUL(phl[1], phl[0], qh, (b));
670 	phl[1] = (WLSHIFT(phl[1], HWORD_BITS) |
671 		  WRSHIFT(phl[0], HWORD_BITS));
672 	phl[0] = WLSHIFT(phl[0], HWORD_BITS);
673 
674 	for (j = 0; j < 2; j++) {
675 		larger = (_wcmp_22(phl, rhl) > 0);
676 		qh = (word_t)(qh - (word_t)larger);
677 		WORD_CND_SUB_22(larger, phl[1], phl[0], bh, bl);
678 	}
679 
680 	ret = (_wcmp_22(phl, rhl) > 0);
681 	MUST_HAVE(!(ret), ret, err);
682 	IGNORE_RET_VAL(_wsub_22(rhl, phl));
683 	MUST_HAVE((WRSHIFT(rhl[1], HWORD_BITS) == 0), ret, err);
684 
685 	/* Compute low part of the quotient. */
686 	rm = (WLSHIFT(rhl[1], HWORD_BITS) |
687 	      WRSHIFT(rhl[0], HWORD_BITS));
688 	ql = (rm / bh);
689 	ql = WORD_MIN(ql, HWORD_MASK);
690 	WORD_MUL(phl[1], phl[0], ql, (b));
691 
692 	for (j = 0; j < 2; j++) {
693 		larger = (_wcmp_22(phl, rhl) > 0);
694 		ql = (word_t) (ql - (word_t)larger);
695 		WORD_CND_SUB_21(larger, phl[1], phl[0], (b));
696 	}
697 
698 	ret = _wcmp_22(phl, rhl) > 0;
699 	MUST_HAVE(!(ret), ret, err);
700 	IGNORE_RET_VAL(_wsub_22(rhl, phl));
701 	/* Set outputs. */
702 	MUST_HAVE((rhl[1] == WORD(0)), ret, err);
703 	MUST_HAVE(!(rhl[0] >= (b)), ret, err);
704 	(*q) = (WLSHIFT(qh, HWORD_BITS) | ql);
705 	(*r) = rhl[0];
706 	MUST_HAVE(!((word_t) ((*q)*(b) + (*r)) != (al)), ret, err);
707 	ret = 0;
708 
709 err:
710 	return ret;
711 }
712 
713 /*
714  * Compute the reciprocal of d as
715  *	floor(B^3/(d+1)) - B
716  * which is used to perform approximate small division using a multiplication.
717  *
718  * No attempt was made to make it constant time. Indeed, such values are usually
719  * precomputed in contexts where constant time is wanted, e.g. in the fp layer.
720  *
721  * Returns 0 on success, -1 on error.
722  */
wreciprocal(word_t dh,word_t dl,word_t * reciprocal)723 int wreciprocal(word_t dh, word_t dl, word_t *reciprocal)
724 {
725 	word_t q, carry, r[2], t[2];
726 	int ret;
727 
728 	MUST_HAVE((reciprocal != NULL), ret, err);
729 
730 	if (((word_t)(dh + WORD(1)) == WORD(0)) &&
731 	    ((word_t)(dl + WORD(1)) == WORD(0))) {
732 		(*reciprocal) = WORD(0);
733 		ret = 0;
734 		goto err;
735 	}
736 
737 	if ((word_t)(dh + WORD(1)) == WORD(0)) {
738 		q = (word_t)(~dh);
739 		r[1] = (word_t)(~dl);
740 	} else {
741 		t[1] = (word_t)(~dh);
742 		t[0] = (word_t)(~dl);
743 		ret = _word_divrem(&q, r+1, t[1], t[0],
744 				   (word_t)(dh + WORD(1))); EG(ret, err);
745 	}
746 
747 	if ((word_t)(dl + WORD(1)) == WORD(0)) {
748 		(*reciprocal) = q;
749 		ret = 0;
750 		goto err;
751 	}
752 
753 	r[0] = WORD(0);
754 
755 	WORD_MUL(t[1], t[0], q, (word_t)~dl);
756 	carry = _wadd_22(r, t);
757 
758 	t[0] = (word_t)(dl + WORD(1));
759 	t[1] = dh;
760 	while (carry || (_wcmp_22(r, t) >= 0)) {
761 		q++;
762 		carry = (word_t)(carry - _wsub_22(r, t));
763 	}
764 
765 	(*reciprocal) = q;
766 	ret = 0;
767 
768 err:
769 	return ret;
770 }
771 
772 /*
773  * Given an odd number p, compute division coefficients p_normalized,
774  * p_shift and p_reciprocal so that:
775  *	- p_shift = p_rounded_bitlen - bitsizeof(p), where
776  *          o p_rounded_bitlen = BIT_LEN_WORDS(p) (i.e. bit length of
777  *            minimum number of words required to store p) and
778  *          o p_bitlen is the real bit size of p
779  *	- p_normalized = p << p_shift
780  *	- p_reciprocal = B^3 / ((p_normalized >> (pbitlen - 2*WORDSIZE)) + 1) - B
781  *	  with B = 2^WORDSIZE
782  *
783  * These coefficients are useful for the optimized shifted variants of NN
784  * division and modular functions. Because we have two word_t outputs
785  * (p_shift and p_reciprocal), these are passed through word_t pointers.
786  * Aliasing of outputs with the input is possible since p_in is copied in
787  * local p at the beginning of the function.
788  *
789  * The function does not support aliasing.
790  *
791  * The function returns 0 on success, -1 on error.
792  */
nn_compute_div_coefs(nn_t p_normalized,word_t * p_shift,word_t * p_reciprocal,nn_src_t p_in)793 int nn_compute_div_coefs(nn_t p_normalized, word_t *p_shift,
794 			  word_t *p_reciprocal, nn_src_t p_in)
795 {
796 	bitcnt_t p_rounded_bitlen, p_bitlen;
797 	nn p, tmp_nn;
798 	int ret;
799 	p.magic = tmp_nn.magic = WORD(0);
800 
801 	ret = nn_check_initialized(p_in); EG(ret, err);
802 
803 	MUST_HAVE((p_shift != NULL), ret, err);
804 	MUST_HAVE((p_reciprocal != NULL), ret, err);
805 
806 	/* Unsupported aliasing */
807 	MUST_HAVE((p_normalized != p_in), ret, err);
808 
809 	ret = nn_init(&p, 0); EG(ret, err);
810 	ret = nn_copy(&p, p_in); EG(ret, err);
811 
812 	/*
813 	 * In order for our reciprocal division routines to work, it is expected
814 	 * that the bit length (including leading zeroes) of input prime
815 	 * p is >= 2 * wlen where wlen is the number of bits of a word size.
816 	 */
817 	if (p.wlen < 2) {
818 		ret = nn_set_wlen(&p, 2); EG(ret, err);
819 	}
820 
821 	ret = nn_init(p_normalized, 0); EG(ret, err);
822 	ret = nn_init(&tmp_nn, 0); EG(ret, err);
823 
824 	/* p_rounded_bitlen = bitlen of p rounded to word size */
825 	p_rounded_bitlen = (bitcnt_t)(WORD_BITS * p.wlen);
826 
827 	/* p_shift */
828 	ret = nn_bitlen(&p, &p_bitlen); EG(ret, err);
829 	(*p_shift) = (word_t)(p_rounded_bitlen - p_bitlen);
830 
831 	/* p_normalized = p << pshift */
832 	ret = nn_lshift(p_normalized, &p, (bitcnt_t)(*p_shift)); EG(ret, err);
833 
834 	/* Sanity check to protect the p_reciprocal computation */
835 	MUST_HAVE((p_rounded_bitlen >= (2 * WORDSIZE)), ret, err);
836 
837 	/*
838 	 * p_reciprocal = B^3 / ((p_normalized >> (p_rounded_bitlen - 2 * wlen)) + 1) - B
839 	 * where B = 2^wlen where wlen = word size in bits. We use our NN
840 	 * helper to compute it.
841 	 */
842 	ret = nn_rshift(&tmp_nn, p_normalized, (bitcnt_t)(p_rounded_bitlen - (2 * WORDSIZE))); EG(ret, err);
843 	ret = wreciprocal(tmp_nn.val[1], tmp_nn.val[0], p_reciprocal);
844 
845 err:
846 	nn_uninit(&p);
847 	nn_uninit(&tmp_nn);
848 
849 	return ret;
850 }
851 
852 /*
853  * Compute quotient remainder of Euclidean division.
854  *
855  * This function is a wrapper to normalize the divisor, i.e. shift it so that
856  * the MSB of its MSW is set, and precompute the reciprocal of this MSW to be
857  * used to perform small divisions using multiplications during the long
858  * schoolbook division. It uses the helper functions/macros above.
859  *
860  * This is NOT constant time with regards to the word length of a and b,
861  * but also the actual bitlength of b as we need to normalize b at the
862  * bit level.
863  * Moreover the precomputation of the reciprocal is not constant time at all.
864  *
865  * r need not be initialized, the function does it for the the caller.
866  *
867  * This function does not support aliasing. This is an internal helper, which
868  * expects caller to check parameters.
869  *
870  * It returns 0 on sucess, -1 on error.
871  */
_nn_divrem(nn_t q,nn_t r,nn_src_t a,nn_src_t b)872 ATTRIBUTE_WARN_UNUSED_RET static int _nn_divrem(nn_t q, nn_t r, nn_src_t a, nn_src_t b)
873 {
874 	nn b_large, b_normalized;
875 	bitcnt_t cnt;
876 	word_t v;
877 	nn_src_t ptr = b;
878 	int ret, iszero;
879 	b_large.magic = b_normalized.magic = WORD(0);
880 
881 	ret = nn_init(r, 0); EG(ret, err);
882 	ret = nn_init(q, 0); EG(ret, err);
883 	ret = nn_init(&b_large, 0); EG(ret, err);
884 
885 	MUST_HAVE(!nn_iszero(b, &iszero) && !iszero, ret, err);
886 
887 	if (b->wlen == 1) {
888 		ret = nn_copy(&b_large, b); EG(ret, err);
889 
890 		/* Expand our big number with zeroes */
891 		ret = nn_set_wlen(&b_large, 2); EG(ret, err);
892 
893 		/*
894 		 * This cast could seem inappropriate, but we are
895 		 * sure here that we won't touch ptr since it is only
896 		 * given as a const parameter to sub functions.
897 		 */
898 		ptr = (nn_src_t) &b_large;
899 	}
900 
901 	/* After this, we only handle >= 2 words big numbers */
902 	MUST_HAVE(!(ptr->wlen < 2), ret, err);
903 
904 	ret = nn_init(&b_normalized, (u16)((ptr->wlen) * WORD_BYTES)); EG(ret, err);
905 	ret = nn_clz(ptr, &cnt); EG(ret, err);
906 	ret = nn_lshift_fixedlen(&b_normalized, ptr, cnt); EG(ret, err);
907 	ret = wreciprocal(b_normalized.val[ptr->wlen - 1],
908 			  b_normalized.val[ptr->wlen - 2],
909 			  &v); /* Not constant time. */ EG(ret, err);
910 
911 	ret = _nn_divrem_unshifted(q, r, a, &b_normalized, v, cnt);
912 
913 err:
914 	nn_uninit(&b_normalized);
915 	nn_uninit(&b_large);
916 
917 	return ret;
918 }
919 
920 /*
921  * Returns 0 on succes, -1 on error. Internal helper. Checks on params
922  * expected from the caller.
923  */
__nn_divrem_notrim_alias(nn_t q,nn_t r,nn_src_t a,nn_src_t b)924 ATTRIBUTE_WARN_UNUSED_RET static int __nn_divrem_notrim_alias(nn_t q, nn_t r, nn_src_t a, nn_src_t b)
925 {
926 	nn a_cpy, b_cpy;
927 	int ret;
928 	a_cpy.magic = b_cpy.magic = WORD(0);
929 
930 	ret = nn_init(&a_cpy, 0); EG(ret, err);
931 	ret = nn_init(&b_cpy, 0); EG(ret, err);
932 	ret = nn_copy(&a_cpy, a); EG(ret, err);
933 	ret = nn_copy(&b_cpy, b); EG(ret, err);
934 	ret = _nn_divrem(q, r, &a_cpy, &b_cpy);
935 
936 err:
937 	nn_uninit(&b_cpy);
938 	nn_uninit(&a_cpy);
939 
940 	return ret;
941 }
942 
943 
944 
945 /*
946  * Compute quotient and remainder and normalize them.
947  * Not constant time, see documentation of _nn_divrem.
948  *
949  * Aliased version of _nn_divrem. Returns 0 on success,
950  * -1 on error.
951  */
nn_divrem_notrim(nn_t q,nn_t r,nn_src_t a,nn_src_t b)952 int nn_divrem_notrim(nn_t q, nn_t r, nn_src_t a, nn_src_t b)
953 {
954 	int ret;
955 
956 	/* _nn_divrem initializes q and r */
957 	ret = nn_check_initialized(a); EG(ret, err);
958 	ret = nn_check_initialized(b); EG(ret, err);
959 	MUST_HAVE(((q != NULL) && (r != NULL)), ret, err);
960 
961 	/*
962 	 * Handle aliasing whenever any of the inputs is
963 	 * used as an output.
964 	 */
965 	if ((a == q) || (a == r) || (b == q) || (b == r)) {
966 		ret = __nn_divrem_notrim_alias(q, r, a, b);
967 	} else {
968 		ret = _nn_divrem(q, r, a, b);
969 	}
970 
971 err:
972 	return ret;
973 }
974 
975 /*
976  * Compute quotient and remainder and normalize them.
977  * Not constant time, see documentation of _nn_divrem().
978  * Returns 0 on success, -1 on error.
979  *
980  * Aliasing is supported.
981  */
nn_divrem(nn_t q,nn_t r,nn_src_t a,nn_src_t b)982 int nn_divrem(nn_t q, nn_t r, nn_src_t a, nn_src_t b)
983 {
984 	int ret;
985 
986 	ret = nn_divrem_notrim(q, r, a, b); EG(ret, err);
987 
988 	/* Normalize (trim) the quotient and rest to avoid size overflow */
989 	ret = nn_normalize(q); EG(ret, err);
990 	ret = nn_normalize(r);
991 
992 err:
993 	return ret;
994 }
995 
996 /*
997  * Compute remainder only and do not normalize it. Not constant time, see
998  * documentation of _nn_divrem(). Returns 0 on success, -1 on error.
999  *
1000  * Aliasing is supported.
1001  */
nn_mod_notrim(nn_t r,nn_src_t a,nn_src_t b)1002 int nn_mod_notrim(nn_t r, nn_src_t a, nn_src_t b)
1003 {
1004 	int ret;
1005 	nn q;
1006 	q.magic = WORD(0);
1007 
1008 	/* nn_divrem() will init q. */
1009 	ret = nn_divrem_notrim(&q, r, a, b);
1010 
1011 	nn_uninit(&q);
1012 
1013 	return ret;
1014 }
1015 
1016 /*
1017  * Compute remainder only and normalize it. Not constant time, see
1018  * documentation of _nn_divrem(). r is initialized by the function.
1019  * Returns 0 on success, -1 on error.
1020  *
1021  * Aliasing is supported.
1022  */
nn_mod(nn_t r,nn_src_t a,nn_src_t b)1023 int nn_mod(nn_t r, nn_src_t a, nn_src_t b)
1024 {
1025 	int ret;
1026 	nn q;
1027 	q.magic = WORD(0);
1028 
1029 	/* nn_divrem will init q. */
1030 	ret = nn_divrem(&q, r, a, b);
1031 
1032 	nn_uninit(&q);
1033 
1034 	return ret;
1035 }
1036 
1037 /*
1038  * Below follow gcd and xgcd non constant time functions for the user ease.
1039  */
1040 
1041 /*
1042  * Unaliased version of xgcd, and we suppose that a >= b. Badly non-constant
1043  * time per the algorithm used. The function returns 0 on success, -1 on
1044  * error. internal helper: expect caller to check parameters.
1045  */
_nn_xgcd(nn_t g,nn_t u,nn_t v,nn_src_t a,nn_src_t b,int * sign)1046 ATTRIBUTE_WARN_UNUSED_RET static int _nn_xgcd(nn_t g, nn_t u, nn_t v, nn_src_t a, nn_src_t b,
1047 		    int *sign)
1048 {
1049 	nn_t c, d, q, r, u1, v1, u2, v2;
1050 	nn scratch[8];
1051 	int ret, swap, iszero;
1052 	u8 i;
1053 
1054 	for (i = 0; i < 8; i++){
1055 		scratch[i].magic = WORD(0);
1056 	}
1057 
1058 	/*
1059 	 * Maintain:
1060 	 * |u1 v1| |c| = |a|
1061 	 * |u2 v2| |d|   |b|
1062 	 * u1, v1, u2, v2 >= 0
1063 	 * c >= d
1064 	 *
1065 	 * Initially:
1066 	 * |1  0 | |a| = |a|
1067 	 * |0  1 | |b|   |b|
1068 	 *
1069 	 * At each iteration:
1070 	 * c >= d
1071 	 * c = q*d + r
1072 	 * |u1 v1| = |q*u1+v1 u1|
1073 	 * |u2 v2|   |q*u2+v2 u2|
1074 	 *
1075 	 * Finally, after i steps:
1076 	 * |u1 v1| |g| = |a|
1077 	 * |u2 v2| |0| = |b|
1078 	 *
1079 	 * Inverting the matrix:
1080 	 * |g| = (-1)^i | v2 -v1| |a|
1081 	 * |0|          |-u2  u1| |b|
1082 	 */
1083 
1084 	/*
1085 	 * Initialization.
1086 	 */
1087 	ret = nn_init(g, 0); EG(ret, err);
1088 	ret = nn_init(u, 0); EG(ret, err);
1089 	ret = nn_init(v, 0); EG(ret, err);
1090 	ret = nn_iszero(b, &iszero); EG(ret, err);
1091 	if (iszero) {
1092 		/* gcd(0, a) = a, and 1*a + 0*b = a */
1093 		ret = nn_copy(g, a); EG(ret, err);
1094 		ret = nn_one(u); EG(ret, err);
1095 		ret = nn_zero(v); EG(ret, err);
1096 		(*sign) = 1;
1097 		goto err;
1098 	}
1099 
1100 	for (i = 0; i < 8; i++){
1101 		ret = nn_init(&scratch[i], 0); EG(ret, err);
1102 	}
1103 
1104 	u1 = &(scratch[0]);
1105 	v1 = &(scratch[1]);
1106 	u2 = &(scratch[2]);
1107 	v2 = &(scratch[3]);
1108 	ret = nn_one(u1); EG(ret, err);
1109 	ret = nn_zero(v1); EG(ret, err);
1110 	ret = nn_zero(u2); EG(ret, err);
1111 	ret = nn_one(v2); EG(ret, err);
1112 	c = &(scratch[4]);
1113 	d = &(scratch[5]);
1114 	ret = nn_copy(c, a); EG(ret, err); /* Copy could be skipped. */
1115 	ret = nn_copy(d, b); EG(ret, err); /* Copy could be skipped. */
1116 	q = &(scratch[6]);
1117 	r = &(scratch[7]);
1118 	swap = 0;
1119 
1120 	/*
1121 	 * Loop.
1122 	 */
1123 	ret = nn_iszero(d, &iszero); EG(ret, err);
1124 	while (!iszero) {
1125 		ret = nn_divrem(q, r, c, d); EG(ret, err);
1126 		ret = nn_normalize(q); EG(ret, err);
1127 		ret = nn_normalize(r); EG(ret, err);
1128 		ret = nn_copy(c, r); EG(ret, err);
1129 		ret = nn_mul(r, q, u1); EG(ret, err);
1130 		ret = nn_normalize(r); EG(ret, err);
1131 		ret = nn_add(v1, v1, r); EG(ret, err);
1132 		ret = nn_mul(r, q, u2); EG(ret, err);
1133 		ret = nn_normalize(r); EG(ret, err);
1134 		ret = nn_add(v2, v2, r); EG(ret, err);
1135 		ret = nn_normalize(v1); EG(ret, err);
1136 		ret = nn_normalize(v2); EG(ret, err);
1137 		swap = 1;
1138 		ret = nn_iszero(c, &iszero); EG(ret, err);
1139 		if (iszero) {
1140 			break;
1141 		}
1142 		ret = nn_divrem(q, r, d, c); EG(ret, err);
1143 		ret = nn_normalize(q); EG(ret, err);
1144 		ret = nn_normalize(r); EG(ret, err);
1145 		ret = nn_copy(d, r); EG(ret, err);
1146 		ret = nn_mul(r, q, v1); EG(ret, err);
1147 		ret = nn_normalize(r); EG(ret, err);
1148 		ret = nn_add(u1, u1, r); EG(ret, err);
1149 		ret = nn_mul(r, q, v2); EG(ret, err);
1150 		ret = nn_normalize(r); EG(ret, err);
1151 		ret = nn_add(u2, u2, r); EG(ret, err);
1152 		ret = nn_normalize(u1); EG(ret, err);
1153 		ret = nn_normalize(u2); EG(ret, err);
1154 		swap = 0;
1155 
1156 		/* refresh loop condition */
1157 		ret = nn_iszero(d, &iszero); EG(ret, err);
1158 	}
1159 
1160 	/* Copies could be skipped. */
1161 	if (swap) {
1162 		ret = nn_copy(g, d); EG(ret, err);
1163 		ret = nn_copy(u, u2); EG(ret, err);
1164 		ret = nn_copy(v, u1); EG(ret, err);
1165 	} else {
1166 		ret = nn_copy(g, c); EG(ret, err);
1167 		ret = nn_copy(u, v2); EG(ret, err);
1168 		ret = nn_copy(v, v1); EG(ret, err);
1169 	}
1170 
1171 	/* swap = -1 means u <= 0; = 1 means v <= 0 */
1172 	(*sign) = swap ? -1 : 1;
1173 	ret = 0;
1174 
1175 err:
1176 	/*
1177 	 * We uninit scratch elements in all cases, i.e. whether or not
1178 	 * we return an error or not.
1179 	 */
1180 	for (i = 0; i < 8; i++){
1181 		nn_uninit(&scratch[i]);
1182 	}
1183 	/* Unitialize output in case of error */
1184 	if (ret){
1185 		nn_uninit(v);
1186 		nn_uninit(u);
1187 		nn_uninit(g);
1188 	}
1189 
1190 	return ret;
1191 }
1192 
1193 /*
1194  * Aliased version of xgcd, and no assumption on a and b. Not constant time at
1195  * all. returns 0 on success, -1 on error. XXX document 'sign'
1196  *
1197  * Aliasing is supported.
1198  */
nn_xgcd(nn_t g,nn_t u,nn_t v,nn_src_t a,nn_src_t b,int * sign)1199 int nn_xgcd(nn_t g, nn_t u, nn_t v, nn_src_t a, nn_src_t b, int *sign)
1200 {
1201 	/* Handle aliasing
1202 	 * Note: in order to properly handle aliasing, we accept to lose
1203 	 * some "space" on the stack with copies.
1204 	 */
1205 	nn a_cpy, b_cpy;
1206 	nn_src_t a_, b_;
1207 	int ret, cmp, _sign;
1208 	a_cpy.magic = b_cpy.magic = WORD(0);
1209 
1210 	/* The internal _nn_xgcd function initializes g, u and v */
1211 	ret = nn_check_initialized(a); EG(ret, err);
1212 	ret = nn_check_initialized(b); EG(ret, err);
1213 	MUST_HAVE((sign != NULL), ret, err);
1214 
1215 	ret = nn_init(&b_cpy, 0); EG(ret, err);
1216 
1217 	/* Aliasing of a */
1218 	if ((g == a) || (u == a) || (v == a)){
1219 		ret = nn_copy(&a_cpy, a); EG(ret, err);
1220 		a_ = &a_cpy;
1221 	} else {
1222 		a_ = a;
1223 	}
1224 	/* Aliasing of b */
1225 	if ((g == b) || (u == b) || (v == b)) {
1226 		ret = nn_copy(&b_cpy, b); EG(ret, err);
1227 		b_ = &b_cpy;
1228 	} else {
1229 		b_ = b;
1230 	}
1231 
1232 	ret = nn_cmp(a_, b_, &cmp); EG(ret, err);
1233 	if (cmp < 0) {
1234 		/* If a < b, swap the inputs */
1235 		ret = _nn_xgcd(g, v, u, b_, a_, &_sign); EG(ret, err);
1236 		(*sign) = -(_sign);
1237 	} else {
1238 		ret = _nn_xgcd(g, u, v, a_, b_, &_sign); EG(ret, err);
1239 		(*sign) = _sign;
1240 	}
1241 
1242 err:
1243 	nn_uninit(&b_cpy);
1244 	nn_uninit(&a_cpy);
1245 
1246 	return ret;
1247 }
1248 
1249 /*
1250  * Compute g = gcd(a, b). Internally use the xgcd and drop u and v.
1251  * Not constant time at all. Returns 0 on success, -1 on error.
1252  * XXX document 'sign'.
1253  *
1254  * Aliasing is supported.
1255  */
nn_gcd(nn_t g,nn_src_t a,nn_src_t b,int * sign)1256 int nn_gcd(nn_t g, nn_src_t a, nn_src_t b, int *sign)
1257 {
1258 	nn u, v;
1259 	int ret;
1260 	u.magic = v.magic = WORD(0);
1261 
1262 	/* nn_xgcd will initialize g, u and v and
1263 	 * check if a and b are indeed initialized.
1264 	 */
1265 	ret = nn_xgcd(g, &u, &v, a, b, sign);
1266 
1267 	nn_uninit(&u);
1268 	nn_uninit(&v);
1269 
1270 	return ret;
1271 }
1272