bn_gcd.c revision 100936
1/* crypto/bn/bn_gcd.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdio.h>
60#include "cryptlib.h"
61#include "bn_lcl.h"
62
63static BIGNUM *euclid(BIGNUM *a, BIGNUM *b);
64
65int BN_gcd(BIGNUM *r, BIGNUM *in_a, BIGNUM *in_b, BN_CTX *ctx)
66	{
67	BIGNUM *a,*b,*t;
68	int ret=0;
69
70	bn_check_top(in_a);
71	bn_check_top(in_b);
72
73	BN_CTX_start(ctx);
74	a = BN_CTX_get(ctx);
75	b = BN_CTX_get(ctx);
76	if (a == NULL || b == NULL) goto err;
77
78	if (BN_copy(a,in_a) == NULL) goto err;
79	if (BN_copy(b,in_b) == NULL) goto err;
80
81	if (BN_cmp(a,b) < 0) { t=a; a=b; b=t; }
82	t=euclid(a,b);
83	if (t == NULL) goto err;
84
85	if (BN_copy(r,t) == NULL) goto err;
86	ret=1;
87err:
88	BN_CTX_end(ctx);
89	return(ret);
90	}
91
92static BIGNUM *euclid(BIGNUM *a, BIGNUM *b)
93	{
94	BIGNUM *t;
95	int shifts=0;
96
97	bn_check_top(a);
98	bn_check_top(b);
99
100	for (;;)
101		{
102		if (BN_is_zero(b))
103			break;
104
105		if (BN_is_odd(a))
106			{
107			if (BN_is_odd(b))
108				{
109				if (!BN_sub(a,a,b)) goto err;
110				if (!BN_rshift1(a,a)) goto err;
111				if (BN_cmp(a,b) < 0)
112					{ t=a; a=b; b=t; }
113				}
114			else		/* a odd - b even */
115				{
116				if (!BN_rshift1(b,b)) goto err;
117				if (BN_cmp(a,b) < 0)
118					{ t=a; a=b; b=t; }
119				}
120			}
121		else			/* a is even */
122			{
123			if (BN_is_odd(b))
124				{
125				if (!BN_rshift1(a,a)) goto err;
126				if (BN_cmp(a,b) < 0)
127					{ t=a; a=b; b=t; }
128				}
129			else		/* a even - b even */
130				{
131				if (!BN_rshift1(a,a)) goto err;
132				if (!BN_rshift1(b,b)) goto err;
133				shifts++;
134				}
135			}
136		}
137	if (shifts)
138		{
139		if (!BN_lshift(a,a,shifts)) goto err;
140		}
141	return(a);
142err:
143	return(NULL);
144	}
145
146/* solves ax == 1 (mod n) */
147BIGNUM *BN_mod_inverse(BIGNUM *in, BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
148	{
149	BIGNUM *A,*B,*X,*Y,*M,*D,*R=NULL;
150	BIGNUM *T,*ret=NULL;
151	int sign;
152
153	bn_check_top(a);
154	bn_check_top(n);
155
156	BN_CTX_start(ctx);
157	A = BN_CTX_get(ctx);
158	B = BN_CTX_get(ctx);
159	X = BN_CTX_get(ctx);
160	D = BN_CTX_get(ctx);
161	M = BN_CTX_get(ctx);
162	Y = BN_CTX_get(ctx);
163	if (Y == NULL) goto err;
164
165	if (in == NULL)
166		R=BN_new();
167	else
168		R=in;
169	if (R == NULL) goto err;
170
171	if (!BN_zero(X)) goto err;
172	if (!BN_one(Y)) goto err;
173	if (BN_copy(A,a) == NULL) goto err;
174	if (BN_copy(B,n) == NULL) goto err;
175	sign=1;
176
177	while (!BN_is_zero(B))
178		{
179		if (!BN_div(D,M,A,B,ctx)) goto err;
180		T=A;
181		A=B;
182		B=M;
183		/* T has a struct, M does not */
184
185		if (!BN_mul(T,D,X,ctx)) goto err;
186		if (!BN_add(T,T,Y)) goto err;
187		M=Y;
188		Y=X;
189		X=T;
190		sign= -sign;
191		}
192	if (sign < 0)
193		{
194		if (!BN_sub(Y,n,Y)) goto err;
195		}
196
197	if (BN_is_one(A))
198		{ if (!BN_mod(R,Y,n,ctx)) goto err; }
199	else
200		{
201		BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE);
202		goto err;
203		}
204	ret=R;
205err:
206	if ((ret == NULL) && (in == NULL)) BN_free(R);
207	BN_CTX_end(ctx);
208	return(ret);
209	}
210
211