qsieve.c revision 1.4 1 1.4 andvar /* $NetBSD: qsieve.c,v 1.4 2025/02/17 22:58:34 andvar Exp $ */
2 1.1 elad
3 1.1 elad /*-
4 1.1 elad * Copyright 1994 Phil Karn <karn (at) qualcomm.com>
5 1.1 elad * Copyright 1996-1998, 2003 William Allen Simpson <wsimpson (at) greendragon.com>
6 1.1 elad * Copyright 2000 Niels Provos <provos (at) citi.umich.edu>
7 1.1 elad * All rights reserved.
8 1.1 elad *
9 1.1 elad * Redistribution and use in source and binary forms, with or without
10 1.1 elad * modification, are permitted provided that the following conditions
11 1.1 elad * are met:
12 1.1 elad * 1. Redistributions of source code must retain the above copyright
13 1.1 elad * notice, this list of conditions and the following disclaimer.
14 1.1 elad * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 elad * notice, this list of conditions and the following disclaimer in the
16 1.1 elad * documentation and/or other materials provided with the distribution.
17 1.1 elad *
18 1.1 elad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.1 elad * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.1 elad * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.1 elad * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.1 elad * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 1.1 elad * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.1 elad * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.1 elad * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.1 elad * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 1.1 elad * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 elad */
29 1.1 elad
30 1.1 elad /*
31 1.1 elad * Sieve candidates for "safe" primes,
32 1.1 elad * suitable for use as Diffie-Hellman moduli;
33 1.1 elad * that is, where q = (p-1)/2 is also prime.
34 1.1 elad *
35 1.1 elad * This is the first of two steps.
36 1.1 elad * This step is memory intensive.
37 1.1 elad *
38 1.1 elad * 1996 May William Allen Simpson
39 1.1 elad * extracted from earlier code by Phil Karn, April 1994.
40 1.1 elad * save large primes list for later processing.
41 1.1 elad * 1998 May William Allen Simpson
42 1.1 elad * parameterized.
43 1.1 elad * 2000 Dec Niels Provos
44 1.1 elad * convert from GMP to openssl BN.
45 1.1 elad * 2003 Jun William Allen Simpson
46 1.1 elad * change outfile definition slightly to match openssh mistake.
47 1.1 elad * move common file i/o to own file for better documentation.
48 1.1 elad * redo memory again.
49 1.1 elad */
50 1.1 elad
51 1.1 elad #include <stdio.h>
52 1.1 elad #include <stdlib.h>
53 1.1 elad #include <time.h>
54 1.1 elad #include <openssl/bn.h>
55 1.1 elad #include <string.h>
56 1.1 elad #include <err.h>
57 1.1 elad #include "qfile.h"
58 1.1 elad
59 1.1 elad /* define DEBUG_LARGE 1 */
60 1.1 elad /* define DEBUG_SMALL 1 */
61 1.1 elad
62 1.1 elad /*
63 1.1 elad * Using virtual memory can cause thrashing. This should be the largest
64 1.1 elad * number that is supported without a large amount of disk activity --
65 1.1 elad * that would increase the run time from hours to days or weeks!
66 1.1 elad */
67 1.1 elad #define LARGE_MINIMUM (8UL) /* megabytes */
68 1.1 elad
69 1.1 elad /*
70 1.1 elad * Do not increase this number beyond the unsigned integer bit size.
71 1.1 elad * Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits).
72 1.1 elad */
73 1.1 elad #define LARGE_MAXIMUM (127UL) /* megabytes */
74 1.1 elad
75 1.1 elad /*
76 1.1 elad * Constant: assuming 8 bit bytes and 32 bit words
77 1.1 elad */
78 1.1 elad #define SHIFT_BIT (3)
79 1.1 elad #define SHIFT_BYTE (2)
80 1.1 elad #define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE)
81 1.1 elad #define SHIFT_MEGABYTE (20)
82 1.1 elad #define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE)
83 1.1 elad
84 1.1 elad /*
85 1.1 elad * Constant: when used with 32-bit integers, the largest sieve prime
86 1.1 elad * has to be less than 2**32.
87 1.1 elad */
88 1.1 elad #define SMALL_MAXIMUM (0xffffffffUL)
89 1.1 elad
90 1.1 elad /*
91 1.1 elad * Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1.
92 1.1 elad */
93 1.1 elad #define TINY_NUMBER (1UL<<16)
94 1.1 elad
95 1.1 elad /*
96 1.1 elad * Ensure enough bit space for testing 2*q.
97 1.1 elad */
98 1.1 elad #define TEST_MAXIMUM (1UL<<16)
99 1.1 elad #define TEST_MINIMUM (QSIZE_MINIMUM + 1)
100 1.1 elad /* real TEST_MINIMUM (1UL << (SHIFT_WORD - TEST_POWER)) */
101 1.1 elad #define TEST_POWER (3) /* 2**n, n < SHIFT_WORD */
102 1.1 elad
103 1.1 elad /*
104 1.1 elad * bit operations on 32-bit words
105 1.1 elad */
106 1.1 elad #define BIT_CLEAR(a,n) ((a)[(n)>>SHIFT_WORD] &= ~(1U << ((n) & 31)))
107 1.1 elad #define BIT_SET(a,n) ((a)[(n)>>SHIFT_WORD] |= (1U << ((n) & 31)))
108 1.1 elad #define BIT_TEST(a,n) ((a)[(n)>>SHIFT_WORD] & (1U << ((n) & 31)))
109 1.1 elad
110 1.1 elad /*
111 1.1 elad * sieve relative to the initial value
112 1.1 elad */
113 1.3 joerg static uint32_t *LargeSieve;
114 1.3 joerg static uint32_t largewords;
115 1.3 joerg static uint32_t largetries;
116 1.3 joerg static uint32_t largenumbers;
117 1.3 joerg static uint32_t largememory; /* megabytes */
118 1.3 joerg static uint32_t largebits;
119 1.3 joerg static BIGNUM *largebase;
120 1.1 elad
121 1.1 elad /*
122 1.1 elad * sieve 2**30 in 2**16 parts
123 1.1 elad */
124 1.3 joerg static uint32_t *SmallSieve;
125 1.3 joerg static uint32_t smallbits;
126 1.3 joerg static uint32_t smallbase;
127 1.1 elad
128 1.1 elad /*
129 1.1 elad * sieve 2**16
130 1.1 elad */
131 1.3 joerg static uint32_t *TinySieve;
132 1.3 joerg static uint32_t tinybits;
133 1.1 elad
134 1.3 joerg __dead static void usage(void);
135 1.3 joerg static void sieve_large(uint32_t);
136 1.1 elad
137 1.1 elad /*
138 1.1 elad * Sieve p's and q's with small factors
139 1.1 elad */
140 1.3 joerg static void
141 1.1 elad sieve_large(uint32_t s)
142 1.1 elad {
143 1.1 elad BN_ULONG r;
144 1.1 elad BN_ULONG u;
145 1.1 elad
146 1.1 elad #ifdef DEBUG_SMALL
147 1.1 elad (void)fprintf(stderr, "%lu\n", s);
148 1.1 elad #endif
149 1.1 elad largetries++;
150 1.1 elad /* r = largebase mod s */
151 1.1 elad r = BN_mod_word(largebase, (BN_ULONG) s);
152 1.1 elad if (r == 0) {
153 1.1 elad /* s divides into largebase exactly */
154 1.1 elad u = 0;
155 1.1 elad } else {
156 1.1 elad /* largebase+u is first entry divisible by s */
157 1.1 elad u = s - r;
158 1.1 elad }
159 1.1 elad
160 1.1 elad if (u < largebits * 2) {
161 1.1 elad /*
162 1.1 elad * The sieve omits p's and q's divisible by 2, so ensure that
163 1.1 elad * largebase+u is odd. Then, step through the sieve in
164 1.1 elad * increments of 2*s
165 1.1 elad */
166 1.1 elad if (u & 0x1) {
167 1.1 elad /* Make largebase+u odd, and u even */
168 1.1 elad u += s;
169 1.1 elad }
170 1.1 elad
171 1.1 elad /* Mark all multiples of 2*s */
172 1.1 elad for (u /= 2; u < largebits; u += s) {
173 1.1 elad BIT_SET(LargeSieve, (uint32_t)u);
174 1.1 elad }
175 1.1 elad }
176 1.1 elad
177 1.1 elad /* r = p mod s */
178 1.1 elad r = (2 * r + 1) % s;
179 1.1 elad
180 1.1 elad if (r == 0) {
181 1.1 elad /* s divides p exactly */
182 1.1 elad u = 0;
183 1.1 elad } else {
184 1.1 elad /* p+u is first entry divisible by s */
185 1.1 elad u = s - r;
186 1.1 elad }
187 1.1 elad
188 1.1 elad if (u < largebits * 4) {
189 1.1 elad /*
190 1.1 elad * The sieve omits p's divisible by 4, so ensure that
191 1.1 elad * largebase+u is not. Then, step through the sieve in
192 1.1 elad * increments of 4*s
193 1.1 elad */
194 1.1 elad while (u & 0x3) {
195 1.1 elad if (SMALL_MAXIMUM - u < s) {
196 1.1 elad return;
197 1.1 elad }
198 1.1 elad
199 1.1 elad u += s;
200 1.1 elad }
201 1.1 elad
202 1.1 elad /* Mark all multiples of 4*s */
203 1.1 elad for (u /= 4; u < largebits; u += s) {
204 1.1 elad BIT_SET(LargeSieve, (uint32_t)u);
205 1.1 elad }
206 1.1 elad }
207 1.1 elad }
208 1.1 elad
209 1.1 elad /*
210 1.1 elad * list candidates for Sophie-Germaine primes
211 1.1 elad * (where q = (p-1)/2)
212 1.1 elad * to standard output.
213 1.1 elad * The list is checked against small known primes
214 1.1 elad * (less than 2**30).
215 1.1 elad */
216 1.1 elad int
217 1.1 elad main(int argc, char *argv[])
218 1.1 elad {
219 1.1 elad BIGNUM *q;
220 1.1 elad uint32_t j;
221 1.1 elad int power;
222 1.1 elad uint32_t r;
223 1.1 elad uint32_t s;
224 1.1 elad uint32_t smallwords = TINY_NUMBER >> 6;
225 1.1 elad uint32_t t;
226 1.1 elad time_t time_start;
227 1.1 elad time_t time_stop;
228 1.1 elad uint32_t tinywords = TINY_NUMBER >> 6;
229 1.1 elad unsigned int i;
230 1.1 elad
231 1.1 elad setprogname(argv[0]);
232 1.1 elad
233 1.1 elad if (argc < 3) {
234 1.1 elad usage();
235 1.1 elad }
236 1.1 elad
237 1.1 elad /*
238 1.1 elad * Set power to the length in bits of the prime to be generated.
239 1.1 elad * This is changed to 1 less than the desired safe prime moduli p.
240 1.1 elad */
241 1.1 elad power = (int) strtoul(argv[2], NULL, 10);
242 1.2 lukem if ((unsigned)power > TEST_MAXIMUM) {
243 1.1 elad errx(1, "Too many bits: %d > %lu.", power,
244 1.1 elad (unsigned long)TEST_MAXIMUM);
245 1.1 elad } else if (power < TEST_MINIMUM) {
246 1.1 elad errx(1, "Too few bits: %d < %lu.", power,
247 1.1 elad (unsigned long)TEST_MINIMUM);
248 1.1 elad }
249 1.1 elad
250 1.1 elad power--; /* decrement before squaring */
251 1.1 elad
252 1.1 elad /*
253 1.1 elad * The density of ordinary primes is on the order of 1/bits, so the
254 1.1 elad * density of safe primes should be about (1/bits)**2. Set test range
255 1.1 elad * to something well above bits**2 to be reasonably sure (but not
256 1.1 elad * guaranteed) of catching at least one safe prime.
257 1.1 elad */
258 1.1 elad largewords = (uint32_t)((unsigned long)
259 1.1 elad (power * power) >> (SHIFT_WORD - TEST_POWER));
260 1.1 elad
261 1.1 elad /*
262 1.1 elad * Need idea of how much memory is available. We don't have to use all
263 1.1 elad * of it.
264 1.1 elad */
265 1.1 elad largememory = (uint32_t)strtoul(argv[1], NULL, 10);
266 1.1 elad if (largememory > LARGE_MAXIMUM) {
267 1.1 elad warnx("Limited memory: %u MB; limit %lu MB.", largememory,
268 1.1 elad LARGE_MAXIMUM);
269 1.1 elad largememory = LARGE_MAXIMUM;
270 1.1 elad }
271 1.1 elad
272 1.1 elad if (largewords <= (largememory << SHIFT_MEGAWORD)) {
273 1.1 elad warnx("Increased memory: %u MB; need %u bytes.",
274 1.1 elad largememory, (largewords << SHIFT_BYTE));
275 1.1 elad largewords = (largememory << SHIFT_MEGAWORD);
276 1.1 elad } else if (largememory > 0) {
277 1.1 elad warnx("Decreased memory: %u MB; want %u bytes.",
278 1.1 elad largememory, (largewords << SHIFT_BYTE));
279 1.1 elad largewords = (largememory << SHIFT_MEGAWORD);
280 1.1 elad }
281 1.1 elad
282 1.1 elad if ((TinySieve = (uint32_t *) calloc((size_t) tinywords, sizeof(uint32_t))) == NULL) {
283 1.4 andvar errx(1, "Insufficient memory for tiny sieve: need %u bytes.",
284 1.1 elad tinywords << SHIFT_BYTE);
285 1.1 elad }
286 1.1 elad tinybits = tinywords << SHIFT_WORD;
287 1.1 elad
288 1.1 elad if ((SmallSieve = (uint32_t *) calloc((size_t) smallwords, sizeof(uint32_t))) == NULL) {
289 1.1 elad errx(1, "Insufficient memory for small sieve: need %u bytes.",
290 1.1 elad smallwords << SHIFT_BYTE);
291 1.1 elad }
292 1.1 elad smallbits = smallwords << SHIFT_WORD;
293 1.1 elad
294 1.1 elad /*
295 1.1 elad * dynamically determine available memory
296 1.1 elad */
297 1.1 elad while ((LargeSieve = (uint32_t *)calloc((size_t)largewords,
298 1.1 elad sizeof(uint32_t))) == NULL) {
299 1.1 elad /* 1/4 MB chunks */
300 1.1 elad largewords -= (1L << (SHIFT_MEGAWORD - 2));
301 1.1 elad }
302 1.1 elad largebits = largewords << SHIFT_WORD;
303 1.1 elad largenumbers = largebits * 2; /* even numbers excluded */
304 1.1 elad
305 1.1 elad /* validation check: count the number of primes tried */
306 1.1 elad largetries = 0;
307 1.1 elad
308 1.1 elad q = BN_new();
309 1.1 elad largebase = BN_new();
310 1.1 elad
311 1.1 elad /*
312 1.1 elad * Generate random starting point for subprime search, or use
313 1.1 elad * specified parameter.
314 1.1 elad */
315 1.1 elad if (argc < 4) {
316 1.1 elad BN_rand(largebase, power, 1, 1);
317 1.1 elad } else {
318 1.1 elad BIGNUM *a;
319 1.1 elad
320 1.1 elad a = largebase;
321 1.1 elad BN_hex2bn(&a, argv[2]);
322 1.1 elad }
323 1.1 elad
324 1.1 elad /* ensure odd */
325 1.1 elad if (!BN_is_odd(largebase)) {
326 1.1 elad BN_set_bit(largebase, 0);
327 1.1 elad }
328 1.1 elad
329 1.1 elad time(&time_start);
330 1.1 elad (void)fprintf(stderr,
331 1.1 elad "%.24s Sieve next %u plus %d-bit start point:\n# ",
332 1.1 elad ctime(&time_start), largenumbers, power);
333 1.1 elad BN_print_fp(stderr, largebase);
334 1.1 elad (void)fprintf(stderr, "\n");
335 1.1 elad
336 1.1 elad /*
337 1.1 elad * TinySieve
338 1.1 elad */
339 1.1 elad for (i = 0; i < tinybits; i++) {
340 1.1 elad if (BIT_TEST(TinySieve, i)) {
341 1.1 elad /* 2*i+3 is composite */
342 1.1 elad continue;
343 1.1 elad }
344 1.1 elad
345 1.1 elad /* The next tiny prime */
346 1.1 elad t = 2 * i + 3;
347 1.1 elad
348 1.1 elad /* Mark all multiples of t */
349 1.1 elad for (j = i + t; j < tinybits; j += t) {
350 1.1 elad BIT_SET(TinySieve, j);
351 1.1 elad }
352 1.1 elad
353 1.1 elad sieve_large(t);
354 1.1 elad }
355 1.1 elad
356 1.1 elad /*
357 1.1 elad * Start the small block search at the next possible prime. To avoid
358 1.1 elad * fencepost errors, the last pass is skipped.
359 1.1 elad */
360 1.1 elad for (smallbase = TINY_NUMBER + 3;
361 1.1 elad smallbase < (SMALL_MAXIMUM - TINY_NUMBER);
362 1.1 elad smallbase += TINY_NUMBER) {
363 1.1 elad for (i = 0; i < tinybits; i++) {
364 1.1 elad if (BIT_TEST(TinySieve, i)) {
365 1.1 elad /* 2*i+3 is composite */
366 1.1 elad continue;
367 1.1 elad }
368 1.1 elad
369 1.1 elad /* The next tiny prime */
370 1.1 elad t = 2 * i + 3;
371 1.1 elad r = smallbase % t;
372 1.1 elad
373 1.1 elad if (r == 0) {
374 1.1 elad /* t divides into smallbase exactly */
375 1.1 elad s = 0;
376 1.1 elad } else {
377 1.1 elad /* smallbase+s is first entry divisible by t */
378 1.1 elad s = t - r;
379 1.1 elad }
380 1.1 elad
381 1.1 elad /*
382 1.1 elad * The sieve omits even numbers, so ensure that
383 1.1 elad * smallbase+s is odd. Then, step through the sieve in
384 1.1 elad * increments of 2*t
385 1.1 elad */
386 1.1 elad if (s & 1) {
387 1.1 elad /* Make smallbase+s odd, and s even */
388 1.1 elad s += t;
389 1.1 elad }
390 1.1 elad
391 1.1 elad /* Mark all multiples of 2*t */
392 1.1 elad for (s /= 2; s < smallbits; s += t) {
393 1.1 elad BIT_SET(SmallSieve, s);
394 1.1 elad }
395 1.1 elad }
396 1.1 elad
397 1.1 elad /*
398 1.1 elad * SmallSieve
399 1.1 elad */
400 1.1 elad for (i = 0; i < smallbits; i++) {
401 1.1 elad if (BIT_TEST(SmallSieve, i)) {
402 1.1 elad /* 2*i+smallbase is composite */
403 1.1 elad continue;
404 1.1 elad }
405 1.1 elad
406 1.1 elad /* The next small prime */
407 1.1 elad sieve_large((2 * i) + smallbase);
408 1.1 elad }
409 1.1 elad
410 1.1 elad memset(SmallSieve, 0, (size_t)(smallwords << SHIFT_BYTE));
411 1.1 elad }
412 1.1 elad
413 1.1 elad time(&time_stop);
414 1.1 elad (void)fprintf(stderr,
415 1.1 elad "%.24s Sieved with %u small primes in %lu seconds\n",
416 1.1 elad ctime(&time_stop), largetries,
417 1.1 elad (long) (time_stop - time_start));
418 1.1 elad
419 1.1 elad for (j = r = 0; j < largebits; j++) {
420 1.1 elad if (BIT_TEST(LargeSieve, j)) {
421 1.1 elad /* Definitely composite, skip */
422 1.1 elad continue;
423 1.1 elad }
424 1.1 elad
425 1.1 elad #ifdef DEBUG_LARGE
426 1.1 elad (void)fprintf(stderr, "test q = largebase+%lu\n", 2 * j);
427 1.1 elad #endif
428 1.1 elad
429 1.1 elad BN_set_word(q, (unsigned long)(2 * j));
430 1.1 elad BN_add(q, q, largebase);
431 1.1 elad
432 1.1 elad if (0 > qfileout(stdout,
433 1.1 elad (uint32_t) QTYPE_SOPHIE_GERMAINE,
434 1.1 elad (uint32_t) QTEST_SIEVE,
435 1.1 elad largetries,
436 1.1 elad (uint32_t) (power - 1), /* MSB */
437 1.1 elad (uint32_t) (0), /* generator unknown */
438 1.1 elad q)) {
439 1.1 elad break;
440 1.1 elad }
441 1.1 elad
442 1.1 elad r++; /* count q */
443 1.1 elad }
444 1.1 elad
445 1.1 elad time(&time_stop);
446 1.1 elad
447 1.1 elad free(LargeSieve);
448 1.1 elad free(SmallSieve);
449 1.1 elad free(TinySieve);
450 1.1 elad
451 1.1 elad fflush(stdout);
452 1.1 elad /* fclose(stdout); */
453 1.1 elad
454 1.1 elad (void) fprintf(stderr, "%.24s Found %u candidates\n",
455 1.1 elad ctime(&time_stop), r);
456 1.1 elad
457 1.1 elad return (0);
458 1.1 elad }
459 1.1 elad
460 1.1 elad static void
461 1.1 elad usage(void)
462 1.1 elad {
463 1.1 elad (void)fprintf(stderr, "Usage: %s <megabytes> <bits> [initial]\n"
464 1.1 elad "Possible values for <megabytes>: 0, %lu to %lu\n"
465 1.1 elad "Possible values for <bits>: %lu to %lu\n",
466 1.1 elad getprogname(),
467 1.1 elad LARGE_MINIMUM,
468 1.1 elad LARGE_MAXIMUM,
469 1.1 elad (unsigned long) TEST_MINIMUM,
470 1.1 elad (unsigned long) TEST_MAXIMUM);
471 1.1 elad
472 1.1 elad exit(1);
473 1.1 elad }
474