Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "os.h"
#include <mp.h>

// chinese remainder theorem
//
// handbook of applied cryptography, menezes et al, 1997, pp 610 - 613

struct CRTpre
{
        int     n;              // number of moduli
        mpint   **m;            // pointer to moduli
        mpint   **c;            // precomputed coefficients
        mpint   **p;            // precomputed products
        mpint   *a[1];          // local storage
};

// setup crt info, returns a newly created structure
CRTpre*
crtpre(int n, mpint **m)
{
        CRTpre *crt;
        int i, j;
        mpint *u;

        crt = malloc(sizeof(CRTpre)+sizeof(mpint)*3*n);
        if(crt == nil)
                sysfatal("crtpre: %r");
        crt->m = crt->a;
        crt->c = crt->a+n;
        crt->p = crt->c+n;
        crt->n = n;

        // make a copy of the moduli
        for(i = 0; i < n; i++)
                crt->m[i] = mpcopy(m[i]);

        // precompute the products
        u = mpcopy(mpone);
        for(i = 0; i < n; i++){
                mpmul(u, m[i], u);
                crt->p[i] = mpcopy(u);
        }

        // precompute the coefficients
        for(i = 1; i < n; i++){
                crt->c[i] = mpcopy(mpone);
                for(j = 0; j < i; j++){
                        mpinvert(m[j], m[i], u);
                        mpmul(u, crt->c[i], u);
                        mpmod(u, m[i], crt->c[i]);
                }
        }

        mpfree(u);

        return crt;             
}

void
crtprefree(CRTpre *crt)
{
        int i;

        for(i = 0; i < crt->n; i++){
                if(i != 0)
                        mpfree(crt->c[i]);
                mpfree(crt->p[i]);
                mpfree(crt->m[i]);
        }
        free(crt);
}

// convert to residues, returns a newly created structure
CRTres*
crtin(CRTpre *crt, mpint *x)
{
        int i;
        CRTres *res;

        res = malloc(sizeof(CRTres)+sizeof(mpint)*crt->n);
        if(res == nil)
                sysfatal("crtin: %r");
        res->n = crt->n;
        for(i = 0; i < res->n; i++){
                res->r[i] = mpnew(0);
                mpmod(x, crt->m[i], res->r[i]);
        }
        return res;
}

// garners algorithm for converting residue form to linear
void
crtout(CRTpre *crt, CRTres *res, mpint *x)
{
        mpint *u;
        int i;

        u = mpnew(0);
        mpassign(res->r[0], x);

        for(i = 1; i < crt->n; i++){
                mpsub(res->r[i], x, u);
                mpmul(u, crt->c[i], u);
                mpmod(u, crt->m[i], u);
                mpmul(u, crt->p[i-1], u);
                mpadd(x, u, x);
        }

        mpfree(u);
}

// free the residue
void
crtresfree(CRTres *res)
{
        int i;

        for(i = 0; i < res->n; i++)
                mpfree(res->r[i]);
        free(res);
}