xref: /openbsd/lib/libcrypto/bn/bn_gcd.c (revision 71743258)
1*71743258Sjmc /* $OpenBSD: bn_gcd.c,v 1.20 2022/12/26 07:18:51 jmc Exp $ */
25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
35b37fcf3Sryker  * All rights reserved.
45b37fcf3Sryker  *
55b37fcf3Sryker  * This package is an SSL implementation written
65b37fcf3Sryker  * by Eric Young (eay@cryptsoft.com).
75b37fcf3Sryker  * The implementation was written so as to conform with Netscapes SSL.
85b37fcf3Sryker  *
95b37fcf3Sryker  * This library is free for commercial and non-commercial use as long as
105b37fcf3Sryker  * the following conditions are aheared to.  The following conditions
115b37fcf3Sryker  * apply to all code found in this distribution, be it the RC4, RSA,
125b37fcf3Sryker  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
135b37fcf3Sryker  * included with this distribution is covered by the same copyright terms
145b37fcf3Sryker  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
155b37fcf3Sryker  *
165b37fcf3Sryker  * Copyright remains Eric Young's, and as such any Copyright notices in
175b37fcf3Sryker  * the code are not to be removed.
185b37fcf3Sryker  * If this package is used in a product, Eric Young should be given attribution
195b37fcf3Sryker  * as the author of the parts of the library used.
205b37fcf3Sryker  * This can be in the form of a textual message at program startup or
215b37fcf3Sryker  * in documentation (online or textual) provided with the package.
225b37fcf3Sryker  *
235b37fcf3Sryker  * Redistribution and use in source and binary forms, with or without
245b37fcf3Sryker  * modification, are permitted provided that the following conditions
255b37fcf3Sryker  * are met:
265b37fcf3Sryker  * 1. Redistributions of source code must retain the copyright
275b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer.
285b37fcf3Sryker  * 2. Redistributions in binary form must reproduce the above copyright
295b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer in the
305b37fcf3Sryker  *    documentation and/or other materials provided with the distribution.
315b37fcf3Sryker  * 3. All advertising materials mentioning features or use of this software
325b37fcf3Sryker  *    must display the following acknowledgement:
335b37fcf3Sryker  *    "This product includes cryptographic software written by
345b37fcf3Sryker  *     Eric Young (eay@cryptsoft.com)"
355b37fcf3Sryker  *    The word 'cryptographic' can be left out if the rouines from the library
365b37fcf3Sryker  *    being used are not cryptographic related :-).
375b37fcf3Sryker  * 4. If you include any Windows specific code (or a derivative thereof) from
385b37fcf3Sryker  *    the apps directory (application code) you must include an acknowledgement:
395b37fcf3Sryker  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
405b37fcf3Sryker  *
415b37fcf3Sryker  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
425b37fcf3Sryker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
435b37fcf3Sryker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
445b37fcf3Sryker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
455b37fcf3Sryker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
465b37fcf3Sryker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
475b37fcf3Sryker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485b37fcf3Sryker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495b37fcf3Sryker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
505b37fcf3Sryker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
515b37fcf3Sryker  * SUCH DAMAGE.
525b37fcf3Sryker  *
535b37fcf3Sryker  * The licence and distribution terms for any publically available version or
545b37fcf3Sryker  * derivative of this code cannot be changed.  i.e. this code cannot simply be
555b37fcf3Sryker  * copied and put under another distribution licence
565b37fcf3Sryker  * [including the GNU Public Licence.]
575b37fcf3Sryker  */
58da347917Sbeck /* ====================================================================
59da347917Sbeck  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
60da347917Sbeck  *
61da347917Sbeck  * Redistribution and use in source and binary forms, with or without
62da347917Sbeck  * modification, are permitted provided that the following conditions
63da347917Sbeck  * are met:
64da347917Sbeck  *
65da347917Sbeck  * 1. Redistributions of source code must retain the above copyright
66da347917Sbeck  *    notice, this list of conditions and the following disclaimer.
67da347917Sbeck  *
68da347917Sbeck  * 2. Redistributions in binary form must reproduce the above copyright
69da347917Sbeck  *    notice, this list of conditions and the following disclaimer in
70da347917Sbeck  *    the documentation and/or other materials provided with the
71da347917Sbeck  *    distribution.
72da347917Sbeck  *
73da347917Sbeck  * 3. All advertising materials mentioning features or use of this
74da347917Sbeck  *    software must display the following acknowledgment:
75da347917Sbeck  *    "This product includes software developed by the OpenSSL Project
76da347917Sbeck  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77da347917Sbeck  *
78da347917Sbeck  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79da347917Sbeck  *    endorse or promote products derived from this software without
80da347917Sbeck  *    prior written permission. For written permission, please contact
81da347917Sbeck  *    openssl-core@openssl.org.
82da347917Sbeck  *
83da347917Sbeck  * 5. Products derived from this software may not be called "OpenSSL"
84da347917Sbeck  *    nor may "OpenSSL" appear in their names without prior written
85da347917Sbeck  *    permission of the OpenSSL Project.
86da347917Sbeck  *
87da347917Sbeck  * 6. Redistributions of any form whatsoever must retain the following
88da347917Sbeck  *    acknowledgment:
89da347917Sbeck  *    "This product includes software developed by the OpenSSL Project
90da347917Sbeck  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91da347917Sbeck  *
92da347917Sbeck  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93da347917Sbeck  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94da347917Sbeck  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95da347917Sbeck  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96da347917Sbeck  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97da347917Sbeck  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98da347917Sbeck  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99da347917Sbeck  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100da347917Sbeck  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101da347917Sbeck  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102da347917Sbeck  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103da347917Sbeck  * OF THE POSSIBILITY OF SUCH DAMAGE.
104da347917Sbeck  * ====================================================================
105da347917Sbeck  *
106da347917Sbeck  * This product includes cryptographic software written by Eric Young
107da347917Sbeck  * (eay@cryptsoft.com).  This product includes software written by Tim
108da347917Sbeck  * Hudson (tjh@cryptsoft.com).
109da347917Sbeck  *
110da347917Sbeck  */
1115b37fcf3Sryker 
112b6ab114eSjsing #include <openssl/err.h>
113b6ab114eSjsing 
114c9675a23Stb #include "bn_local.h"
1155b37fcf3Sryker 
1165b37fcf3Sryker static BIGNUM *euclid(BIGNUM *a, BIGNUM *b);
117572569cdSbeck static BIGNUM *BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
118572569cdSbeck     BN_CTX *ctx);
119ba5406e9Sbeck 
1202bd9bb84Sjsing int
1212bd9bb84Sjsing BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
1225b37fcf3Sryker {
1235b37fcf3Sryker 	BIGNUM *a, *b, *t;
1245b37fcf3Sryker 	int ret = 0;
1255b37fcf3Sryker 
126913ec974Sbeck 
127ba5406e9Sbeck 	BN_CTX_start(ctx);
128aa389b8cSjsing 	if ((a = BN_CTX_get(ctx)) == NULL)
129aa389b8cSjsing 		goto err;
130aa389b8cSjsing 	if ((b = BN_CTX_get(ctx)) == NULL)
1312bd9bb84Sjsing 		goto err;
1325b37fcf3Sryker 
1332bd9bb84Sjsing 	if (BN_copy(a, in_a) == NULL)
1342bd9bb84Sjsing 		goto err;
1352bd9bb84Sjsing 	if (BN_copy(b, in_b) == NULL)
1362bd9bb84Sjsing 		goto err;
137da347917Sbeck 	a->neg = 0;
138da347917Sbeck 	b->neg = 0;
1395b37fcf3Sryker 
1402bd9bb84Sjsing 	if (BN_cmp(a, b) < 0) {
1412bd9bb84Sjsing 		t = a;
1422bd9bb84Sjsing 		a = b;
1432bd9bb84Sjsing 		b = t;
1442bd9bb84Sjsing 	}
1455b37fcf3Sryker 	t = euclid(a, b);
1462bd9bb84Sjsing 	if (t == NULL)
1472bd9bb84Sjsing 		goto err;
1485b37fcf3Sryker 
1492bd9bb84Sjsing 	if (BN_copy(r, t) == NULL)
1502bd9bb84Sjsing 		goto err;
1515b37fcf3Sryker 	ret = 1;
1522bd9bb84Sjsing 
1535b37fcf3Sryker err:
154ba5406e9Sbeck 	BN_CTX_end(ctx);
1555b37fcf3Sryker 	return (ret);
1565b37fcf3Sryker }
1575b37fcf3Sryker 
158572569cdSbeck int
159572569cdSbeck BN_gcd_ct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
160572569cdSbeck {
161572569cdSbeck 	if (BN_gcd_no_branch(r, in_a, in_b, ctx) == NULL)
162572569cdSbeck 		return 0;
163572569cdSbeck 	return 1;
164572569cdSbeck }
165572569cdSbeck 
166572569cdSbeck int
167572569cdSbeck BN_gcd_nonct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
168572569cdSbeck {
169572569cdSbeck 	return BN_gcd(r, in_a, in_b, ctx);
170572569cdSbeck }
171572569cdSbeck 
172572569cdSbeck 
1732bd9bb84Sjsing static BIGNUM *
1742bd9bb84Sjsing euclid(BIGNUM *a, BIGNUM *b)
1755b37fcf3Sryker {
1765b37fcf3Sryker 	BIGNUM *t;
1775b37fcf3Sryker 	int shifts = 0;
1785b37fcf3Sryker 
179913ec974Sbeck 
180da347917Sbeck 	/* 0 <= b <= a */
1812bd9bb84Sjsing 	while (!BN_is_zero(b)) {
182da347917Sbeck 		/* 0 < b <= a */
1835b37fcf3Sryker 
1842bd9bb84Sjsing 		if (BN_is_odd(a)) {
1852bd9bb84Sjsing 			if (BN_is_odd(b)) {
1862bd9bb84Sjsing 				if (!BN_sub(a, a, b))
1872bd9bb84Sjsing 					goto err;
1882bd9bb84Sjsing 				if (!BN_rshift1(a, a))
1892bd9bb84Sjsing 					goto err;
1902bd9bb84Sjsing 				if (BN_cmp(a, b) < 0) {
1912bd9bb84Sjsing 					t = a;
1922bd9bb84Sjsing 					a = b;
1932bd9bb84Sjsing 					b = t;
1942bd9bb84Sjsing 				}
1955b37fcf3Sryker 			}
1965b37fcf3Sryker 			else		/* a odd - b even */
1975b37fcf3Sryker 			{
1982bd9bb84Sjsing 				if (!BN_rshift1(b, b))
1992bd9bb84Sjsing 					goto err;
2002bd9bb84Sjsing 				if (BN_cmp(a, b) < 0) {
2012bd9bb84Sjsing 					t = a;
2022bd9bb84Sjsing 					a = b;
2032bd9bb84Sjsing 					b = t;
2042bd9bb84Sjsing 				}
2055b37fcf3Sryker 			}
2065b37fcf3Sryker 		}
2075b37fcf3Sryker 		else			/* a is even */
2085b37fcf3Sryker 		{
2092bd9bb84Sjsing 			if (BN_is_odd(b)) {
2102bd9bb84Sjsing 				if (!BN_rshift1(a, a))
2112bd9bb84Sjsing 					goto err;
2122bd9bb84Sjsing 				if (BN_cmp(a, b) < 0) {
2132bd9bb84Sjsing 					t = a;
2142bd9bb84Sjsing 					a = b;
2152bd9bb84Sjsing 					b = t;
2162bd9bb84Sjsing 				}
2175b37fcf3Sryker 			}
2185b37fcf3Sryker 			else		/* a even - b even */
2195b37fcf3Sryker 			{
2202bd9bb84Sjsing 				if (!BN_rshift1(a, a))
2212bd9bb84Sjsing 					goto err;
2222bd9bb84Sjsing 				if (!BN_rshift1(b, b))
2232bd9bb84Sjsing 					goto err;
2245b37fcf3Sryker 				shifts++;
2255b37fcf3Sryker 			}
2265b37fcf3Sryker 		}
227da347917Sbeck 		/* 0 <= b <= a */
2285b37fcf3Sryker 	}
229da347917Sbeck 
2302bd9bb84Sjsing 	if (shifts) {
2312bd9bb84Sjsing 		if (!BN_lshift(a, a, shifts))
2322bd9bb84Sjsing 			goto err;
2335b37fcf3Sryker 	}
2345b37fcf3Sryker 	return (a);
2352bd9bb84Sjsing 
2365b37fcf3Sryker err:
2375b37fcf3Sryker 	return (NULL);
2385b37fcf3Sryker }
2395b37fcf3Sryker 
240da347917Sbeck 
2415b37fcf3Sryker /* solves ax == 1 (mod n) */
2422bd9bb84Sjsing static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a,
2432bd9bb84Sjsing     const BIGNUM *n, BN_CTX *ctx);
24497222eddSmiod 
245b0f5cbc3Sbeck static BIGNUM *
246b0f5cbc3Sbeck BN_mod_inverse_internal(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx,
247b0f5cbc3Sbeck     int ct)
2485b37fcf3Sryker {
249da347917Sbeck 	BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
250da347917Sbeck 	BIGNUM *ret = NULL;
2515b37fcf3Sryker 	int sign;
2525b37fcf3Sryker 
253b0f5cbc3Sbeck 	if (ct)
2544fcf65c5Sdjm 		return BN_mod_inverse_no_branch(in, a, n, ctx);
2554fcf65c5Sdjm 
256913ec974Sbeck 
257ba5406e9Sbeck 	BN_CTX_start(ctx);
258aa389b8cSjsing 	if ((A = BN_CTX_get(ctx)) == NULL)
259aa389b8cSjsing 		goto err;
260aa389b8cSjsing 	if ((B = BN_CTX_get(ctx)) == NULL)
261aa389b8cSjsing 		goto err;
262aa389b8cSjsing 	if ((X = BN_CTX_get(ctx)) == NULL)
263aa389b8cSjsing 		goto err;
264aa389b8cSjsing 	if ((D = BN_CTX_get(ctx)) == NULL)
265aa389b8cSjsing 		goto err;
266aa389b8cSjsing 	if ((M = BN_CTX_get(ctx)) == NULL)
267aa389b8cSjsing 		goto err;
268aa389b8cSjsing 	if ((Y = BN_CTX_get(ctx)) == NULL)
269aa389b8cSjsing 		goto err;
270aa389b8cSjsing 	if ((T = BN_CTX_get(ctx)) == NULL)
2712bd9bb84Sjsing 		goto err;
272ba5406e9Sbeck 
273913ec974Sbeck 	if (in == NULL)
2745b37fcf3Sryker 		R = BN_new();
275913ec974Sbeck 	else
276913ec974Sbeck 		R = in;
2772bd9bb84Sjsing 	if (R == NULL)
2782bd9bb84Sjsing 		goto err;
2795b37fcf3Sryker 
280dd1a6ee8Sjsing 	if (!BN_one(X))
281dd1a6ee8Sjsing 		goto err;
282da347917Sbeck 	BN_zero(Y);
2832bd9bb84Sjsing 	if (BN_copy(B, a) == NULL)
2842bd9bb84Sjsing 		goto err;
2852bd9bb84Sjsing 	if (BN_copy(A, n) == NULL)
2862bd9bb84Sjsing 		goto err;
287da347917Sbeck 	A->neg = 0;
2882bd9bb84Sjsing 	if (B->neg || (BN_ucmp(B, A) >= 0)) {
2892bd9bb84Sjsing 		if (!BN_nnmod(B, B, A, ctx))
2902bd9bb84Sjsing 			goto err;
291da347917Sbeck 	}
292da347917Sbeck 	sign = -1;
293da347917Sbeck 	/* From  B = a mod |n|,  A = |n|  it follows that
294da347917Sbeck 	 *
295da347917Sbeck 	 *      0 <= B < A,
296da347917Sbeck 	 *     -sign*X*a  ==  B   (mod |n|),
297da347917Sbeck 	 *      sign*Y*a  ==  A   (mod |n|).
298da347917Sbeck 	 */
299da347917Sbeck 
3002bd9bb84Sjsing 	if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) {
301da347917Sbeck 		/* Binary inversion algorithm; requires odd modulus.
302da347917Sbeck 		 * This is faster than the general algorithm if the modulus
303da347917Sbeck 		 * is sufficiently small (about 400 .. 500 bits on 32-bit
304*71743258Sjmc 		 * systems, but much more on 64-bit systems) */
305da347917Sbeck 		int shift;
3065b37fcf3Sryker 
3072bd9bb84Sjsing 		while (!BN_is_zero(B)) {
308da347917Sbeck 			/*
309da347917Sbeck 			 *      0 < B < |n|,
310da347917Sbeck 			 *      0 < A <= |n|,
311da347917Sbeck 			 * (1) -sign*X*a  ==  B   (mod |n|),
312da347917Sbeck 			 * (2)  sign*Y*a  ==  A   (mod |n|)
313da347917Sbeck 			 */
314da347917Sbeck 
315da347917Sbeck 			/* Now divide  B  by the maximum possible power of two in the integers,
316da347917Sbeck 			 * and divide  X  by the same value mod |n|.
317da347917Sbeck 			 * When we're done, (1) still holds. */
318da347917Sbeck 			shift = 0;
319da347917Sbeck 			while (!BN_is_bit_set(B, shift)) /* note that 0 < B */
320da347917Sbeck 			{
321da347917Sbeck 				shift++;
322da347917Sbeck 
3232bd9bb84Sjsing 				if (BN_is_odd(X)) {
3242bd9bb84Sjsing 					if (!BN_uadd(X, X, n))
3252bd9bb84Sjsing 						goto err;
326da347917Sbeck 				}
327da347917Sbeck 				/* now X is even, so we can easily divide it by two */
3282bd9bb84Sjsing 				if (!BN_rshift1(X, X))
3292bd9bb84Sjsing 					goto err;
330da347917Sbeck 			}
3312bd9bb84Sjsing 			if (shift > 0) {
3322bd9bb84Sjsing 				if (!BN_rshift(B, B, shift))
3332bd9bb84Sjsing 					goto err;
334da347917Sbeck 			}
335da347917Sbeck 
336da347917Sbeck 
337da347917Sbeck 			/* Same for  A  and  Y.  Afterwards, (2) still holds. */
338da347917Sbeck 			shift = 0;
339da347917Sbeck 			while (!BN_is_bit_set(A, shift)) /* note that 0 < A */
340da347917Sbeck 			{
341da347917Sbeck 				shift++;
342da347917Sbeck 
3432bd9bb84Sjsing 				if (BN_is_odd(Y)) {
3442bd9bb84Sjsing 					if (!BN_uadd(Y, Y, n))
3452bd9bb84Sjsing 						goto err;
346da347917Sbeck 				}
347da347917Sbeck 				/* now Y is even */
3482bd9bb84Sjsing 				if (!BN_rshift1(Y, Y))
3492bd9bb84Sjsing 					goto err;
350da347917Sbeck 			}
3512bd9bb84Sjsing 			if (shift > 0) {
3522bd9bb84Sjsing 				if (!BN_rshift(A, A, shift))
3532bd9bb84Sjsing 					goto err;
354da347917Sbeck 			}
355da347917Sbeck 
356da347917Sbeck 
357da347917Sbeck 			/* We still have (1) and (2).
358da347917Sbeck 			 * Both  A  and  B  are odd.
359da347917Sbeck 			 * The following computations ensure that
360da347917Sbeck 			 *
361da347917Sbeck 			 *     0 <= B < |n|,
362da347917Sbeck 			 *      0 < A < |n|,
363da347917Sbeck 			 * (1) -sign*X*a  ==  B   (mod |n|),
364da347917Sbeck 			 * (2)  sign*Y*a  ==  A   (mod |n|),
365da347917Sbeck 			 *
366da347917Sbeck 			 * and that either  A  or  B  is even in the next iteration.
367da347917Sbeck 			 */
3682bd9bb84Sjsing 			if (BN_ucmp(B, A) >= 0) {
369da347917Sbeck 				/* -sign*(X + Y)*a == B - A  (mod |n|) */
3702bd9bb84Sjsing 				if (!BN_uadd(X, X, Y))
3712bd9bb84Sjsing 					goto err;
372da347917Sbeck 				/* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
373da347917Sbeck 				 * actually makes the algorithm slower */
3742bd9bb84Sjsing 				if (!BN_usub(B, B, A))
3752bd9bb84Sjsing 					goto err;
3762bd9bb84Sjsing 			} else {
377da347917Sbeck 				/*  sign*(X + Y)*a == A - B  (mod |n|) */
3782bd9bb84Sjsing 				if (!BN_uadd(Y, Y, X))
3792bd9bb84Sjsing 					goto err;
380da347917Sbeck 				/* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
3812bd9bb84Sjsing 				if (!BN_usub(A, A, B))
3822bd9bb84Sjsing 					goto err;
383da347917Sbeck 			}
384da347917Sbeck 		}
3852bd9bb84Sjsing 	} else {
386da347917Sbeck 		/* general inversion algorithm */
387da347917Sbeck 
3882bd9bb84Sjsing 		while (!BN_is_zero(B)) {
389da347917Sbeck 			BIGNUM *tmp;
390da347917Sbeck 
391da347917Sbeck 			/*
392da347917Sbeck 			 *      0 < B < A,
393da347917Sbeck 			 * (*) -sign*X*a  ==  B   (mod |n|),
394da347917Sbeck 			 *      sign*Y*a  ==  A   (mod |n|)
395da347917Sbeck 			 */
396da347917Sbeck 
397da347917Sbeck 			/* (D, M) := (A/B, A%B) ... */
3982bd9bb84Sjsing 			if (BN_num_bits(A) == BN_num_bits(B)) {
3992bd9bb84Sjsing 				if (!BN_one(D))
4002bd9bb84Sjsing 					goto err;
4012bd9bb84Sjsing 				if (!BN_sub(M, A, B))
4022bd9bb84Sjsing 					goto err;
4032bd9bb84Sjsing 			} else if (BN_num_bits(A) == BN_num_bits(B) + 1) {
404da347917Sbeck 				/* A/B is 1, 2, or 3 */
4052bd9bb84Sjsing 				if (!BN_lshift1(T, B))
4062bd9bb84Sjsing 					goto err;
4072bd9bb84Sjsing 				if (BN_ucmp(A, T) < 0) {
408da347917Sbeck 					/* A < 2*B, so D=1 */
4092bd9bb84Sjsing 					if (!BN_one(D))
4102bd9bb84Sjsing 						goto err;
4112bd9bb84Sjsing 					if (!BN_sub(M, A, B))
4122bd9bb84Sjsing 						goto err;
4132bd9bb84Sjsing 				} else {
414da347917Sbeck 					/* A >= 2*B, so D=2 or D=3 */
4152bd9bb84Sjsing 					if (!BN_sub(M, A, T))
4162bd9bb84Sjsing 						goto err;
417da347917Sbeck 					if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */
4182bd9bb84Sjsing 						if (BN_ucmp(A, D) < 0) {
419da347917Sbeck 						/* A < 3*B, so D=2 */
4202bd9bb84Sjsing 						if (!BN_set_word(D, 2))
4212bd9bb84Sjsing 							goto err;
422da347917Sbeck 						/* M (= A - 2*B) already has the correct value */
4232bd9bb84Sjsing 					} else {
424da347917Sbeck 						/* only D=3 remains */
4252bd9bb84Sjsing 						if (!BN_set_word(D, 3))
4262bd9bb84Sjsing 							goto err;
427da347917Sbeck 						/* currently  M = A - 2*B,  but we need  M = A - 3*B */
4282bd9bb84Sjsing 						if (!BN_sub(M, M, B))
4292bd9bb84Sjsing 							goto err;
430da347917Sbeck 					}
431da347917Sbeck 				}
4322bd9bb84Sjsing 			} else {
433923a8ed2Sbeck 				if (!BN_div_nonct(D, M, A, B, ctx))
4342bd9bb84Sjsing 					goto err;
435da347917Sbeck 			}
436da347917Sbeck 
437da347917Sbeck 			/* Now
438da347917Sbeck 			 *      A = D*B + M;
439da347917Sbeck 			 * thus we have
440da347917Sbeck 			 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
441da347917Sbeck 			 */
442da347917Sbeck 			tmp = A; /* keep the BIGNUM object, the value does not matter */
443da347917Sbeck 
444da347917Sbeck 			/* (A, B) := (B, A mod B) ... */
4455b37fcf3Sryker 			A = B;
4465b37fcf3Sryker 			B = M;
447da347917Sbeck 			/* ... so we have  0 <= B < A  again */
4485b37fcf3Sryker 
449da347917Sbeck 			/* Since the former  M  is now  B  and the former  B  is now  A,
450da347917Sbeck 			 * (**) translates into
451da347917Sbeck 			 *       sign*Y*a  ==  D*A + B    (mod |n|),
452da347917Sbeck 			 * i.e.
453da347917Sbeck 			 *       sign*Y*a - D*A  ==  B    (mod |n|).
454da347917Sbeck 			 * Similarly, (*) translates into
455da347917Sbeck 			 *      -sign*X*a  ==  A          (mod |n|).
456da347917Sbeck 			 *
457da347917Sbeck 			 * Thus,
458da347917Sbeck 			 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
459da347917Sbeck 			 * i.e.
460da347917Sbeck 			 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
461da347917Sbeck 			 *
462da347917Sbeck 			 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
463da347917Sbeck 			 *      -sign*X*a  ==  B   (mod |n|),
464da347917Sbeck 			 *       sign*Y*a  ==  A   (mod |n|).
465da347917Sbeck 			 * Note that  X  and  Y  stay non-negative all the time.
466da347917Sbeck 			 */
467da347917Sbeck 
468da347917Sbeck 			/* most of the time D is very small, so we can optimize tmp := D*X+Y */
4692bd9bb84Sjsing 			if (BN_is_one(D)) {
4702bd9bb84Sjsing 				if (!BN_add(tmp, X, Y))
4712bd9bb84Sjsing 					goto err;
4722bd9bb84Sjsing 			} else {
4732bd9bb84Sjsing 				if (BN_is_word(D, 2)) {
4742bd9bb84Sjsing 					if (!BN_lshift1(tmp, X))
4752bd9bb84Sjsing 						goto err;
4762bd9bb84Sjsing 				} else if (BN_is_word(D, 4)) {
4772bd9bb84Sjsing 					if (!BN_lshift(tmp, X, 2))
4782bd9bb84Sjsing 						goto err;
4792bd9bb84Sjsing 				} else if (D->top == 1) {
4802bd9bb84Sjsing 					if (!BN_copy(tmp, X))
4812bd9bb84Sjsing 						goto err;
4822bd9bb84Sjsing 					if (!BN_mul_word(tmp, D->d[0]))
4832bd9bb84Sjsing 						goto err;
4842bd9bb84Sjsing 				} else {
4852bd9bb84Sjsing 					if (!BN_mul(tmp, D,X, ctx))
4862bd9bb84Sjsing 						goto err;
487da347917Sbeck 				}
4882bd9bb84Sjsing 				if (!BN_add(tmp, tmp, Y))
4892bd9bb84Sjsing 					goto err;
490da347917Sbeck 			}
491da347917Sbeck 
492da347917Sbeck 			M = Y; /* keep the BIGNUM object, the value does not matter */
4935b37fcf3Sryker 			Y = X;
494da347917Sbeck 			X = tmp;
4955b37fcf3Sryker 			sign = -sign;
4965b37fcf3Sryker 		}
497da347917Sbeck 	}
498da347917Sbeck 
499da347917Sbeck 	/*
500da347917Sbeck 	 * The while loop (Euclid's algorithm) ends when
501da347917Sbeck 	 *      A == gcd(a,n);
502da347917Sbeck 	 * we have
503da347917Sbeck 	 *       sign*Y*a  ==  A  (mod |n|),
504da347917Sbeck 	 * where  Y  is non-negative.
505da347917Sbeck 	 */
506da347917Sbeck 
5072bd9bb84Sjsing 	if (sign < 0) {
5082bd9bb84Sjsing 		if (!BN_sub(Y, n, Y))
5092bd9bb84Sjsing 			goto err;
5105b37fcf3Sryker 	}
511da347917Sbeck 	/* Now  Y*a  ==  A  (mod |n|).  */
512da347917Sbeck 
5132bd9bb84Sjsing 	if (BN_is_one(A)) {
514da347917Sbeck 		/* Y*a == 1  (mod |n|) */
5152bd9bb84Sjsing 		if (!Y->neg && BN_ucmp(Y, n) < 0) {
5162bd9bb84Sjsing 			if (!BN_copy(R, Y))
5172bd9bb84Sjsing 				goto err;
5182bd9bb84Sjsing 		} else {
5192bd9bb84Sjsing 			if (!BN_nnmod(R, Y,n, ctx))
5202bd9bb84Sjsing 				goto err;
521da347917Sbeck 		}
5222bd9bb84Sjsing 	} else {
5235067ae9fSbeck 		BNerror(BN_R_NO_INVERSE);
5245b37fcf3Sryker 		goto err;
5255b37fcf3Sryker 	}
5265b37fcf3Sryker 	ret = R;
5272bd9bb84Sjsing 
5285b37fcf3Sryker err:
5292bd9bb84Sjsing 	if ((ret == NULL) && (in == NULL))
5302bd9bb84Sjsing 		BN_free(R);
531ba5406e9Sbeck 	BN_CTX_end(ctx);
5324fcf65c5Sdjm 	return (ret);
5334fcf65c5Sdjm }
5344fcf65c5Sdjm 
535b0f5cbc3Sbeck BIGNUM *
536b0f5cbc3Sbeck BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
537b0f5cbc3Sbeck {
538b0f5cbc3Sbeck 	int ct = ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) ||
539b0f5cbc3Sbeck 	    (BN_get_flags(n, BN_FLG_CONSTTIME) != 0));
540b0f5cbc3Sbeck 	return BN_mod_inverse_internal(in, a, n, ctx, ct);
541b0f5cbc3Sbeck }
542b0f5cbc3Sbeck 
543b0f5cbc3Sbeck BIGNUM *
544b0f5cbc3Sbeck BN_mod_inverse_nonct(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
545b0f5cbc3Sbeck {
546b0f5cbc3Sbeck 	return BN_mod_inverse_internal(in, a, n, ctx, 0);
547b0f5cbc3Sbeck }
548b0f5cbc3Sbeck 
549b0f5cbc3Sbeck BIGNUM *
550b0f5cbc3Sbeck BN_mod_inverse_ct(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
551b0f5cbc3Sbeck {
552b0f5cbc3Sbeck 	return BN_mod_inverse_internal(in, a, n, ctx, 1);
553b0f5cbc3Sbeck }
5544fcf65c5Sdjm 
5554fcf65c5Sdjm /* BN_mod_inverse_no_branch is a special version of BN_mod_inverse.
5564fcf65c5Sdjm  * It does not contain branches that may leak sensitive information.
5574fcf65c5Sdjm  */
5582bd9bb84Sjsing static BIGNUM *
5592bd9bb84Sjsing BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
5602bd9bb84Sjsing     BN_CTX *ctx)
5614fcf65c5Sdjm {
5624fcf65c5Sdjm 	BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
5634fcf65c5Sdjm 	BIGNUM local_A, local_B;
5644fcf65c5Sdjm 	BIGNUM *pA, *pB;
5654fcf65c5Sdjm 	BIGNUM *ret = NULL;
5664fcf65c5Sdjm 	int sign;
5674fcf65c5Sdjm 
5684fcf65c5Sdjm 
56993ee03aaStb 	BN_init(&local_A);
57093ee03aaStb 	BN_init(&local_B);
57193ee03aaStb 
5724fcf65c5Sdjm 	BN_CTX_start(ctx);
573aa389b8cSjsing 	if ((A = BN_CTX_get(ctx)) == NULL)
574aa389b8cSjsing 		goto err;
575aa389b8cSjsing 	if ((B = BN_CTX_get(ctx)) == NULL)
576aa389b8cSjsing 		goto err;
577aa389b8cSjsing 	if ((X = BN_CTX_get(ctx)) == NULL)
578aa389b8cSjsing 		goto err;
579aa389b8cSjsing 	if ((D = BN_CTX_get(ctx)) == NULL)
580aa389b8cSjsing 		goto err;
581aa389b8cSjsing 	if ((M = BN_CTX_get(ctx)) == NULL)
582aa389b8cSjsing 		goto err;
583aa389b8cSjsing 	if ((Y = BN_CTX_get(ctx)) == NULL)
584aa389b8cSjsing 		goto err;
585aa389b8cSjsing 	if ((T = BN_CTX_get(ctx)) == NULL)
5862bd9bb84Sjsing 		goto err;
5874fcf65c5Sdjm 
5884fcf65c5Sdjm 	if (in == NULL)
5894fcf65c5Sdjm 		R = BN_new();
5904fcf65c5Sdjm 	else
5914fcf65c5Sdjm 		R = in;
5922bd9bb84Sjsing 	if (R == NULL)
5932bd9bb84Sjsing 		goto err;
5944fcf65c5Sdjm 
595dd1a6ee8Sjsing 	if (!BN_one(X))
596dd1a6ee8Sjsing 		goto err;
5974fcf65c5Sdjm 	BN_zero(Y);
5982bd9bb84Sjsing 	if (BN_copy(B, a) == NULL)
5992bd9bb84Sjsing 		goto err;
6002bd9bb84Sjsing 	if (BN_copy(A, n) == NULL)
6012bd9bb84Sjsing 		goto err;
6024fcf65c5Sdjm 	A->neg = 0;
6034fcf65c5Sdjm 
6042bd9bb84Sjsing 	if (B->neg || (BN_ucmp(B, A) >= 0)) {
60593ee03aaStb 		/*
60693ee03aaStb 		 * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
6074fcf65c5Sdjm 		 * BN_div_no_branch will be called eventually.
6084fcf65c5Sdjm 		 */
6094fcf65c5Sdjm 		pB = &local_B;
61093ee03aaStb 		/* BN_init() done at the top of the function. */
6114fcf65c5Sdjm 		BN_with_flags(pB, B, BN_FLG_CONSTTIME);
6122bd9bb84Sjsing 		if (!BN_nnmod(B, pB, A, ctx))
6132bd9bb84Sjsing 			goto err;
6144fcf65c5Sdjm 	}
6154fcf65c5Sdjm 	sign = -1;
6164fcf65c5Sdjm 	/* From  B = a mod |n|,  A = |n|  it follows that
6174fcf65c5Sdjm 	 *
6184fcf65c5Sdjm 	 *      0 <= B < A,
6194fcf65c5Sdjm 	 *     -sign*X*a  ==  B   (mod |n|),
6204fcf65c5Sdjm 	 *      sign*Y*a  ==  A   (mod |n|).
6214fcf65c5Sdjm 	 */
6224fcf65c5Sdjm 
6232bd9bb84Sjsing 	while (!BN_is_zero(B)) {
6244fcf65c5Sdjm 		BIGNUM *tmp;
6254fcf65c5Sdjm 
6264fcf65c5Sdjm 		/*
6274fcf65c5Sdjm 		 *      0 < B < A,
6284fcf65c5Sdjm 		 * (*) -sign*X*a  ==  B   (mod |n|),
6294fcf65c5Sdjm 		 *      sign*Y*a  ==  A   (mod |n|)
6304fcf65c5Sdjm 		 */
6314fcf65c5Sdjm 
63293ee03aaStb 		/*
63393ee03aaStb 		 * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
6344fcf65c5Sdjm 		 * BN_div_no_branch will be called eventually.
6354fcf65c5Sdjm 		 */
6364fcf65c5Sdjm 		pA = &local_A;
63793ee03aaStb 		/* BN_init() done at the top of the function. */
6384fcf65c5Sdjm 		BN_with_flags(pA, A, BN_FLG_CONSTTIME);
6394fcf65c5Sdjm 
6404fcf65c5Sdjm 		/* (D, M) := (A/B, A%B) ... */
64144adc1eaSbeck 		if (!BN_div_ct(D, M, pA, B, ctx))
6422bd9bb84Sjsing 			goto err;
6434fcf65c5Sdjm 
6444fcf65c5Sdjm 		/* Now
6454fcf65c5Sdjm 		 *      A = D*B + M;
6464fcf65c5Sdjm 		 * thus we have
6474fcf65c5Sdjm 		 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
6484fcf65c5Sdjm 		 */
6494fcf65c5Sdjm 		tmp = A; /* keep the BIGNUM object, the value does not matter */
6504fcf65c5Sdjm 
6514fcf65c5Sdjm 		/* (A, B) := (B, A mod B) ... */
6524fcf65c5Sdjm 		A = B;
6534fcf65c5Sdjm 		B = M;
6544fcf65c5Sdjm 		/* ... so we have  0 <= B < A  again */
6554fcf65c5Sdjm 
6564fcf65c5Sdjm 		/* Since the former  M  is now  B  and the former  B  is now  A,
6574fcf65c5Sdjm 		 * (**) translates into
6584fcf65c5Sdjm 		 *       sign*Y*a  ==  D*A + B    (mod |n|),
6594fcf65c5Sdjm 		 * i.e.
6604fcf65c5Sdjm 		 *       sign*Y*a - D*A  ==  B    (mod |n|).
6614fcf65c5Sdjm 		 * Similarly, (*) translates into
6624fcf65c5Sdjm 		 *      -sign*X*a  ==  A          (mod |n|).
6634fcf65c5Sdjm 		 *
6644fcf65c5Sdjm 		 * Thus,
6654fcf65c5Sdjm 		 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
6664fcf65c5Sdjm 		 * i.e.
6674fcf65c5Sdjm 		 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
6684fcf65c5Sdjm 		 *
6694fcf65c5Sdjm 		 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
6704fcf65c5Sdjm 		 *      -sign*X*a  ==  B   (mod |n|),
6714fcf65c5Sdjm 		 *       sign*Y*a  ==  A   (mod |n|).
6724fcf65c5Sdjm 		 * Note that  X  and  Y  stay non-negative all the time.
6734fcf65c5Sdjm 		 */
6744fcf65c5Sdjm 
6752bd9bb84Sjsing 		if (!BN_mul(tmp, D, X, ctx))
6762bd9bb84Sjsing 			goto err;
6772bd9bb84Sjsing 		if (!BN_add(tmp, tmp, Y))
6782bd9bb84Sjsing 			goto err;
6794fcf65c5Sdjm 
6804fcf65c5Sdjm 		M = Y; /* keep the BIGNUM object, the value does not matter */
6814fcf65c5Sdjm 		Y = X;
6824fcf65c5Sdjm 		X = tmp;
6834fcf65c5Sdjm 		sign = -sign;
6844fcf65c5Sdjm 	}
6854fcf65c5Sdjm 
6864fcf65c5Sdjm 	/*
6874fcf65c5Sdjm 	 * The while loop (Euclid's algorithm) ends when
6884fcf65c5Sdjm 	 *      A == gcd(a,n);
6894fcf65c5Sdjm 	 * we have
6904fcf65c5Sdjm 	 *       sign*Y*a  ==  A  (mod |n|),
6914fcf65c5Sdjm 	 * where  Y  is non-negative.
6924fcf65c5Sdjm 	 */
6934fcf65c5Sdjm 
6942bd9bb84Sjsing 	if (sign < 0) {
6952bd9bb84Sjsing 		if (!BN_sub(Y, n, Y))
6962bd9bb84Sjsing 			goto err;
6974fcf65c5Sdjm 	}
6984fcf65c5Sdjm 	/* Now  Y*a  ==  A  (mod |n|).  */
6994fcf65c5Sdjm 
7002bd9bb84Sjsing 	if (BN_is_one(A)) {
7014fcf65c5Sdjm 		/* Y*a == 1  (mod |n|) */
7022bd9bb84Sjsing 		if (!Y->neg && BN_ucmp(Y, n) < 0) {
7032bd9bb84Sjsing 			if (!BN_copy(R, Y))
7042bd9bb84Sjsing 				goto err;
7052bd9bb84Sjsing 		} else {
7062bd9bb84Sjsing 			if (!BN_nnmod(R, Y, n, ctx))
7072bd9bb84Sjsing 				goto err;
7084fcf65c5Sdjm 		}
7092bd9bb84Sjsing 	} else {
7105067ae9fSbeck 		BNerror(BN_R_NO_INVERSE);
7114fcf65c5Sdjm 		goto err;
7124fcf65c5Sdjm 	}
7134fcf65c5Sdjm 	ret = R;
7142bd9bb84Sjsing 
7154fcf65c5Sdjm err:
7162bd9bb84Sjsing 	if ((ret == NULL) && (in == NULL))
7172bd9bb84Sjsing 		BN_free(R);
7184fcf65c5Sdjm 	BN_CTX_end(ctx);
7195b37fcf3Sryker 	return (ret);
7205b37fcf3Sryker }
721572569cdSbeck 
722572569cdSbeck /*
723572569cdSbeck  * BN_gcd_no_branch is a special version of BN_mod_inverse_no_branch.
724572569cdSbeck  * that returns the GCD.
725572569cdSbeck  */
726572569cdSbeck static BIGNUM *
727572569cdSbeck BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
728572569cdSbeck     BN_CTX *ctx)
729572569cdSbeck {
730572569cdSbeck 	BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
731572569cdSbeck 	BIGNUM local_A, local_B;
732572569cdSbeck 	BIGNUM *pA, *pB;
733572569cdSbeck 	BIGNUM *ret = NULL;
734572569cdSbeck 	int sign;
735572569cdSbeck 
736572569cdSbeck 	if (in == NULL)
737572569cdSbeck 		goto err;
738572569cdSbeck 	R = in;
739572569cdSbeck 
74093ee03aaStb 	BN_init(&local_A);
74193ee03aaStb 	BN_init(&local_B);
74293ee03aaStb 
743572569cdSbeck 
744572569cdSbeck 	BN_CTX_start(ctx);
745572569cdSbeck 	if ((A = BN_CTX_get(ctx)) == NULL)
746572569cdSbeck 		goto err;
747572569cdSbeck 	if ((B = BN_CTX_get(ctx)) == NULL)
748572569cdSbeck 		goto err;
749572569cdSbeck 	if ((X = BN_CTX_get(ctx)) == NULL)
750572569cdSbeck 		goto err;
751572569cdSbeck 	if ((D = BN_CTX_get(ctx)) == NULL)
752572569cdSbeck 		goto err;
753572569cdSbeck 	if ((M = BN_CTX_get(ctx)) == NULL)
754572569cdSbeck 		goto err;
755572569cdSbeck 	if ((Y = BN_CTX_get(ctx)) == NULL)
756572569cdSbeck 		goto err;
757572569cdSbeck 	if ((T = BN_CTX_get(ctx)) == NULL)
758572569cdSbeck 		goto err;
759572569cdSbeck 
760dd1a6ee8Sjsing 	if (!BN_one(X))
761dd1a6ee8Sjsing 		goto err;
762572569cdSbeck 	BN_zero(Y);
763572569cdSbeck 	if (BN_copy(B, a) == NULL)
764572569cdSbeck 		goto err;
765572569cdSbeck 	if (BN_copy(A, n) == NULL)
766572569cdSbeck 		goto err;
767572569cdSbeck 	A->neg = 0;
768572569cdSbeck 
769572569cdSbeck 	if (B->neg || (BN_ucmp(B, A) >= 0)) {
77093ee03aaStb 		/*
77193ee03aaStb 		 * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
772572569cdSbeck 		 * BN_div_no_branch will be called eventually.
773572569cdSbeck 		 */
774572569cdSbeck 		pB = &local_B;
77593ee03aaStb 		/* BN_init() done at the top of the function. */
776572569cdSbeck 		BN_with_flags(pB, B, BN_FLG_CONSTTIME);
777572569cdSbeck 		if (!BN_nnmod(B, pB, A, ctx))
778572569cdSbeck 			goto err;
779572569cdSbeck 	}
780572569cdSbeck 	sign = -1;
781572569cdSbeck 	/* From  B = a mod |n|,  A = |n|  it follows that
782572569cdSbeck 	 *
783572569cdSbeck 	 *      0 <= B < A,
784572569cdSbeck 	 *     -sign*X*a  ==  B   (mod |n|),
785572569cdSbeck 	 *      sign*Y*a  ==  A   (mod |n|).
786572569cdSbeck 	 */
787572569cdSbeck 
788572569cdSbeck 	while (!BN_is_zero(B)) {
789572569cdSbeck 		BIGNUM *tmp;
790572569cdSbeck 
791572569cdSbeck 		/*
792572569cdSbeck 		 *      0 < B < A,
793572569cdSbeck 		 * (*) -sign*X*a  ==  B   (mod |n|),
794572569cdSbeck 		 *      sign*Y*a  ==  A   (mod |n|)
795572569cdSbeck 		 */
796572569cdSbeck 
79793ee03aaStb 		/*
79893ee03aaStb 		 * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
799572569cdSbeck 		 * BN_div_no_branch will be called eventually.
800572569cdSbeck 		 */
801572569cdSbeck 		pA = &local_A;
80293ee03aaStb 		/* BN_init() done at the top of the function. */
803572569cdSbeck 		BN_with_flags(pA, A, BN_FLG_CONSTTIME);
804572569cdSbeck 
805572569cdSbeck 		/* (D, M) := (A/B, A%B) ... */
806572569cdSbeck 		if (!BN_div_ct(D, M, pA, B, ctx))
807572569cdSbeck 			goto err;
808572569cdSbeck 
809572569cdSbeck 		/* Now
810572569cdSbeck 		 *      A = D*B + M;
811572569cdSbeck 		 * thus we have
812572569cdSbeck 		 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
813572569cdSbeck 		 */
814572569cdSbeck 		tmp = A; /* keep the BIGNUM object, the value does not matter */
815572569cdSbeck 
816572569cdSbeck 		/* (A, B) := (B, A mod B) ... */
817572569cdSbeck 		A = B;
818572569cdSbeck 		B = M;
819572569cdSbeck 		/* ... so we have  0 <= B < A  again */
820572569cdSbeck 
821572569cdSbeck 		/* Since the former  M  is now  B  and the former  B  is now  A,
822572569cdSbeck 		 * (**) translates into
823572569cdSbeck 		 *       sign*Y*a  ==  D*A + B    (mod |n|),
824572569cdSbeck 		 * i.e.
825572569cdSbeck 		 *       sign*Y*a - D*A  ==  B    (mod |n|).
826572569cdSbeck 		 * Similarly, (*) translates into
827572569cdSbeck 		 *      -sign*X*a  ==  A          (mod |n|).
828572569cdSbeck 		 *
829572569cdSbeck 		 * Thus,
830572569cdSbeck 		 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
831572569cdSbeck 		 * i.e.
832572569cdSbeck 		 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
833572569cdSbeck 		 *
834572569cdSbeck 		 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
835572569cdSbeck 		 *      -sign*X*a  ==  B   (mod |n|),
836572569cdSbeck 		 *       sign*Y*a  ==  A   (mod |n|).
837572569cdSbeck 		 * Note that  X  and  Y  stay non-negative all the time.
838572569cdSbeck 		 */
839572569cdSbeck 
840572569cdSbeck 		if (!BN_mul(tmp, D, X, ctx))
841572569cdSbeck 			goto err;
842572569cdSbeck 		if (!BN_add(tmp, tmp, Y))
843572569cdSbeck 			goto err;
844572569cdSbeck 
845572569cdSbeck 		M = Y; /* keep the BIGNUM object, the value does not matter */
846572569cdSbeck 		Y = X;
847572569cdSbeck 		X = tmp;
848572569cdSbeck 		sign = -sign;
849572569cdSbeck 	}
850572569cdSbeck 
851572569cdSbeck 	/*
852572569cdSbeck 	 * The while loop (Euclid's algorithm) ends when
853572569cdSbeck 	 *      A == gcd(a,n);
854572569cdSbeck 	 */
855572569cdSbeck 
856572569cdSbeck 	if (!BN_copy(R, A))
857572569cdSbeck 		goto err;
858572569cdSbeck 	ret = R;
859572569cdSbeck err:
860572569cdSbeck 	if ((ret == NULL) && (in == NULL))
861572569cdSbeck 		BN_free(R);
862572569cdSbeck 	BN_CTX_end(ctx);
863572569cdSbeck 	return (ret);
864572569cdSbeck }
865