|  | #include "os.h" | 
|  | #include <mp.h> | 
|  | #include <libsec.h> | 
|  |  | 
|  | /* NIST algorithm for generating DSA primes */ | 
|  | /* Menezes et al (1997) Handbook of Applied Cryptography, p.151 */ | 
|  | /* q is a 160-bit prime;  p is a 1024-bit prime;  q divides p-1 */ | 
|  |  | 
|  | /* arithmetic on unsigned ints mod 2**160, represented */ | 
|  | /*    as 20-byte, little-endian uchar array */ | 
|  |  | 
|  | static void | 
|  | Hrand(uchar *s) | 
|  | { | 
|  | uint32 *u = (uint32*)s; | 
|  | *u++ = fastrand(); | 
|  | *u++ = fastrand(); | 
|  | *u++ = fastrand(); | 
|  | *u++ = fastrand(); | 
|  | *u = fastrand(); | 
|  | } | 
|  |  | 
|  | static void | 
|  | Hincr(uchar *s) | 
|  | { | 
|  | int i; | 
|  | for(i=0; i<20; i++) | 
|  | if(++s[i]!=0) | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* this can run for quite a while;  be patient */ | 
|  | void | 
|  | DSAprimes(mpint *q, mpint *p, uchar seed[SHA1dlen]) | 
|  | { | 
|  | int i, j, k, n = 6, b = 63; | 
|  | uchar s[SHA1dlen], Hs[SHA1dlen], Hs1[SHA1dlen], sj[SHA1dlen], sjk[SHA1dlen]; | 
|  | mpint *two1023, *mb, *Vk, *W, *X, *q2; | 
|  |  | 
|  | two1023 = mpnew(1024); | 
|  | mpleft(mpone, 1023, two1023); | 
|  | mb = mpnew(0); | 
|  | mpleft(mpone, b, mb); | 
|  | W = mpnew(1024); | 
|  | Vk = mpnew(1024); | 
|  | X = mpnew(0); | 
|  | q2 = mpnew(0); | 
|  | forever: | 
|  | do{ | 
|  | Hrand(s); | 
|  | memcpy(sj, s, 20); | 
|  | sha1(s, 20, Hs, 0); | 
|  | Hincr(sj); | 
|  | sha1(sj, 20, Hs1, 0); | 
|  | for(i=0; i<20; i++) | 
|  | Hs[i] ^= Hs1[i]; | 
|  | Hs[0] |= 1; | 
|  | Hs[19] |= 0x80; | 
|  | letomp(Hs, 20, q); | 
|  | }while(!probably_prime(q, 18)); | 
|  | if(seed != nil)	/* allow skeptics to confirm computation */ | 
|  | memmove(seed, s, SHA1dlen); | 
|  | i = 0; | 
|  | j = 2; | 
|  | Hincr(sj); | 
|  | mpleft(q, 1, q2); | 
|  | while(i<4096){ | 
|  | memcpy(sjk, sj, 20); | 
|  | for(k=0; k <= n; k++){ | 
|  | sha1(sjk, 20, Hs, 0); | 
|  | letomp(Hs, 20, Vk); | 
|  | if(k == n) | 
|  | mpmod(Vk, mb, Vk); | 
|  | mpleft(Vk, 160*k, Vk); | 
|  | mpadd(W, Vk, W); | 
|  | Hincr(sjk); | 
|  | } | 
|  | mpadd(W, two1023, X); | 
|  | mpmod(X, q2, W); | 
|  | mpsub(W, mpone, W); | 
|  | mpsub(X, W, p); | 
|  | if(mpcmp(p, two1023)>=0 && probably_prime(p, 5)) | 
|  | goto done; | 
|  | i += 1; | 
|  | j += n+1; | 
|  | for(k=0; k<n+1; k++) | 
|  | Hincr(sj); | 
|  | } | 
|  | goto forever; | 
|  | done: | 
|  | mpfree(q2); | 
|  | mpfree(X); | 
|  | mpfree(Vk); | 
|  | mpfree(W); | 
|  | mpfree(mb); | 
|  | mpfree(two1023); | 
|  | } |