xref: /plan9/sys/src/libmp/port/crt.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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