17dd7cddfSDavid du Colombier #include "os.h"
27dd7cddfSDavid du Colombier #include <mp.h>
37dd7cddfSDavid du Colombier
49a747e4fSDavid du Colombier // extended euclid
59a747e4fSDavid du Colombier //
69a747e4fSDavid du Colombier // For a and b it solves, d = gcd(a,b) and finds x and y s.t.
77dd7cddfSDavid du Colombier // ax + by = d
89a747e4fSDavid du Colombier //
99a747e4fSDavid du Colombier // Handbook of Applied Cryptography, Menezes et al, 1997, pg 67
107dd7cddfSDavid du Colombier
117dd7cddfSDavid du Colombier void
mpeuclid(mpint * a,mpint * b,mpint * d,mpint * x,mpint * y)127dd7cddfSDavid du Colombier mpeuclid(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y)
137dd7cddfSDavid du Colombier {
147dd7cddfSDavid du Colombier mpint *tmp, *x0, *x1, *x2, *y0, *y1, *y2, *q, *r;
157dd7cddfSDavid du Colombier
16*39734e7eSDavid du Colombier if(a->sign<0 || b->sign<0)
17*39734e7eSDavid du Colombier sysfatal("mpeuclid: negative arg");
18*39734e7eSDavid du Colombier
197dd7cddfSDavid du Colombier if(mpcmp(a, b) < 0){
207dd7cddfSDavid du Colombier tmp = a;
217dd7cddfSDavid du Colombier a = b;
227dd7cddfSDavid du Colombier b = tmp;
237dd7cddfSDavid du Colombier tmp = x;
247dd7cddfSDavid du Colombier x = y;
257dd7cddfSDavid du Colombier y = tmp;
267dd7cddfSDavid du Colombier }
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier if(b->top == 0){
297dd7cddfSDavid du Colombier mpassign(a, d);
307dd7cddfSDavid du Colombier mpassign(mpone, x);
317dd7cddfSDavid du Colombier mpassign(mpzero, y);
327dd7cddfSDavid du Colombier return;
337dd7cddfSDavid du Colombier }
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier a = mpcopy(a);
367dd7cddfSDavid du Colombier b = mpcopy(b);
377dd7cddfSDavid du Colombier x0 = mpnew(0);
387dd7cddfSDavid du Colombier x1 = mpcopy(mpzero);
397dd7cddfSDavid du Colombier x2 = mpcopy(mpone);
407dd7cddfSDavid du Colombier y0 = mpnew(0);
417dd7cddfSDavid du Colombier y1 = mpcopy(mpone);
427dd7cddfSDavid du Colombier y2 = mpcopy(mpzero);
437dd7cddfSDavid du Colombier q = mpnew(0);
447dd7cddfSDavid du Colombier r = mpnew(0);
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier while(b->top != 0 && b->sign > 0){
477dd7cddfSDavid du Colombier // q = a/b
487dd7cddfSDavid du Colombier // r = a mod b
497dd7cddfSDavid du Colombier mpdiv(a, b, q, r);
507dd7cddfSDavid du Colombier // x0 = x2 - qx1
517dd7cddfSDavid du Colombier mpmul(q, x1, x0);
527dd7cddfSDavid du Colombier mpsub(x2, x0, x0);
537dd7cddfSDavid du Colombier // y0 = y2 - qy1
547dd7cddfSDavid du Colombier mpmul(q, y1, y0);
557dd7cddfSDavid du Colombier mpsub(y2, y0, y0);
567dd7cddfSDavid du Colombier // rotate values
577dd7cddfSDavid du Colombier tmp = a;
587dd7cddfSDavid du Colombier a = b;
597dd7cddfSDavid du Colombier b = r;
607dd7cddfSDavid du Colombier r = tmp;
617dd7cddfSDavid du Colombier tmp = x2;
627dd7cddfSDavid du Colombier x2 = x1;
637dd7cddfSDavid du Colombier x1 = x0;
647dd7cddfSDavid du Colombier x0 = tmp;
657dd7cddfSDavid du Colombier tmp = y2;
667dd7cddfSDavid du Colombier y2 = y1;
677dd7cddfSDavid du Colombier y1 = y0;
687dd7cddfSDavid du Colombier y0 = tmp;
697dd7cddfSDavid du Colombier }
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier mpassign(a, d);
727dd7cddfSDavid du Colombier mpassign(x2, x);
737dd7cddfSDavid du Colombier mpassign(y2, y);
747dd7cddfSDavid du Colombier
757dd7cddfSDavid du Colombier mpfree(x0);
767dd7cddfSDavid du Colombier mpfree(x1);
777dd7cddfSDavid du Colombier mpfree(x2);
787dd7cddfSDavid du Colombier mpfree(y0);
797dd7cddfSDavid du Colombier mpfree(y1);
807dd7cddfSDavid du Colombier mpfree(y2);
817dd7cddfSDavid du Colombier mpfree(q);
827dd7cddfSDavid du Colombier mpfree(r);
837dd7cddfSDavid du Colombier mpfree(a);
847dd7cddfSDavid du Colombier mpfree(b);
857dd7cddfSDavid du Colombier }
86