moduli.c revision 1.1.1.3 1 /* $OpenBSD: moduli.c,v 1.25 2011/10/19 00:06:10 djm Exp $ */
2 /*
3 * Copyright 1994 Phil Karn <karn (at) qualcomm.com>
4 * Copyright 1996-1998, 2003 William Allen Simpson <wsimpson (at) greendragon.com>
5 * Copyright 2000 Niels Provos <provos (at) 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 <sys/param.h>
41 #include <sys/types.h>
42
43 #include <openssl/bn.h>
44 #include <openssl/dh.h>
45
46 #include <errno.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <stdarg.h>
51 #include <time.h>
52 #include <unistd.h>
53
54 #include "xmalloc.h"
55 #include "dh.h"
56 #include "log.h"
57
58 /*
59 * File output defines
60 */
61
62 /* need line long enough for largest moduli plus headers */
63 #define QLINESIZE (100+8192)
64
65 /*
66 * Size: decimal.
67 * Specifies the number of the most significant bit (0 to M).
68 * WARNING: internally, usually 1 to N.
69 */
70 #define QSIZE_MINIMUM (511)
71
72 /*
73 * Prime sieving defines
74 */
75
76 /* Constant: assuming 8 bit bytes and 32 bit words */
77 #define SHIFT_BIT (3)
78 #define SHIFT_BYTE (2)
79 #define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE)
80 #define SHIFT_MEGABYTE (20)
81 #define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE)
82
83 /*
84 * Using virtual memory can cause thrashing. This should be the largest
85 * number that is supported without a large amount of disk activity --
86 * that would increase the run time from hours to days or weeks!
87 */
88 #define LARGE_MINIMUM (8UL) /* megabytes */
89
90 /*
91 * Do not increase this number beyond the unsigned integer bit size.
92 * Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits).
93 */
94 #define LARGE_MAXIMUM (127UL) /* megabytes */
95
96 /*
97 * Constant: when used with 32-bit integers, the largest sieve prime
98 * has to be less than 2**32.
99 */
100 #define SMALL_MAXIMUM (0xffffffffUL)
101
102 /* Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1. */
103 #define TINY_NUMBER (1UL<<16)
104
105 /* Ensure enough bit space for testing 2*q. */
106 #define TEST_MAXIMUM (1UL<<16)
107 #define TEST_MINIMUM (QSIZE_MINIMUM + 1)
108 /* real TEST_MINIMUM (1UL << (SHIFT_WORD - TEST_POWER)) */
109 #define TEST_POWER (3) /* 2**n, n < SHIFT_WORD */
110
111 /* bit operations on 32-bit words */
112 #define BIT_CLEAR(a,n) ((a)[(n)>>SHIFT_WORD] &= ~(1L << ((n) & 31)))
113 #define BIT_SET(a,n) ((a)[(n)>>SHIFT_WORD] |= (1L << ((n) & 31)))
114 #define BIT_TEST(a,n) ((a)[(n)>>SHIFT_WORD] & (1L << ((n) & 31)))
115
116 /*
117 * Prime testing defines
118 */
119
120 /* Minimum number of primality tests to perform */
121 #define TRIAL_MINIMUM (4)
122
123 /*
124 * Sieving data (XXX - move to struct)
125 */
126
127 /* sieve 2**16 */
128 static u_int32_t *TinySieve, tinybits;
129
130 /* sieve 2**30 in 2**16 parts */
131 static u_int32_t *SmallSieve, smallbits, smallbase;
132
133 /* sieve relative to the initial value */
134 static u_int32_t *LargeSieve, largewords, largetries, largenumbers;
135 static u_int32_t largebits, largememory; /* megabytes */
136 static BIGNUM *largebase;
137
138 int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
139 int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *);
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 debug3("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-Germain 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, u_int32_t memory, u_int32_t 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 u_int32_t i;
243 int ret = 0;
244
245 largememory = memory;
246
247 if (memory != 0 &&
248 (memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) {
249 error("Invalid memory amount (min %ld, max %ld)",
250 LARGE_MINIMUM, LARGE_MAXIMUM);
251 return (-1);
252 }
253
254 /*
255 * Set power to the length in bits of the prime to be generated.
256 * This is changed to 1 less than the desired safe prime moduli p.
257 */
258 if (power > TEST_MAXIMUM) {
259 error("Too many bits: %u > %lu", power, TEST_MAXIMUM);
260 return (-1);
261 } else if (power < TEST_MINIMUM) {
262 error("Too few bits: %u < %u", power, TEST_MINIMUM);
263 return (-1);
264 }
265 power--; /* decrement before squaring */
266
267 /*
268 * The density of ordinary primes is on the order of 1/bits, so the
269 * density of safe primes should be about (1/bits)**2. Set test range
270 * to something well above bits**2 to be reasonably sure (but not
271 * guaranteed) of catching at least one safe prime.
272 */
273 largewords = ((power * power) >> (SHIFT_WORD - TEST_POWER));
274
275 /*
276 * Need idea of how much memory is available. We don't have to use all
277 * of it.
278 */
279 if (largememory > LARGE_MAXIMUM) {
280 logit("Limited memory: %u MB; limit %lu MB",
281 largememory, LARGE_MAXIMUM);
282 largememory = LARGE_MAXIMUM;
283 }
284
285 if (largewords <= (largememory << SHIFT_MEGAWORD)) {
286 logit("Increased memory: %u MB; need %u bytes",
287 largememory, (largewords << SHIFT_BYTE));
288 largewords = (largememory << SHIFT_MEGAWORD);
289 } else if (largememory > 0) {
290 logit("Decreased memory: %u MB; want %u bytes",
291 largememory, (largewords << SHIFT_BYTE));
292 largewords = (largememory << SHIFT_MEGAWORD);
293 }
294
295 TinySieve = xcalloc(tinywords, sizeof(u_int32_t));
296 tinybits = tinywords << SHIFT_WORD;
297
298 SmallSieve = xcalloc(smallwords, sizeof(u_int32_t));
299 smallbits = smallwords << SHIFT_WORD;
300
301 /*
302 * dynamically determine available memory
303 */
304 while ((LargeSieve = calloc(largewords, sizeof(u_int32_t))) == NULL)
305 largewords -= (1L << (SHIFT_MEGAWORD - 2)); /* 1/4 MB chunks */
306
307 largebits = largewords << SHIFT_WORD;
308 largenumbers = largebits * 2; /* even numbers excluded */
309
310 /* validation check: count the number of primes tried */
311 largetries = 0;
312 if ((q = BN_new()) == NULL)
313 fatal("BN_new failed");
314
315 /*
316 * Generate random starting point for subprime search, or use
317 * specified parameter.
318 */
319 if ((largebase = BN_new()) == NULL)
320 fatal("BN_new failed");
321 if (start == NULL) {
322 if (BN_rand(largebase, power, 1, 1) == 0)
323 fatal("BN_rand failed");
324 } else {
325 if (BN_copy(largebase, start) == NULL)
326 fatal("BN_copy: failed");
327 }
328
329 /* ensure odd */
330 if (BN_set_bit(largebase, 0) == 0)
331 fatal("BN_set_bit: failed");
332
333 time(&time_start);
334
335 logit("%.24s Sieve next %u plus %u-bit", ctime(&time_start),
336 largenumbers, power);
337 debug2("start point: 0x%s", BN_bn2hex(largebase));
338
339 /*
340 * TinySieve
341 */
342 for (i = 0; i < tinybits; i++) {
343 if (BIT_TEST(TinySieve, i))
344 continue; /* 2*i+3 is composite */
345
346 /* The next tiny prime */
347 t = 2 * i + 3;
348
349 /* Mark all multiples of t */
350 for (j = i + t; j < tinybits; j += t)
351 BIT_SET(TinySieve, j);
352
353 sieve_large(t);
354 }
355
356 /*
357 * Start the small block search at the next possible prime. To avoid
358 * fencepost errors, the last pass is skipped.
359 */
360 for (smallbase = TINY_NUMBER + 3;
361 smallbase < (SMALL_MAXIMUM - TINY_NUMBER);
362 smallbase += TINY_NUMBER) {
363 for (i = 0; i < tinybits; i++) {
364 if (BIT_TEST(TinySieve, i))
365 continue; /* 2*i+3 is composite */
366
367 /* The next tiny prime */
368 t = 2 * i + 3;
369 r = smallbase % t;
370
371 if (r == 0) {
372 s = 0; /* t divides into smallbase exactly */
373 } else {
374 /* smallbase+s is first entry divisible by t */
375 s = t - r;
376 }
377
378 /*
379 * The sieve omits even numbers, so ensure that
380 * smallbase+s is odd. Then, step through the sieve
381 * in increments of 2*t
382 */
383 if (s & 1)
384 s += t; /* Make smallbase+s odd, and s even */
385
386 /* Mark all multiples of 2*t */
387 for (s /= 2; s < smallbits; s += t)
388 BIT_SET(SmallSieve, s);
389 }
390
391 /*
392 * SmallSieve
393 */
394 for (i = 0; i < smallbits; i++) {
395 if (BIT_TEST(SmallSieve, i))
396 continue; /* 2*i+smallbase is composite */
397
398 /* The next small prime */
399 sieve_large((2 * i) + smallbase);
400 }
401
402 memset(SmallSieve, 0, smallwords << SHIFT_BYTE);
403 }
404
405 time(&time_stop);
406
407 logit("%.24s Sieved with %u small primes in %ld seconds",
408 ctime(&time_stop), largetries, (long) (time_stop - time_start));
409
410 for (j = r = 0; j < largebits; j++) {
411 if (BIT_TEST(LargeSieve, j))
412 continue; /* Definitely composite, skip */
413
414 debug2("test q = largebase+%u", 2 * j);
415 if (BN_set_word(q, 2 * j) == 0)
416 fatal("BN_set_word failed");
417 if (BN_add(q, q, largebase) == 0)
418 fatal("BN_add failed");
419 if (qfileout(out, MODULI_TYPE_SOPHIE_GERMAIN,
420 MODULI_TESTS_SIEVE, largetries,
421 (power - 1) /* MSB */, (0), q) == -1) {
422 ret = -1;
423 break;
424 }
425
426 r++; /* count q */
427 }
428
429 time(&time_stop);
430
431 xfree(LargeSieve);
432 xfree(SmallSieve);
433 xfree(TinySieve);
434
435 logit("%.24s Found %u candidates", ctime(&time_stop), r);
436
437 return (ret);
438 }
439
440 static void
441 write_checkpoint(char *cpfile, u_int32_t lineno)
442 {
443 FILE *fp;
444 char tmp[MAXPATHLEN];
445 int r;
446
447 r = snprintf(tmp, sizeof(tmp), "%s.XXXXXXXXXX", cpfile);
448 if (r == -1 || r >= MAXPATHLEN) {
449 logit("write_checkpoint: temp pathname too long");
450 return;
451 }
452 if ((r = mkstemp(tmp)) == -1) {
453 logit("mkstemp(%s): %s", tmp, strerror(errno));
454 return;
455 }
456 if ((fp = fdopen(r, "w")) == NULL) {
457 logit("write_checkpoint: fdopen: %s", strerror(errno));
458 close(r);
459 return;
460 }
461 if (fprintf(fp, "%lu\n", (unsigned long)lineno) > 0 && fclose(fp) == 0
462 && rename(tmp, cpfile) == 0)
463 debug3("wrote checkpoint line %lu to '%s'",
464 (unsigned long)lineno, cpfile);
465 else
466 logit("failed to write to checkpoint file '%s': %s", cpfile,
467 strerror(errno));
468 }
469
470 static unsigned long
471 read_checkpoint(char *cpfile)
472 {
473 FILE *fp;
474 unsigned long lineno = 0;
475
476 if ((fp = fopen(cpfile, "r")) == NULL)
477 return 0;
478 if (fscanf(fp, "%lu\n", &lineno) < 1)
479 logit("Failed to load checkpoint from '%s'", cpfile);
480 else
481 logit("Loaded checkpoint from '%s' line %lu", cpfile, lineno);
482 fclose(fp);
483 return lineno;
484 }
485
486 /*
487 * perform a Miller-Rabin primality test
488 * on the list of candidates
489 * (checking both q and p)
490 * The result is a list of so-call "safe" primes
491 */
492 int
493 prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted,
494 char *checkpoint_file)
495 {
496 BIGNUM *q, *p, *a;
497 BN_CTX *ctx;
498 char *cp, *lp;
499 u_int32_t count_in = 0, count_out = 0, count_possible = 0;
500 u_int32_t generator_known, in_tests, in_tries, in_type, in_size;
501 unsigned long last_processed = 0;
502 time_t time_start, time_stop;
503 int res;
504
505 if (trials < TRIAL_MINIMUM) {
506 error("Minimum primality trials is %d", TRIAL_MINIMUM);
507 return (-1);
508 }
509
510 time(&time_start);
511
512 if ((p = BN_new()) == NULL)
513 fatal("BN_new failed");
514 if ((q = BN_new()) == NULL)
515 fatal("BN_new failed");
516 if ((ctx = BN_CTX_new()) == NULL)
517 fatal("BN_CTX_new failed");
518
519 debug2("%.24s Final %u Miller-Rabin trials (%x generator)",
520 ctime(&time_start), trials, generator_wanted);
521
522 if (checkpoint_file != NULL)
523 last_processed = read_checkpoint(checkpoint_file);
524
525 res = 0;
526 lp = xmalloc(QLINESIZE + 1);
527 while (fgets(lp, QLINESIZE + 1, in) != NULL) {
528 count_in++;
529 if (checkpoint_file != NULL) {
530 if (count_in <= last_processed) {
531 debug3("skipping line %u, before checkpoint",
532 count_in);
533 continue;
534 }
535 write_checkpoint(checkpoint_file, count_in);
536 }
537 if (strlen(lp) < 14 || *lp == '!' || *lp == '#') {
538 debug2("%10u: comment or short line", count_in);
539 continue;
540 }
541
542 /* XXX - fragile parser */
543 /* time */
544 cp = &lp[14]; /* (skip) */
545
546 /* type */
547 in_type = strtoul(cp, &cp, 10);
548
549 /* tests */
550 in_tests = strtoul(cp, &cp, 10);
551
552 if (in_tests & MODULI_TESTS_COMPOSITE) {
553 debug2("%10u: known composite", count_in);
554 continue;
555 }
556
557 /* tries */
558 in_tries = strtoul(cp, &cp, 10);
559
560 /* size (most significant bit) */
561 in_size = strtoul(cp, &cp, 10);
562
563 /* generator (hex) */
564 generator_known = strtoul(cp, &cp, 16);
565
566 /* Skip white space */
567 cp += strspn(cp, " ");
568
569 /* modulus (hex) */
570 switch (in_type) {
571 case MODULI_TYPE_SOPHIE_GERMAIN:
572 debug2("%10u: (%u) Sophie-Germain", count_in, in_type);
573 a = q;
574 if (BN_hex2bn(&a, cp) == 0)
575 fatal("BN_hex2bn failed");
576 /* p = 2*q + 1 */
577 if (BN_lshift(p, q, 1) == 0)
578 fatal("BN_lshift failed");
579 if (BN_add_word(p, 1) == 0)
580 fatal("BN_add_word failed");
581 in_size += 1;
582 generator_known = 0;
583 break;
584 case MODULI_TYPE_UNSTRUCTURED:
585 case MODULI_TYPE_SAFE:
586 case MODULI_TYPE_SCHNORR:
587 case MODULI_TYPE_STRONG:
588 case MODULI_TYPE_UNKNOWN:
589 debug2("%10u: (%u)", count_in, in_type);
590 a = p;
591 if (BN_hex2bn(&a, cp) == 0)
592 fatal("BN_hex2bn failed");
593 /* q = (p-1) / 2 */
594 if (BN_rshift(q, p, 1) == 0)
595 fatal("BN_rshift failed");
596 break;
597 default:
598 debug2("Unknown prime type");
599 break;
600 }
601
602 /*
603 * due to earlier inconsistencies in interpretation, check
604 * the proposed bit size.
605 */
606 if ((u_int32_t)BN_num_bits(p) != (in_size + 1)) {
607 debug2("%10u: bit size %u mismatch", count_in, in_size);
608 continue;
609 }
610 if (in_size < QSIZE_MINIMUM) {
611 debug2("%10u: bit size %u too short", count_in, in_size);
612 continue;
613 }
614
615 if (in_tests & MODULI_TESTS_MILLER_RABIN)
616 in_tries += trials;
617 else
618 in_tries = trials;
619
620 /*
621 * guess unknown generator
622 */
623 if (generator_known == 0) {
624 if (BN_mod_word(p, 24) == 11)
625 generator_known = 2;
626 else if (BN_mod_word(p, 12) == 5)
627 generator_known = 3;
628 else {
629 u_int32_t r = BN_mod_word(p, 10);
630
631 if (r == 3 || r == 7)
632 generator_known = 5;
633 }
634 }
635 /*
636 * skip tests when desired generator doesn't match
637 */
638 if (generator_wanted > 0 &&
639 generator_wanted != generator_known) {
640 debug2("%10u: generator %d != %d",
641 count_in, generator_known, generator_wanted);
642 continue;
643 }
644
645 /*
646 * Primes with no known generator are useless for DH, so
647 * skip those.
648 */
649 if (generator_known == 0) {
650 debug2("%10u: no known generator", count_in);
651 continue;
652 }
653
654 count_possible++;
655
656 /*
657 * The (1/4)^N performance bound on Miller-Rabin is
658 * extremely pessimistic, so don't spend a lot of time
659 * really verifying that q is prime until after we know
660 * that p is also prime. A single pass will weed out the
661 * vast majority of composite q's.
662 */
663 if (BN_is_prime_ex(q, 1, ctx, NULL) <= 0) {
664 debug("%10u: q failed first possible prime test",
665 count_in);
666 continue;
667 }
668
669 /*
670 * q is possibly prime, so go ahead and really make sure
671 * that p is prime. If it is, then we can go back and do
672 * the same for q. If p is composite, chances are that
673 * will show up on the first Rabin-Miller iteration so it
674 * doesn't hurt to specify a high iteration count.
675 */
676 if (!BN_is_prime_ex(p, trials, ctx, NULL)) {
677 debug("%10u: p is not prime", count_in);
678 continue;
679 }
680 debug("%10u: p is almost certainly prime", count_in);
681
682 /* recheck q more rigorously */
683 if (!BN_is_prime_ex(q, trials - 1, ctx, NULL)) {
684 debug("%10u: q is not prime", count_in);
685 continue;
686 }
687 debug("%10u: q is almost certainly prime", count_in);
688
689 if (qfileout(out, MODULI_TYPE_SAFE,
690 in_tests | MODULI_TESTS_MILLER_RABIN,
691 in_tries, in_size, generator_known, p)) {
692 res = -1;
693 break;
694 }
695
696 count_out++;
697 }
698
699 time(&time_stop);
700 xfree(lp);
701 BN_free(p);
702 BN_free(q);
703 BN_CTX_free(ctx);
704
705 if (checkpoint_file != NULL)
706 unlink(checkpoint_file);
707
708 logit("%.24s Found %u safe primes of %u candidates in %ld seconds",
709 ctime(&time_stop), count_out, count_possible,
710 (long) (time_stop - time_start));
711
712 return (res);
713 }
714