|  | #include "os.h" | 
|  | #include <mp.h> | 
|  |  | 
|  | /* extended euclid */ | 
|  | /* */ | 
|  | /* For a and b it solves, d = gcd(a,b) and finds x and y s.t. */ | 
|  | /* ax + by = d */ | 
|  | /* */ | 
|  | /* Handbook of Applied Cryptography, Menezes et al, 1997, pg 67 */ | 
|  |  | 
|  | void | 
|  | mpeuclid(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y) | 
|  | { | 
|  | mpint *tmp, *x0, *x1, *x2, *y0, *y1, *y2, *q, *r; | 
|  |  | 
|  | if(a->sign<0 || b->sign<0) | 
|  | sysfatal("mpeuclid: negative arg"); | 
|  |  | 
|  | if(mpcmp(a, b) < 0){ | 
|  | tmp = a; | 
|  | a = b; | 
|  | b = tmp; | 
|  | tmp = x; | 
|  | x = y; | 
|  | y = tmp; | 
|  | } | 
|  |  | 
|  | if(b->top == 0){ | 
|  | mpassign(a, d); | 
|  | mpassign(mpone, x); | 
|  | mpassign(mpzero, y); | 
|  | return; | 
|  | } | 
|  |  | 
|  | a = mpcopy(a); | 
|  | b = mpcopy(b); | 
|  | x0 = mpnew(0); | 
|  | x1 = mpcopy(mpzero); | 
|  | x2 = mpcopy(mpone); | 
|  | y0 = mpnew(0); | 
|  | y1 = mpcopy(mpone); | 
|  | y2 = mpcopy(mpzero); | 
|  | q = mpnew(0); | 
|  | r = mpnew(0); | 
|  |  | 
|  | while(b->top != 0 && b->sign > 0){ | 
|  | /* q = a/b */ | 
|  | /* r = a mod b */ | 
|  | mpdiv(a, b, q, r); | 
|  | /* x0 = x2 - qx1 */ | 
|  | mpmul(q, x1, x0); | 
|  | mpsub(x2, x0, x0); | 
|  | /* y0 = y2 - qy1 */ | 
|  | mpmul(q, y1, y0); | 
|  | mpsub(y2, y0, y0); | 
|  | /* rotate values */ | 
|  | tmp = a; | 
|  | a = b; | 
|  | b = r; | 
|  | r = tmp; | 
|  | tmp = x2; | 
|  | x2 = x1; | 
|  | x1 = x0; | 
|  | x0 = tmp; | 
|  | tmp = y2; | 
|  | y2 = y1; | 
|  | y1 = y0; | 
|  | y0 = tmp; | 
|  | } | 
|  |  | 
|  | mpassign(a, d); | 
|  | mpassign(x2, x); | 
|  | mpassign(y2, y); | 
|  |  | 
|  | mpfree(x0); | 
|  | mpfree(x1); | 
|  | mpfree(x2); | 
|  | mpfree(y0); | 
|  | mpfree(y1); | 
|  | mpfree(y2); | 
|  | mpfree(q); | 
|  | mpfree(r); | 
|  | mpfree(a); | 
|  | mpfree(b); | 
|  | } |