diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | Makefile.in | 8 | ||||
-rw-r--r-- | moduli.c | 617 | ||||
-rw-r--r-- | moduli.h | 23 |
4 files changed, 648 insertions, 3 deletions
@@ -25,6 +25,7 @@ | |||
25 | (copied from OpenBSD an re-applied portable changes) | 25 | (copied from OpenBSD an re-applied portable changes) |
26 | - (dtucker) [openbsd-compat/bsd-misc.c openbsd-compat/bsd-misc.h] | 26 | - (dtucker) [openbsd-compat/bsd-misc.c openbsd-compat/bsd-misc.h] |
27 | Add a tcgetpgrp function. | 27 | Add a tcgetpgrp function. |
28 | - (dtucker) [Makefile.in moduli.c moduli.h] Add new files and to Makefile. | ||
28 | 29 | ||
29 | 20030730 | 30 | 20030730 |
30 | - (djm) [auth-pam.c] Don't use crappy APIs like sprintf. Thanks bal | 31 | - (djm) [auth-pam.c] Don't use crappy APIs like sprintf. Thanks bal |
@@ -763,4 +764,4 @@ | |||
763 | - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo. | 764 | - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo. |
764 | Report from murple@murple.net, diagnosis from dtucker@zip.com.au | 765 | Report from murple@murple.net, diagnosis from dtucker@zip.com.au |
765 | 766 | ||
766 | $Id: ChangeLog,v 1.2873 2003/08/02 13:31:42 dtucker Exp $ | 767 | $Id: ChangeLog,v 1.2874 2003/08/02 13:51:38 dtucker Exp $ |
diff --git a/Makefile.in b/Makefile.in index c5674c735..cffefece6 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: Makefile.in,v 1.239 2003/08/02 12:24:49 dtucker Exp $ | 1 | # $Id: Makefile.in,v 1.240 2003/08/02 13:51:38 dtucker Exp $ |
2 | 2 | ||
3 | # uncomment if you run a non bourne compatable shell. Ie. csh | 3 | # uncomment if you run a non bourne compatable shell. Ie. csh |
4 | #SHELL = @SH@ | 4 | #SHELL = @SH@ |
@@ -63,7 +63,7 @@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keys | |||
63 | LIBSSH_OBJS=authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o \ | 63 | LIBSSH_OBJS=authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o \ |
64 | cipher.o cipher-aes.o cipher-bf1.o cipher-ctr.o cipher-3des1.o \ | 64 | cipher.o cipher-aes.o cipher-bf1.o cipher-ctr.o cipher-3des1.o \ |
65 | compat.o compress.o crc32.o deattack.o fatal.o \ | 65 | compat.o compress.o crc32.o deattack.o fatal.o \ |
66 | hostfile.o log.o match.o mpaux.o nchan.o packet.o \ | 66 | hostfile.o log.o match.o moduli.o mpaux.o nchan.o packet.o \ |
67 | readpass.o rsa.o tildexpand.o ttymodes.o xmalloc.o atomicio.o \ | 67 | readpass.o rsa.o tildexpand.o ttymodes.o xmalloc.o atomicio.o \ |
68 | key.o dispatch.o kex.o mac.o uuencode.o misc.o \ | 68 | key.o dispatch.o kex.o mac.o uuencode.o misc.o \ |
69 | rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o kexgex.o \ | 69 | rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o kexgex.o \ |
@@ -186,6 +186,10 @@ ssh_prng_cmds.out: ssh_prng_cmds | |||
186 | $(PERL) $(srcdir)/fixprogs ssh_prng_cmds $(ENT); \ | 186 | $(PERL) $(srcdir)/fixprogs ssh_prng_cmds $(ENT); \ |
187 | fi | 187 | fi |
188 | 188 | ||
189 | # fake rule to stop make trying to compile moduli.o into a binary "modulo" | ||
190 | moduli: | ||
191 | echo | ||
192 | |||
189 | clean: | 193 | clean: |
190 | rm -f *.o *.a $(TARGETS) logintest config.cache config.log | 194 | rm -f *.o *.a $(TARGETS) logintest config.cache config.log |
191 | rm -f *.out core | 195 | rm -f *.out core |
diff --git a/moduli.c b/moduli.c new file mode 100644 index 000000000..eb2c0fd18 --- /dev/null +++ b/moduli.c | |||
@@ -0,0 +1,617 @@ | |||
1 | /* $OpenBSD: moduli.c,v 1.1 2003/07/28 09:49:56 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright 1994 Phil Karn <karn@qualcomm.com> | ||
4 | * Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com> | ||
5 | * Copyright 2000 Niels Provos <provos@citi.umich.edu> | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * Two-step process to generate safe primes for DHGEX | ||
31 | * | ||
32 | * Sieve candidates for "safe" primes, | ||
33 | * suitable for use as Diffie-Hellman moduli; | ||
34 | * that is, where q = (p-1)/2 is also prime. | ||
35 | * | ||
36 | * First step: generate candidate primes (memory intensive) | ||
37 | * Second step: test primes' safety (processor intensive) | ||
38 | */ | ||
39 | |||
40 | #include "includes.h" | ||
41 | #include "moduli.h" | ||
42 | #include "xmalloc.h" | ||
43 | #include "log.h" | ||
44 | |||
45 | #include <openssl/bn.h> | ||
46 | |||
47 | |||
48 | /* | ||
49 | * Debugging defines | ||
50 | */ | ||
51 | |||
52 | /* define DEBUG_LARGE 1 */ | ||
53 | /* define DEBUG_SMALL 1 */ | ||
54 | /* define DEBUG_TEST 1 */ | ||
55 | |||
56 | /* | ||
57 | * File output defines | ||
58 | */ | ||
59 | |||
60 | /* need line long enough for largest moduli plus headers */ | ||
61 | #define QLINESIZE (100+8192) | ||
62 | |||
63 | /* Type: decimal. | ||
64 | * Specifies the internal structure of the prime modulus. | ||
65 | */ | ||
66 | #define QTYPE_UNKNOWN (0) | ||
67 | #define QTYPE_UNSTRUCTURED (1) | ||
68 | #define QTYPE_SAFE (2) | ||
69 | #define QTYPE_SCHNOOR (3) | ||
70 | #define QTYPE_SOPHIE_GERMAINE (4) | ||
71 | #define QTYPE_STRONG (5) | ||
72 | |||
73 | /* Tests: decimal (bit field). | ||
74 | * Specifies the methods used in checking for primality. | ||
75 | * Usually, more than one test is used. | ||
76 | */ | ||
77 | #define QTEST_UNTESTED (0x00) | ||
78 | #define QTEST_COMPOSITE (0x01) | ||
79 | #define QTEST_SIEVE (0x02) | ||
80 | #define QTEST_MILLER_RABIN (0x04) | ||
81 | #define QTEST_JACOBI (0x08) | ||
82 | #define QTEST_ELLIPTIC (0x10) | ||
83 | |||
84 | /* Size: decimal. | ||
85 | * Specifies the number of the most significant bit (0 to M). | ||
86 | ** WARNING: internally, usually 1 to N. | ||
87 | */ | ||
88 | #define QSIZE_MINIMUM (511) | ||
89 | |||
90 | /* | ||
91 | * Prime sieving defines | ||
92 | */ | ||
93 | |||
94 | /* Constant: assuming 8 bit bytes and 32 bit words */ | ||
95 | #define SHIFT_BIT (3) | ||
96 | #define SHIFT_BYTE (2) | ||
97 | #define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE) | ||
98 | #define SHIFT_MEGABYTE (20) | ||
99 | #define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE) | ||
100 | |||
101 | /* | ||
102 | * Constant: when used with 32-bit integers, the largest sieve prime | ||
103 | * has to be less than 2**32. | ||
104 | */ | ||
105 | #define SMALL_MAXIMUM (0xffffffffUL) | ||
106 | |||
107 | /* Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1. */ | ||
108 | #define TINY_NUMBER (1UL<<16) | ||
109 | |||
110 | /* Ensure enough bit space for testing 2*q. */ | ||
111 | #define TEST_MAXIMUM (1UL<<16) | ||
112 | #define TEST_MINIMUM (QSIZE_MINIMUM + 1) | ||
113 | /* real TEST_MINIMUM (1UL << (SHIFT_WORD - TEST_POWER)) */ | ||
114 | #define TEST_POWER (3) /* 2**n, n < SHIFT_WORD */ | ||
115 | |||
116 | /* bit operations on 32-bit words */ | ||
117 | #define BIT_CLEAR(a,n) ((a)[(n)>>SHIFT_WORD] &= ~(1L << ((n) & 31))) | ||
118 | #define BIT_SET(a,n) ((a)[(n)>>SHIFT_WORD] |= (1L << ((n) & 31))) | ||
119 | #define BIT_TEST(a,n) ((a)[(n)>>SHIFT_WORD] & (1L << ((n) & 31))) | ||
120 | |||
121 | /* | ||
122 | * Prime testing defines | ||
123 | */ | ||
124 | |||
125 | /* | ||
126 | * Sieving data (XXX - move to struct) | ||
127 | */ | ||
128 | |||
129 | /* sieve 2**16 */ | ||
130 | static u_int32_t *TinySieve, tinybits; | ||
131 | |||
132 | /* sieve 2**30 in 2**16 parts */ | ||
133 | static u_int32_t *SmallSieve, smallbits, smallbase; | ||
134 | |||
135 | /* sieve relative to the initial value */ | ||
136 | static u_int32_t *LargeSieve, largewords, largetries, largenumbers; | ||
137 | static u_int32_t largebits, largememory; /* megabytes */ | ||
138 | static BIGNUM *largebase; | ||
139 | |||
140 | |||
141 | /* | ||
142 | * print moduli out in consistent form, | ||
143 | */ | ||
144 | static int | ||
145 | qfileout(FILE * ofile, u_int32_t otype, u_int32_t otests, u_int32_t otries, | ||
146 | u_int32_t osize, u_int32_t ogenerator, BIGNUM * omodulus) | ||
147 | { | ||
148 | struct tm *gtm; | ||
149 | time_t time_now; | ||
150 | int res; | ||
151 | |||
152 | time(&time_now); | ||
153 | gtm = gmtime(&time_now); | ||
154 | |||
155 | res = fprintf(ofile, "%04d%02d%02d%02d%02d%02d %u %u %u %u %x ", | ||
156 | gtm->tm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday, | ||
157 | gtm->tm_hour, gtm->tm_min, gtm->tm_sec, | ||
158 | otype, otests, otries, osize, ogenerator); | ||
159 | |||
160 | if (res < 0) | ||
161 | return (-1); | ||
162 | |||
163 | if (BN_print_fp(ofile, omodulus) < 1) | ||
164 | return (-1); | ||
165 | |||
166 | res = fprintf(ofile, "\n"); | ||
167 | fflush(ofile); | ||
168 | |||
169 | return (res > 0 ? 0 : -1); | ||
170 | } | ||
171 | |||
172 | |||
173 | /* | ||
174 | ** Sieve p's and q's with small factors | ||
175 | */ | ||
176 | static void | ||
177 | sieve_large(u_int32_t s) | ||
178 | { | ||
179 | u_int32_t r, u; | ||
180 | |||
181 | debug2("sieve_large %u", s); | ||
182 | largetries++; | ||
183 | /* r = largebase mod s */ | ||
184 | r = BN_mod_word(largebase, s); | ||
185 | if (r == 0) | ||
186 | u = 0; /* s divides into largebase exactly */ | ||
187 | else | ||
188 | u = s - r; /* largebase+u is first entry divisible by s */ | ||
189 | |||
190 | if (u < largebits * 2) { | ||
191 | /* | ||
192 | * The sieve omits p's and q's divisible by 2, so ensure that | ||
193 | * largebase+u is odd. Then, step through the sieve in | ||
194 | * increments of 2*s | ||
195 | */ | ||
196 | if (u & 0x1) | ||
197 | u += s; /* Make largebase+u odd, and u even */ | ||
198 | |||
199 | /* Mark all multiples of 2*s */ | ||
200 | for (u /= 2; u < largebits; u += s) | ||
201 | BIT_SET(LargeSieve, u); | ||
202 | } | ||
203 | |||
204 | /* r = p mod s */ | ||
205 | r = (2 * r + 1) % s; | ||
206 | if (r == 0) | ||
207 | u = 0; /* s divides p exactly */ | ||
208 | else | ||
209 | u = s - r; /* p+u is first entry divisible by s */ | ||
210 | |||
211 | if (u < largebits * 4) { | ||
212 | /* | ||
213 | * The sieve omits p's divisible by 4, so ensure that | ||
214 | * largebase+u is not. Then, step through the sieve in | ||
215 | * increments of 4*s | ||
216 | */ | ||
217 | while (u & 0x3) { | ||
218 | if (SMALL_MAXIMUM - u < s) | ||
219 | return; | ||
220 | u += s; | ||
221 | } | ||
222 | |||
223 | /* Mark all multiples of 4*s */ | ||
224 | for (u /= 4; u < largebits; u += s) | ||
225 | BIT_SET(LargeSieve, u); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * list candidates for Sophie-Germaine primes (where q = (p-1)/2) | ||
231 | * to standard output. | ||
232 | * The list is checked against small known primes (less than 2**30). | ||
233 | */ | ||
234 | int | ||
235 | gen_candidates(FILE *out, int memory, int power, BIGNUM *start) | ||
236 | { | ||
237 | BIGNUM *q; | ||
238 | u_int32_t j, r, s, t; | ||
239 | u_int32_t smallwords = TINY_NUMBER >> 6; | ||
240 | u_int32_t tinywords = TINY_NUMBER >> 6; | ||
241 | time_t time_start, time_stop; | ||
242 | int i, ret = 0; | ||
243 | |||
244 | largememory = memory; | ||
245 | |||
246 | /* | ||
247 | * Set power to the length in bits of the prime to be generated. | ||
248 | * This is changed to 1 less than the desired safe prime moduli p. | ||
249 | */ | ||
250 | if (power > TEST_MAXIMUM) { | ||
251 | error("Too many bits: %u > %lu", power, TEST_MAXIMUM); | ||
252 | return (-1); | ||
253 | } else if (power < TEST_MINIMUM) { | ||
254 | error("Too few bits: %u < %u", power, TEST_MINIMUM); | ||
255 | return (-1); | ||
256 | } | ||
257 | power--; /* decrement before squaring */ | ||
258 | |||
259 | /* | ||
260 | * The density of ordinary primes is on the order of 1/bits, so the | ||
261 | * density of safe primes should be about (1/bits)**2. Set test range | ||
262 | * to something well above bits**2 to be reasonably sure (but not | ||
263 | * guaranteed) of catching at least one safe prime. | ||
264 | */ | ||
265 | largewords = ((power * power) >> (SHIFT_WORD - TEST_POWER)); | ||
266 | |||
267 | /* | ||
268 | * Need idea of how much memory is available. We don't have to use all | ||
269 | * of it. | ||
270 | */ | ||
271 | if (largememory > LARGE_MAXIMUM) { | ||
272 | logit("Limited memory: %u MB; limit %lu MB", | ||
273 | largememory, LARGE_MAXIMUM); | ||
274 | largememory = LARGE_MAXIMUM; | ||
275 | } | ||
276 | |||
277 | if (largewords <= (largememory << SHIFT_MEGAWORD)) { | ||
278 | logit("Increased memory: %u MB; need %u bytes", | ||
279 | largememory, (largewords << SHIFT_BYTE)); | ||
280 | largewords = (largememory << SHIFT_MEGAWORD); | ||
281 | } else if (largememory > 0) { | ||
282 | logit("Decreased memory: %u MB; want %u bytes", | ||
283 | largememory, (largewords << SHIFT_BYTE)); | ||
284 | largewords = (largememory << SHIFT_MEGAWORD); | ||
285 | } | ||
286 | |||
287 | TinySieve = calloc(tinywords, sizeof(u_int32_t)); | ||
288 | if (TinySieve == NULL) { | ||
289 | error("Insufficient memory for tiny sieve: need %u bytes", | ||
290 | tinywords << SHIFT_BYTE); | ||
291 | exit(1); | ||
292 | } | ||
293 | tinybits = tinywords << SHIFT_WORD; | ||
294 | |||
295 | SmallSieve = calloc(smallwords, sizeof(u_int32_t)); | ||
296 | if (SmallSieve == NULL) { | ||
297 | error("Insufficient memory for small sieve: need %u bytes", | ||
298 | smallwords << SHIFT_BYTE); | ||
299 | xfree(TinySieve); | ||
300 | exit(1); | ||
301 | } | ||
302 | smallbits = smallwords << SHIFT_WORD; | ||
303 | |||
304 | /* | ||
305 | * dynamically determine available memory | ||
306 | */ | ||
307 | while ((LargeSieve = calloc(largewords, sizeof(u_int32_t))) == NULL) | ||
308 | largewords -= (1L << (SHIFT_MEGAWORD - 2)); /* 1/4 MB chunks */ | ||
309 | |||
310 | largebits = largewords << SHIFT_WORD; | ||
311 | largenumbers = largebits * 2; /* even numbers excluded */ | ||
312 | |||
313 | /* validation check: count the number of primes tried */ | ||
314 | largetries = 0; | ||
315 | q = BN_new(); | ||
316 | |||
317 | /* | ||
318 | * Generate random starting point for subprime search, or use | ||
319 | * specified parameter. | ||
320 | */ | ||
321 | largebase = BN_new(); | ||
322 | if (start == NULL) | ||
323 | BN_rand(largebase, power, 1, 1); | ||
324 | else | ||
325 | BN_copy(largebase, start); | ||
326 | |||
327 | /* ensure odd */ | ||
328 | BN_set_bit(largebase, 0); | ||
329 | |||
330 | time(&time_start); | ||
331 | |||
332 | logit("%.24s Sieve next %u plus %u-bit", ctime(&time_start), | ||
333 | largenumbers, power); | ||
334 | debug2("start point: 0x%s", BN_bn2hex(largebase)); | ||
335 | |||
336 | /* | ||
337 | * TinySieve | ||
338 | */ | ||
339 | for (i = 0; i < tinybits; i++) { | ||
340 | if (BIT_TEST(TinySieve, i)) | ||
341 | continue; /* 2*i+3 is composite */ | ||
342 | |||
343 | /* The next tiny prime */ | ||
344 | t = 2 * i + 3; | ||
345 | |||
346 | /* Mark all multiples of t */ | ||
347 | for (j = i + t; j < tinybits; j += t) | ||
348 | BIT_SET(TinySieve, j); | ||
349 | |||
350 | sieve_large(t); | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | * Start the small block search at the next possible prime. To avoid | ||
355 | * fencepost errors, the last pass is skipped. | ||
356 | */ | ||
357 | for (smallbase = TINY_NUMBER + 3; | ||
358 | smallbase < (SMALL_MAXIMUM - TINY_NUMBER); | ||
359 | smallbase += TINY_NUMBER) { | ||
360 | for (i = 0; i < tinybits; i++) { | ||
361 | if (BIT_TEST(TinySieve, i)) | ||
362 | continue; /* 2*i+3 is composite */ | ||
363 | |||
364 | /* The next tiny prime */ | ||
365 | t = 2 * i + 3; | ||
366 | r = smallbase % t; | ||
367 | |||
368 | if (r == 0) { | ||
369 | s = 0; /* t divides into smallbase exactly */ | ||
370 | } else { | ||
371 | /* smallbase+s is first entry divisible by t */ | ||
372 | s = t - r; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * The sieve omits even numbers, so ensure that | ||
377 | * smallbase+s is odd. Then, step through the sieve | ||
378 | * in increments of 2*t | ||
379 | */ | ||
380 | if (s & 1) | ||
381 | s += t; /* Make smallbase+s odd, and s even */ | ||
382 | |||
383 | /* Mark all multiples of 2*t */ | ||
384 | for (s /= 2; s < smallbits; s += t) | ||
385 | BIT_SET(SmallSieve, s); | ||
386 | } | ||
387 | |||
388 | /* | ||
389 | * SmallSieve | ||
390 | */ | ||
391 | for (i = 0; i < smallbits; i++) { | ||
392 | if (BIT_TEST(SmallSieve, i)) | ||
393 | continue; /* 2*i+smallbase is composite */ | ||
394 | |||
395 | /* The next small prime */ | ||
396 | sieve_large((2 * i) + smallbase); | ||
397 | } | ||
398 | |||
399 | memset(SmallSieve, 0, smallwords << SHIFT_BYTE); | ||
400 | } | ||
401 | |||
402 | time(&time_stop); | ||
403 | |||
404 | logit("%.24s Sieved with %u small primes in %ld seconds", | ||
405 | ctime(&time_stop), largetries, (long) (time_stop - time_start)); | ||
406 | |||
407 | for (j = r = 0; j < largebits; j++) { | ||
408 | if (BIT_TEST(LargeSieve, j)) | ||
409 | continue; /* Definitely composite, skip */ | ||
410 | |||
411 | debug2("test q = largebase+%u", 2 * j); | ||
412 | BN_set_word(q, 2 * j); | ||
413 | BN_add(q, q, largebase); | ||
414 | if (qfileout(out, QTYPE_SOPHIE_GERMAINE, QTEST_SIEVE, | ||
415 | largetries, (power - 1) /* MSB */, (0), q) == -1) { | ||
416 | ret = -1; | ||
417 | break; | ||
418 | } | ||
419 | |||
420 | r++; /* count q */ | ||
421 | } | ||
422 | |||
423 | time(&time_stop); | ||
424 | |||
425 | xfree(LargeSieve); | ||
426 | xfree(SmallSieve); | ||
427 | xfree(TinySieve); | ||
428 | |||
429 | logit("%.24s Found %u candidates", ctime(&time_stop), r); | ||
430 | |||
431 | return (ret); | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * perform a Miller-Rabin primality test | ||
436 | * on the list of candidates | ||
437 | * (checking both q and p) | ||
438 | * The result is a list of so-call "safe" primes | ||
439 | */ | ||
440 | int | ||
441 | prime_test(FILE *in, FILE *out, u_int32_t trials, | ||
442 | u_int32_t generator_wanted) | ||
443 | { | ||
444 | BIGNUM *q, *p, *a; | ||
445 | BN_CTX *ctx; | ||
446 | char *cp, *lp; | ||
447 | u_int32_t count_in = 0, count_out = 0, count_possible = 0; | ||
448 | u_int32_t generator_known, in_tests, in_tries, in_type, in_size; | ||
449 | time_t time_start, time_stop; | ||
450 | int res; | ||
451 | |||
452 | time(&time_start); | ||
453 | |||
454 | p = BN_new(); | ||
455 | q = BN_new(); | ||
456 | ctx = BN_CTX_new(); | ||
457 | |||
458 | debug2("%.24s Final %u Miller-Rabin trials (%x generator)", | ||
459 | ctime(&time_start), trials, generator_wanted); | ||
460 | |||
461 | res = 0; | ||
462 | lp = xmalloc(QLINESIZE + 1); | ||
463 | while (fgets(lp, QLINESIZE, in) != NULL) { | ||
464 | int ll = strlen(lp); | ||
465 | |||
466 | count_in++; | ||
467 | if (ll < 14 || *lp == '!' || *lp == '#') { | ||
468 | debug2("%10u: comment or short line", count_in); | ||
469 | continue; | ||
470 | } | ||
471 | |||
472 | /* XXX - fragile parser */ | ||
473 | /* time */ | ||
474 | cp = &lp[14]; /* (skip) */ | ||
475 | |||
476 | /* type */ | ||
477 | in_type = strtoul(cp, &cp, 10); | ||
478 | |||
479 | /* tests */ | ||
480 | in_tests = strtoul(cp, &cp, 10); | ||
481 | |||
482 | if (in_tests & QTEST_COMPOSITE) { | ||
483 | debug2("%10u: known composite", count_in); | ||
484 | continue; | ||
485 | } | ||
486 | /* tries */ | ||
487 | in_tries = strtoul(cp, &cp, 10); | ||
488 | |||
489 | /* size (most significant bit) */ | ||
490 | in_size = strtoul(cp, &cp, 10); | ||
491 | |||
492 | /* generator (hex) */ | ||
493 | generator_known = strtoul(cp, &cp, 16); | ||
494 | |||
495 | /* Skip white space */ | ||
496 | cp += strspn(cp, " "); | ||
497 | |||
498 | /* modulus (hex) */ | ||
499 | switch (in_type) { | ||
500 | case QTYPE_SOPHIE_GERMAINE: | ||
501 | debug2("%10u: (%u) Sophie-Germaine", count_in, in_type); | ||
502 | a = q; | ||
503 | BN_hex2bn(&a, cp); | ||
504 | /* p = 2*q + 1 */ | ||
505 | BN_lshift(p, q, 1); | ||
506 | BN_add_word(p, 1); | ||
507 | in_size += 1; | ||
508 | generator_known = 0; | ||
509 | break; | ||
510 | default: | ||
511 | debug2("%10u: (%u)", count_in, in_type); | ||
512 | a = p; | ||
513 | BN_hex2bn(&a, cp); | ||
514 | /* q = (p-1) / 2 */ | ||
515 | BN_rshift(q, p, 1); | ||
516 | break; | ||
517 | } | ||
518 | |||
519 | /* | ||
520 | * due to earlier inconsistencies in interpretation, check | ||
521 | * the proposed bit size. | ||
522 | */ | ||
523 | if (BN_num_bits(p) != (in_size + 1)) { | ||
524 | debug2("%10u: bit size %u mismatch", count_in, in_size); | ||
525 | continue; | ||
526 | } | ||
527 | if (in_size < QSIZE_MINIMUM) { | ||
528 | debug2("%10u: bit size %u too short", count_in, in_size); | ||
529 | continue; | ||
530 | } | ||
531 | |||
532 | if (in_tests & QTEST_MILLER_RABIN) | ||
533 | in_tries += trials; | ||
534 | else | ||
535 | in_tries = trials; | ||
536 | /* | ||
537 | * guess unknown generator | ||
538 | */ | ||
539 | if (generator_known == 0) { | ||
540 | if (BN_mod_word(p, 24) == 11) | ||
541 | generator_known = 2; | ||
542 | else if (BN_mod_word(p, 12) == 5) | ||
543 | generator_known = 3; | ||
544 | else { | ||
545 | u_int32_t r = BN_mod_word(p, 10); | ||
546 | |||
547 | if (r == 3 || r == 7) { | ||
548 | generator_known = 5; | ||
549 | } | ||
550 | } | ||
551 | } | ||
552 | /* | ||
553 | * skip tests when desired generator doesn't match | ||
554 | */ | ||
555 | if (generator_wanted > 0 && | ||
556 | generator_wanted != generator_known) { | ||
557 | debug2("%10u: generator %d != %d", | ||
558 | count_in, generator_known, generator_wanted); | ||
559 | continue; | ||
560 | } | ||
561 | |||
562 | count_possible++; | ||
563 | |||
564 | /* | ||
565 | * The (1/4)^N performance bound on Miller-Rabin is | ||
566 | * extremely pessimistic, so don't spend a lot of time | ||
567 | * really verifying that q is prime until after we know | ||
568 | * that p is also prime. A single pass will weed out the | ||
569 | * vast majority of composite q's. | ||
570 | */ | ||
571 | if (BN_is_prime(q, 1, NULL, ctx, NULL) <= 0) { | ||
572 | debug2("%10u: q failed first possible prime test", | ||
573 | count_in); | ||
574 | continue; | ||
575 | } | ||
576 | |||
577 | /* | ||
578 | * q is possibly prime, so go ahead and really make sure | ||
579 | * that p is prime. If it is, then we can go back and do | ||
580 | * the same for q. If p is composite, chances are that | ||
581 | * will show up on the first Rabin-Miller iteration so it | ||
582 | * doesn't hurt to specify a high iteration count. | ||
583 | */ | ||
584 | if (!BN_is_prime(p, trials, NULL, ctx, NULL)) { | ||
585 | debug2("%10u: p is not prime", count_in); | ||
586 | continue; | ||
587 | } | ||
588 | debug("%10u: p is almost certainly prime", count_in); | ||
589 | |||
590 | /* recheck q more rigorously */ | ||
591 | if (!BN_is_prime(q, trials - 1, NULL, ctx, NULL)) { | ||
592 | debug("%10u: q is not prime", count_in); | ||
593 | continue; | ||
594 | } | ||
595 | debug("%10u: q is almost certainly prime", count_in); | ||
596 | |||
597 | if (qfileout(out, QTYPE_SAFE, (in_tests | QTEST_MILLER_RABIN), | ||
598 | in_tries, in_size, generator_known, p)) { | ||
599 | res = -1; | ||
600 | break; | ||
601 | } | ||
602 | |||
603 | count_out++; | ||
604 | } | ||
605 | |||
606 | time(&time_stop); | ||
607 | xfree(lp); | ||
608 | BN_free(p); | ||
609 | BN_free(q); | ||
610 | BN_CTX_free(ctx); | ||
611 | |||
612 | logit("%.24s Found %u safe primes of %u candidates in %ld seconds", | ||
613 | ctime(&time_stop), count_out, count_possible, | ||
614 | (long) (time_stop - time_start)); | ||
615 | |||
616 | return (res); | ||
617 | } | ||
diff --git a/moduli.h b/moduli.h new file mode 100644 index 000000000..9cd1cd3f8 --- /dev/null +++ b/moduli.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* $OpenBSD: moduli.h,v 1.1 2003/07/28 09:49:56 djm Exp $ */ | ||
2 | |||
3 | #include <sys/types.h> | ||
4 | #include <openssl/bn.h> | ||
5 | |||
6 | /* | ||
7 | * Using virtual memory can cause thrashing. This should be the largest | ||
8 | * number that is supported without a large amount of disk activity -- | ||
9 | * that would increase the run time from hours to days or weeks! | ||
10 | */ | ||
11 | #define LARGE_MINIMUM (8UL) /* megabytes */ | ||
12 | |||
13 | /* | ||
14 | * Do not increase this number beyond the unsigned integer bit size. | ||
15 | * Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits). | ||
16 | */ | ||
17 | #define LARGE_MAXIMUM (127UL) /* megabytes */ | ||
18 | |||
19 | /* Minimum number of primality tests to perform */ | ||
20 | #define TRIAL_MINIMUM (4) | ||
21 | |||
22 | int gen_candidates(FILE *, int, int, BIGNUM *); | ||
23 | int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); | ||