xref: /inferno-os/libmp/port/mpextendedgcd.c (revision 7de2b42d50e3c05cc143e7b51284009b5e185581)
1*37da2899SCharles.Forsyth #include "os.h"
2*37da2899SCharles.Forsyth #include <mp.h>
3*37da2899SCharles.Forsyth 
4*37da2899SCharles.Forsyth #define iseven(a)	(((a)->p[0] & 1) == 0)
5*37da2899SCharles.Forsyth 
6*37da2899SCharles.Forsyth // extended binary gcd
7*37da2899SCharles.Forsyth //
8*37da2899SCharles.Forsyth // For a anv b it solves, v = gcd(a,b) and finds x and y s.t.
9*37da2899SCharles.Forsyth // ax + by = v
10*37da2899SCharles.Forsyth //
11*37da2899SCharles.Forsyth // Handbook of Applied Cryptography, Menezes et al, 1997, pg 608.
12*37da2899SCharles.Forsyth void
mpextendedgcd(mpint * a,mpint * b,mpint * v,mpint * x,mpint * y)13*37da2899SCharles.Forsyth mpextendedgcd(mpint *a, mpint *b, mpint *v, mpint *x, mpint *y)
14*37da2899SCharles.Forsyth {
15*37da2899SCharles.Forsyth 	mpint *u, *A, *B, *C, *D;
16*37da2899SCharles.Forsyth 	int g;
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 	if(a->sign < 0 || b->sign < 0){
19*37da2899SCharles.Forsyth 		mpassign(mpzero, v);
20*37da2899SCharles.Forsyth 		mpassign(mpzero, y);
21*37da2899SCharles.Forsyth 		mpassign(mpzero, x);
22*37da2899SCharles.Forsyth 		return;
23*37da2899SCharles.Forsyth 	}
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth 	if(a->top == 0){
26*37da2899SCharles.Forsyth 		mpassign(b, v);
27*37da2899SCharles.Forsyth 		mpassign(mpone, y);
28*37da2899SCharles.Forsyth 		mpassign(mpzero, x);
29*37da2899SCharles.Forsyth 		return;
30*37da2899SCharles.Forsyth 	}
31*37da2899SCharles.Forsyth 	if(b->top == 0){
32*37da2899SCharles.Forsyth 		mpassign(a, v);
33*37da2899SCharles.Forsyth 		mpassign(mpone, x);
34*37da2899SCharles.Forsyth 		mpassign(mpzero, y);
35*37da2899SCharles.Forsyth 		return;
36*37da2899SCharles.Forsyth 	}
37*37da2899SCharles.Forsyth 
38*37da2899SCharles.Forsyth 	g = 0;
39*37da2899SCharles.Forsyth 	a = mpcopy(a);
40*37da2899SCharles.Forsyth 	b = mpcopy(b);
41*37da2899SCharles.Forsyth 
42*37da2899SCharles.Forsyth 	while(iseven(a) && iseven(b)){
43*37da2899SCharles.Forsyth 		mpright(a, 1, a);
44*37da2899SCharles.Forsyth 		mpright(b, 1, b);
45*37da2899SCharles.Forsyth 		g++;
46*37da2899SCharles.Forsyth 	}
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth 	u = mpcopy(a);
49*37da2899SCharles.Forsyth 	mpassign(b, v);
50*37da2899SCharles.Forsyth 	A = mpcopy(mpone);
51*37da2899SCharles.Forsyth 	B = mpcopy(mpzero);
52*37da2899SCharles.Forsyth 	C = mpcopy(mpzero);
53*37da2899SCharles.Forsyth 	D = mpcopy(mpone);
54*37da2899SCharles.Forsyth 
55*37da2899SCharles.Forsyth 	for(;;) {
56*37da2899SCharles.Forsyth //		print("%B %B %B %B %B %B\n", u, v, A, B, C, D);
57*37da2899SCharles.Forsyth 		while(iseven(u)){
58*37da2899SCharles.Forsyth 			mpright(u, 1, u);
59*37da2899SCharles.Forsyth 			if(!iseven(A) || !iseven(B)) {
60*37da2899SCharles.Forsyth 				mpadd(A, b, A);
61*37da2899SCharles.Forsyth 				mpsub(B, a, B);
62*37da2899SCharles.Forsyth 			}
63*37da2899SCharles.Forsyth 			mpright(A, 1, A);
64*37da2899SCharles.Forsyth 			mpright(B, 1, B);
65*37da2899SCharles.Forsyth 		}
66*37da2899SCharles.Forsyth 
67*37da2899SCharles.Forsyth //		print("%B %B %B %B %B %B\n", u, v, A, B, C, D);
68*37da2899SCharles.Forsyth 		while(iseven(v)){
69*37da2899SCharles.Forsyth 			mpright(v, 1, v);
70*37da2899SCharles.Forsyth 			if(!iseven(C) || !iseven(D)) {
71*37da2899SCharles.Forsyth 				mpadd(C, b, C);
72*37da2899SCharles.Forsyth 				mpsub(D, a, D);
73*37da2899SCharles.Forsyth 			}
74*37da2899SCharles.Forsyth 			mpright(C, 1, C);
75*37da2899SCharles.Forsyth 			mpright(D, 1, D);
76*37da2899SCharles.Forsyth 		}
77*37da2899SCharles.Forsyth 
78*37da2899SCharles.Forsyth //		print("%B %B %B %B %B %B\n", u, v, A, B, C, D);
79*37da2899SCharles.Forsyth 		if(mpcmp(u, v) >= 0){
80*37da2899SCharles.Forsyth 			mpsub(u, v, u);
81*37da2899SCharles.Forsyth 			mpsub(A, C, A);
82*37da2899SCharles.Forsyth 			mpsub(B, D, B);
83*37da2899SCharles.Forsyth 		} else {
84*37da2899SCharles.Forsyth 			mpsub(v, u, v);
85*37da2899SCharles.Forsyth 			mpsub(C, A, C);
86*37da2899SCharles.Forsyth 			mpsub(D, B, D);
87*37da2899SCharles.Forsyth 		}
88*37da2899SCharles.Forsyth 
89*37da2899SCharles.Forsyth 		if(u->top == 0)
90*37da2899SCharles.Forsyth 			break;
91*37da2899SCharles.Forsyth 
92*37da2899SCharles.Forsyth 	}
93*37da2899SCharles.Forsyth 	mpassign(C, x);
94*37da2899SCharles.Forsyth 	mpassign(D, y);
95*37da2899SCharles.Forsyth 	mpleft(v, g, v);
96*37da2899SCharles.Forsyth 
97*37da2899SCharles.Forsyth 	mpfree(A);
98*37da2899SCharles.Forsyth 	mpfree(B);
99*37da2899SCharles.Forsyth 	mpfree(C);
100*37da2899SCharles.Forsyth 	mpfree(D);
101*37da2899SCharles.Forsyth 	mpfree(u);
102*37da2899SCharles.Forsyth 	mpfree(a);
103*37da2899SCharles.Forsyth 	mpfree(b);
104*37da2899SCharles.Forsyth }
105