180ee5cbfSDavid du Colombier #include "os.h"
280ee5cbfSDavid du Colombier #include <mp.h>
380ee5cbfSDavid du Colombier #include <libsec.h>
480ee5cbfSDavid du Colombier
580ee5cbfSDavid du Colombier RSApriv*
rsagen(int nlen,int elen,int rounds)680ee5cbfSDavid du Colombier rsagen(int nlen, int elen, int rounds)
780ee5cbfSDavid du Colombier {
880ee5cbfSDavid du Colombier mpint *p, *q, *e, *d, *phi, *n, *t1, *t2, *kp, *kq, *c2;
980ee5cbfSDavid du Colombier RSApriv *rsa;
1080ee5cbfSDavid du Colombier
1180ee5cbfSDavid du Colombier p = mpnew(nlen/2);
1280ee5cbfSDavid du Colombier q = mpnew(nlen/2);
1380ee5cbfSDavid du Colombier n = mpnew(nlen);
1480ee5cbfSDavid du Colombier e = mpnew(elen);
1580ee5cbfSDavid du Colombier d = mpnew(0);
1680ee5cbfSDavid du Colombier phi = mpnew(nlen);
1780ee5cbfSDavid du Colombier
1880ee5cbfSDavid du Colombier // create the prime factors and euclid's function
19*51711cb6SDavid du Colombier genprime(p, nlen/2, rounds);
20*51711cb6SDavid du Colombier genprime(q, nlen - mpsignif(p) + 1, rounds);
2180ee5cbfSDavid du Colombier mpmul(p, q, n);
2280ee5cbfSDavid du Colombier mpsub(p, mpone, e);
2380ee5cbfSDavid du Colombier mpsub(q, mpone, d);
2480ee5cbfSDavid du Colombier mpmul(e, d, phi);
2580ee5cbfSDavid du Colombier
2680ee5cbfSDavid du Colombier // find an e relatively prime to phi
2780ee5cbfSDavid du Colombier t1 = mpnew(0);
2880ee5cbfSDavid du Colombier t2 = mpnew(0);
2939734e7eSDavid du Colombier mprand(elen, genrandom, e);
30*51711cb6SDavid du Colombier if(mpcmp(e,mptwo) <= 0)
31*51711cb6SDavid du Colombier itomp(3, e);
32*51711cb6SDavid du Colombier // See Menezes et al. p.291 "8.8 Note (selecting primes)" for discussion
33*51711cb6SDavid du Colombier // of the merits of various choices of primes and exponents. e=3 is a
34*51711cb6SDavid du Colombier // common and recommended exponent, but doesn't necessarily work here
35*51711cb6SDavid du Colombier // because we chose strong rather than safe primes.
3680ee5cbfSDavid du Colombier for(;;){
3739734e7eSDavid du Colombier mpextendedgcd(e, phi, t1, d, t2);
3839734e7eSDavid du Colombier if(mpcmp(t1, mpone) == 0)
3980ee5cbfSDavid du Colombier break;
4080ee5cbfSDavid du Colombier mpadd(mpone, e, e);
4180ee5cbfSDavid du Colombier }
4280ee5cbfSDavid du Colombier mpfree(t1);
4380ee5cbfSDavid du Colombier mpfree(t2);
4480ee5cbfSDavid du Colombier
4580ee5cbfSDavid du Colombier // compute chinese remainder coefficient
4680ee5cbfSDavid du Colombier c2 = mpnew(0);
4780ee5cbfSDavid du Colombier mpinvert(p, q, c2);
4880ee5cbfSDavid du Colombier
4980ee5cbfSDavid du Colombier // for crt a**k mod p == (a**(k mod p-1)) mod p
5080ee5cbfSDavid du Colombier kq = mpnew(0);
5180ee5cbfSDavid du Colombier kp = mpnew(0);
5280ee5cbfSDavid du Colombier mpsub(p, mpone, phi);
5380ee5cbfSDavid du Colombier mpmod(d, phi, kp);
5480ee5cbfSDavid du Colombier mpsub(q, mpone, phi);
5580ee5cbfSDavid du Colombier mpmod(d, phi, kq);
5680ee5cbfSDavid du Colombier
5780ee5cbfSDavid du Colombier rsa = rsaprivalloc();
5880ee5cbfSDavid du Colombier rsa->pub.ek = e;
5980ee5cbfSDavid du Colombier rsa->pub.n = n;
6080ee5cbfSDavid du Colombier rsa->dk = d;
6180ee5cbfSDavid du Colombier rsa->kp = kp;
6280ee5cbfSDavid du Colombier rsa->kq = kq;
6380ee5cbfSDavid du Colombier rsa->p = p;
6480ee5cbfSDavid du Colombier rsa->q = q;
6580ee5cbfSDavid du Colombier rsa->c2 = c2;
6680ee5cbfSDavid du Colombier
6780ee5cbfSDavid du Colombier mpfree(phi);
6880ee5cbfSDavid du Colombier
6980ee5cbfSDavid du Colombier return rsa;
7080ee5cbfSDavid du Colombier }
71