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