1*37da2899SCharles.Forsyth #include "os.h"
2*37da2899SCharles.Forsyth #include <mp.h>
3*37da2899SCharles.Forsyth #include <libsec.h>
4*37da2899SCharles.Forsyth
5*37da2899SCharles.Forsyth // chinese remainder theorem
6*37da2899SCharles.Forsyth //
7*37da2899SCharles.Forsyth // handbook of applied cryptography, menezes et al, 1997, pp 610 - 613
8*37da2899SCharles.Forsyth
9*37da2899SCharles.Forsyth struct CRTpre
10*37da2899SCharles.Forsyth {
11*37da2899SCharles.Forsyth int n; // number of moduli
12*37da2899SCharles.Forsyth mpint **m; // pointer to moduli
13*37da2899SCharles.Forsyth mpint **c; // precomputed coefficients
14*37da2899SCharles.Forsyth mpint **p; // precomputed products
15*37da2899SCharles.Forsyth mpint *a[1]; // local storage
16*37da2899SCharles.Forsyth };
17*37da2899SCharles.Forsyth
18*37da2899SCharles.Forsyth // setup crt info, returns a newly created structure
19*37da2899SCharles.Forsyth CRTpre*
crtpre(int n,mpint ** m)20*37da2899SCharles.Forsyth crtpre(int n, mpint **m)
21*37da2899SCharles.Forsyth {
22*37da2899SCharles.Forsyth CRTpre *crt;
23*37da2899SCharles.Forsyth int i, j;
24*37da2899SCharles.Forsyth mpint *u;
25*37da2899SCharles.Forsyth
26*37da2899SCharles.Forsyth crt = malloc(sizeof(CRTpre)+sizeof(mpint)*3*n);
27*37da2899SCharles.Forsyth if(crt == nil)
28*37da2899SCharles.Forsyth sysfatal("crtpre: %r");
29*37da2899SCharles.Forsyth crt->m = crt->a;
30*37da2899SCharles.Forsyth crt->c = crt->a+n;
31*37da2899SCharles.Forsyth crt->p = crt->c+n;
32*37da2899SCharles.Forsyth crt->n = n;
33*37da2899SCharles.Forsyth
34*37da2899SCharles.Forsyth // make a copy of the moduli
35*37da2899SCharles.Forsyth for(i = 0; i < n; i++)
36*37da2899SCharles.Forsyth crt->m[i] = mpcopy(m[i]);
37*37da2899SCharles.Forsyth
38*37da2899SCharles.Forsyth // precompute the products
39*37da2899SCharles.Forsyth u = mpcopy(mpone);
40*37da2899SCharles.Forsyth for(i = 0; i < n; i++){
41*37da2899SCharles.Forsyth mpmul(u, m[i], u);
42*37da2899SCharles.Forsyth crt->p[i] = mpcopy(u);
43*37da2899SCharles.Forsyth }
44*37da2899SCharles.Forsyth
45*37da2899SCharles.Forsyth // precompute the coefficients
46*37da2899SCharles.Forsyth for(i = 1; i < n; i++){
47*37da2899SCharles.Forsyth crt->c[i] = mpcopy(mpone);
48*37da2899SCharles.Forsyth for(j = 0; j < i; j++){
49*37da2899SCharles.Forsyth mpinvert(m[j], m[i], u);
50*37da2899SCharles.Forsyth mpmul(u, crt->c[i], u);
51*37da2899SCharles.Forsyth mpmod(u, m[i], crt->c[i]);
52*37da2899SCharles.Forsyth }
53*37da2899SCharles.Forsyth }
54*37da2899SCharles.Forsyth
55*37da2899SCharles.Forsyth mpfree(u);
56*37da2899SCharles.Forsyth
57*37da2899SCharles.Forsyth return crt;
58*37da2899SCharles.Forsyth }
59*37da2899SCharles.Forsyth
60*37da2899SCharles.Forsyth void
crtprefree(CRTpre * crt)61*37da2899SCharles.Forsyth crtprefree(CRTpre *crt)
62*37da2899SCharles.Forsyth {
63*37da2899SCharles.Forsyth int i;
64*37da2899SCharles.Forsyth
65*37da2899SCharles.Forsyth for(i = 0; i < crt->n; i++){
66*37da2899SCharles.Forsyth if(i != 0)
67*37da2899SCharles.Forsyth mpfree(crt->c[i]);
68*37da2899SCharles.Forsyth mpfree(crt->p[i]);
69*37da2899SCharles.Forsyth mpfree(crt->m[i]);
70*37da2899SCharles.Forsyth }
71*37da2899SCharles.Forsyth free(crt);
72*37da2899SCharles.Forsyth }
73*37da2899SCharles.Forsyth
74*37da2899SCharles.Forsyth // convert to residues, returns a newly created structure
75*37da2899SCharles.Forsyth CRTres*
crtin(CRTpre * crt,mpint * x)76*37da2899SCharles.Forsyth crtin(CRTpre *crt, mpint *x)
77*37da2899SCharles.Forsyth {
78*37da2899SCharles.Forsyth int i;
79*37da2899SCharles.Forsyth CRTres *res;
80*37da2899SCharles.Forsyth
81*37da2899SCharles.Forsyth res = malloc(sizeof(CRTres)+sizeof(mpint)*crt->n);
82*37da2899SCharles.Forsyth if(res == nil)
83*37da2899SCharles.Forsyth sysfatal("crtin: %r");
84*37da2899SCharles.Forsyth res->n = crt->n;
85*37da2899SCharles.Forsyth for(i = 0; i < res->n; i++){
86*37da2899SCharles.Forsyth res->r[i] = mpnew(0);
87*37da2899SCharles.Forsyth mpmod(x, crt->m[i], res->r[i]);
88*37da2899SCharles.Forsyth }
89*37da2899SCharles.Forsyth return res;
90*37da2899SCharles.Forsyth }
91*37da2899SCharles.Forsyth
92*37da2899SCharles.Forsyth // garners algorithm for converting residue form to linear
93*37da2899SCharles.Forsyth void
crtout(CRTpre * crt,CRTres * res,mpint * x)94*37da2899SCharles.Forsyth crtout(CRTpre *crt, CRTres *res, mpint *x)
95*37da2899SCharles.Forsyth {
96*37da2899SCharles.Forsyth mpint *u;
97*37da2899SCharles.Forsyth int i;
98*37da2899SCharles.Forsyth
99*37da2899SCharles.Forsyth u = mpnew(0);
100*37da2899SCharles.Forsyth mpassign(res->r[0], x);
101*37da2899SCharles.Forsyth
102*37da2899SCharles.Forsyth for(i = 1; i < crt->n; i++){
103*37da2899SCharles.Forsyth mpsub(res->r[i], x, u);
104*37da2899SCharles.Forsyth mpmul(u, crt->c[i], u);
105*37da2899SCharles.Forsyth mpmod(u, crt->m[i], u);
106*37da2899SCharles.Forsyth mpmul(u, crt->p[i-1], u);
107*37da2899SCharles.Forsyth mpadd(x, u, x);
108*37da2899SCharles.Forsyth }
109*37da2899SCharles.Forsyth
110*37da2899SCharles.Forsyth mpfree(u);
111*37da2899SCharles.Forsyth }
112*37da2899SCharles.Forsyth
113*37da2899SCharles.Forsyth // free the residue
114*37da2899SCharles.Forsyth void
crtresfree(CRTres * res)115*37da2899SCharles.Forsyth crtresfree(CRTres *res)
116*37da2899SCharles.Forsyth {
117*37da2899SCharles.Forsyth int i;
118*37da2899SCharles.Forsyth
119*37da2899SCharles.Forsyth for(i = 0; i < res->n; i++)
120*37da2899SCharles.Forsyth mpfree(res->r[i]);
121*37da2899SCharles.Forsyth free(res);
122*37da2899SCharles.Forsyth }
123