Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#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);
}