xref: /inferno-os/libsec/port/dsasign.c (revision 46439007cf417cbd9ac8049bb4122c890097a0fa)
1 #include "os.h"
2 #include <mp.h>
3 #include <libsec.h>
4 
5 DSAsig*
6 dsasign(DSApriv *priv, mpint *m)
7 {
8 	DSApub *pub = &priv->pub;
9 	DSAsig *sig;
10 	mpint *qm1, *k, *kinv, *r, *s;
11 	mpint *q = pub->q, *p = pub->p, *alpha = pub->alpha;
12 	int qlen = mpsignif(q);
13 
14 	qm1 = mpnew(0);
15 	kinv = mpnew(0);
16 	r = mpnew(0);
17 	s = mpnew(0);
18 	k = mpnew(0);
19 	mpsub(pub->q, mpone, qm1);
20 
21 	// find a k that has an inverse mod q
22 	while(1){
23 		mprand(qlen, genrandom, k);
24 		if((mpcmp(mpone, k) > 0) || (mpcmp(k, pub->q) >= 0))
25 			continue;
26 		mpextendedgcd(k, q, r, kinv, s);
27 		if(mpcmp(r, mpone) != 0)
28 			sysfatal("dsasign: pub->q not prime");
29 		break;
30 	}
31 
32   	// make kinv positive
33 	mpmod(kinv, pub->q, kinv);
34 
35 	// r = ((alpha**k) mod p) mod q
36 	mpexp(alpha, k, p, r);
37 	mpmod(r, q, r);
38 
39 	// s = (kinv*(m + ar)) mod q
40 	mpmul(r, priv->secret, s);
41 	mpadd(s, m, s);
42 	mpmul(s, kinv, s);
43 	mpmod(s, q, s);
44 
45 	sig = dsasigalloc();
46 	sig->r = r;
47 	sig->s = s;
48 	mpfree(qm1);
49 	mpfree(k);
50 	mpfree(kinv);
51 	return sig;
52 }
53