17dd7cddfSDavid du Colombier #include "os.h"
27dd7cddfSDavid du Colombier #include <mp.h>
37dd7cddfSDavid du Colombier #include <libsec.h>
47dd7cddfSDavid du Colombier
57dd7cddfSDavid du Colombier // chinese remainder theorem
67dd7cddfSDavid du Colombier //
7*9a747e4fSDavid du Colombier // handbook of applied cryptography, menezes et al, 1997, pp 610 - 613
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier struct CRTpre
107dd7cddfSDavid du Colombier {
117dd7cddfSDavid du Colombier int n; // number of moduli
127dd7cddfSDavid du Colombier mpint **m; // pointer to moduli
137dd7cddfSDavid du Colombier mpint **c; // precomputed coefficients
147dd7cddfSDavid du Colombier mpint **p; // precomputed products
157dd7cddfSDavid du Colombier mpint *a[1]; // local storage
167dd7cddfSDavid du Colombier };
177dd7cddfSDavid du Colombier
187dd7cddfSDavid du Colombier // setup crt info, returns a newly created structure
197dd7cddfSDavid du Colombier CRTpre*
crtpre(int n,mpint ** m)207dd7cddfSDavid du Colombier crtpre(int n, mpint **m)
217dd7cddfSDavid du Colombier {
227dd7cddfSDavid du Colombier CRTpre *crt;
237dd7cddfSDavid du Colombier int i, j;
247dd7cddfSDavid du Colombier mpint *u;
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier crt = malloc(sizeof(CRTpre)+sizeof(mpint)*3*n);
27*9a747e4fSDavid du Colombier if(crt == nil)
28*9a747e4fSDavid du Colombier sysfatal("crtpre: %r");
297dd7cddfSDavid du Colombier crt->m = crt->a;
307dd7cddfSDavid du Colombier crt->c = crt->a+n;
317dd7cddfSDavid du Colombier crt->p = crt->c+n;
327dd7cddfSDavid du Colombier crt->n = n;
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier // make a copy of the moduli
357dd7cddfSDavid du Colombier for(i = 0; i < n; i++)
367dd7cddfSDavid du Colombier crt->m[i] = mpcopy(m[i]);
377dd7cddfSDavid du Colombier
387dd7cddfSDavid du Colombier // precompute the products
397dd7cddfSDavid du Colombier u = mpcopy(mpone);
407dd7cddfSDavid du Colombier for(i = 0; i < n; i++){
417dd7cddfSDavid du Colombier mpmul(u, m[i], u);
427dd7cddfSDavid du Colombier crt->p[i] = mpcopy(u);
437dd7cddfSDavid du Colombier }
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier // precompute the coefficients
467dd7cddfSDavid du Colombier for(i = 1; i < n; i++){
477dd7cddfSDavid du Colombier crt->c[i] = mpcopy(mpone);
487dd7cddfSDavid du Colombier for(j = 0; j < i; j++){
497dd7cddfSDavid du Colombier mpinvert(m[j], m[i], u);
507dd7cddfSDavid du Colombier mpmul(u, crt->c[i], u);
517dd7cddfSDavid du Colombier mpmod(u, m[i], crt->c[i]);
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier }
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier mpfree(u);
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier return crt;
587dd7cddfSDavid du Colombier }
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier void
crtprefree(CRTpre * crt)617dd7cddfSDavid du Colombier crtprefree(CRTpre *crt)
627dd7cddfSDavid du Colombier {
637dd7cddfSDavid du Colombier int i;
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier for(i = 0; i < crt->n; i++){
667dd7cddfSDavid du Colombier if(i != 0)
677dd7cddfSDavid du Colombier mpfree(crt->c[i]);
687dd7cddfSDavid du Colombier mpfree(crt->p[i]);
697dd7cddfSDavid du Colombier mpfree(crt->m[i]);
707dd7cddfSDavid du Colombier }
717dd7cddfSDavid du Colombier free(crt);
727dd7cddfSDavid du Colombier }
737dd7cddfSDavid du Colombier
747dd7cddfSDavid du Colombier // convert to residues, returns a newly created structure
757dd7cddfSDavid du Colombier CRTres*
crtin(CRTpre * crt,mpint * x)767dd7cddfSDavid du Colombier crtin(CRTpre *crt, mpint *x)
777dd7cddfSDavid du Colombier {
787dd7cddfSDavid du Colombier int i;
797dd7cddfSDavid du Colombier CRTres *res;
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier res = malloc(sizeof(CRTres)+sizeof(mpint)*crt->n);
82*9a747e4fSDavid du Colombier if(res == nil)
83*9a747e4fSDavid du Colombier sysfatal("crtin: %r");
847dd7cddfSDavid du Colombier res->n = crt->n;
857dd7cddfSDavid du Colombier for(i = 0; i < res->n; i++){
867dd7cddfSDavid du Colombier res->r[i] = mpnew(0);
877dd7cddfSDavid du Colombier mpmod(x, crt->m[i], res->r[i]);
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier return res;
907dd7cddfSDavid du Colombier }
917dd7cddfSDavid du Colombier
927dd7cddfSDavid du Colombier // garners algorithm for converting residue form to linear
937dd7cddfSDavid du Colombier void
crtout(CRTpre * crt,CRTres * res,mpint * x)947dd7cddfSDavid du Colombier crtout(CRTpre *crt, CRTres *res, mpint *x)
957dd7cddfSDavid du Colombier {
967dd7cddfSDavid du Colombier mpint *u;
977dd7cddfSDavid du Colombier int i;
987dd7cddfSDavid du Colombier
997dd7cddfSDavid du Colombier u = mpnew(0);
1007dd7cddfSDavid du Colombier mpassign(res->r[0], x);
1017dd7cddfSDavid du Colombier
1027dd7cddfSDavid du Colombier for(i = 1; i < crt->n; i++){
1037dd7cddfSDavid du Colombier mpsub(res->r[i], x, u);
1047dd7cddfSDavid du Colombier mpmul(u, crt->c[i], u);
1057dd7cddfSDavid du Colombier mpmod(u, crt->m[i], u);
1067dd7cddfSDavid du Colombier mpmul(u, crt->p[i-1], u);
1077dd7cddfSDavid du Colombier mpadd(x, u, x);
1087dd7cddfSDavid du Colombier }
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier mpfree(u);
1117dd7cddfSDavid du Colombier }
1127dd7cddfSDavid du Colombier
1137dd7cddfSDavid du Colombier // free the residue
1147dd7cddfSDavid du Colombier void
crtresfree(CRTres * res)1157dd7cddfSDavid du Colombier crtresfree(CRTres *res)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier int i;
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier for(i = 0; i < res->n; i++)
1207dd7cddfSDavid du Colombier mpfree(res->r[i]);
1217dd7cddfSDavid du Colombier free(res);
1227dd7cddfSDavid du Colombier }
123