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