version 1.1.2.2, 2004/08/19 22:37:31 |
version 1.2, 2003/11/21 11:57:03 |
|
|
*/ |
*/ |
|
|
#include "includes.h" |
#include "includes.h" |
|
#include "moduli.h" |
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "log.h" |
#include "log.h" |
|
|
#include <openssl/bn.h> |
#include <openssl/bn.h> |
|
|
|
|
/* |
/* |
|
* Debugging defines |
|
*/ |
|
|
|
/* define DEBUG_LARGE 1 */ |
|
/* define DEBUG_SMALL 1 */ |
|
/* define DEBUG_TEST 1 */ |
|
|
|
/* |
* File output defines |
* File output defines |
*/ |
*/ |
|
|
/* need line long enough for largest moduli plus headers */ |
/* need line long enough for largest moduli plus headers */ |
#define QLINESIZE (100+8192) |
#define QLINESIZE (100+8192) |
|
|
/* Type: decimal. |
/* Type: decimal. |
* Specifies the internal structure of the prime modulus. |
* Specifies the internal structure of the prime modulus. |
*/ |
*/ |
#define QTYPE_UNKNOWN (0) |
#define QTYPE_UNKNOWN (0) |
#define QTYPE_UNSTRUCTURED (1) |
#define QTYPE_UNSTRUCTURED (1) |
#define QTYPE_SAFE (2) |
#define QTYPE_SAFE (2) |
#define QTYPE_SCHNOOR (3) |
#define QTYPE_SCHNOOR (3) |
#define QTYPE_SOPHIE_GERMAIN (4) |
#define QTYPE_SOPHIE_GERMAINE (4) |
#define QTYPE_STRONG (5) |
#define QTYPE_STRONG (5) |
|
|
/* Tests: decimal (bit field). |
/* Tests: decimal (bit field). |
* Specifies the methods used in checking for primality. |
* Specifies the methods used in checking for primality. |
* Usually, more than one test is used. |
* Usually, more than one test is used. |
*/ |
*/ |
#define QTEST_UNTESTED (0x00) |
#define QTEST_UNTESTED (0x00) |
#define QTEST_COMPOSITE (0x01) |
#define QTEST_COMPOSITE (0x01) |
#define QTEST_SIEVE (0x02) |
#define QTEST_SIEVE (0x02) |
#define QTEST_MILLER_RABIN (0x04) |
#define QTEST_MILLER_RABIN (0x04) |
#define QTEST_JACOBI (0x08) |
#define QTEST_JACOBI (0x08) |
#define QTEST_ELLIPTIC (0x10) |
#define QTEST_ELLIPTIC (0x10) |
|
|
/* |
/* Size: decimal. |
* Size: decimal. |
|
* Specifies the number of the most significant bit (0 to M). |
* Specifies the number of the most significant bit (0 to M). |
* WARNING: internally, usually 1 to N. |
** WARNING: internally, usually 1 to N. |
*/ |
*/ |
#define QSIZE_MINIMUM (511) |
#define QSIZE_MINIMUM (511) |
|
|
/* |
/* |
* Prime sieving defines |
* Prime sieving defines |
*/ |
*/ |
|
|
/* Constant: assuming 8 bit bytes and 32 bit words */ |
/* Constant: assuming 8 bit bytes and 32 bit words */ |
#define SHIFT_BIT (3) |
#define SHIFT_BIT (3) |
#define SHIFT_BYTE (2) |
#define SHIFT_BYTE (2) |
#define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE) |
#define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE) |
#define SHIFT_MEGABYTE (20) |
#define SHIFT_MEGABYTE (20) |
#define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE) |
#define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE) |
|
|
/* |
/* |
* Using virtual memory can cause thrashing. This should be the largest |
|
* number that is supported without a large amount of disk activity -- |
|
* that would increase the run time from hours to days or weeks! |
|
*/ |
|
#define LARGE_MINIMUM (8UL) /* megabytes */ |
|
|
|
/* |
|
* Do not increase this number beyond the unsigned integer bit size. |
|
* Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits). |
|
*/ |
|
#define LARGE_MAXIMUM (127UL) /* megabytes */ |
|
|
|
/* |
|
* Constant: when used with 32-bit integers, the largest sieve prime |
* Constant: when used with 32-bit integers, the largest sieve prime |
* has to be less than 2**32. |
* has to be less than 2**32. |
*/ |
*/ |
#define SMALL_MAXIMUM (0xffffffffUL) |
#define SMALL_MAXIMUM (0xffffffffUL) |
|
|
/* Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1. */ |
/* Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1. */ |
#define TINY_NUMBER (1UL<<16) |
#define TINY_NUMBER (1UL<<16) |
|
|
/* Ensure enough bit space for testing 2*q. */ |
/* Ensure enough bit space for testing 2*q. */ |
#define TEST_MAXIMUM (1UL<<16) |
#define TEST_MAXIMUM (1UL<<16) |
|
|
* Prime testing defines |
* Prime testing defines |
*/ |
*/ |
|
|
/* Minimum number of primality tests to perform */ |
|
#define TRIAL_MINIMUM (4) |
|
|
|
/* |
/* |
* Sieving data (XXX - move to struct) |
* Sieving data (XXX - move to struct) |
*/ |
*/ |
|
|
static u_int32_t largebits, largememory; /* megabytes */ |
static u_int32_t largebits, largememory; /* megabytes */ |
static BIGNUM *largebase; |
static BIGNUM *largebase; |
|
|
int gen_candidates(FILE *, int, int, BIGNUM *); |
|
int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); |
|
|
|
/* |
/* |
* print moduli out in consistent form, |
* print moduli out in consistent form, |
|
|
{ |
{ |
u_int32_t r, u; |
u_int32_t r, u; |
|
|
debug3("sieve_large %u", s); |
debug2("sieve_large %u", s); |
largetries++; |
largetries++; |
/* r = largebase mod s */ |
/* r = largebase mod s */ |
r = BN_mod_word(largebase, s); |
r = BN_mod_word(largebase, s); |
|
|
} |
} |
|
|
/* |
/* |
* list candidates for Sophie-Germain primes (where q = (p-1)/2) |
* list candidates for Sophie-Germaine primes (where q = (p-1)/2) |
* to standard output. |
* to standard output. |
* The list is checked against small known primes (less than 2**30). |
* The list is checked against small known primes (less than 2**30). |
*/ |
*/ |
|
|
|
|
largememory = memory; |
largememory = memory; |
|
|
if (memory != 0 && |
|
(memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) { |
|
error("Invalid memory amount (min %ld, max %ld)", |
|
LARGE_MINIMUM, LARGE_MAXIMUM); |
|
return (-1); |
|
} |
|
|
|
/* |
/* |
* Set power to the length in bits of the prime to be generated. |
* Set power to the length in bits of the prime to be generated. |
* This is changed to 1 less than the desired safe prime moduli p. |
* This is changed to 1 less than the desired safe prime moduli p. |
|
|
debug2("test q = largebase+%u", 2 * j); |
debug2("test q = largebase+%u", 2 * j); |
BN_set_word(q, 2 * j); |
BN_set_word(q, 2 * j); |
BN_add(q, q, largebase); |
BN_add(q, q, largebase); |
if (qfileout(out, QTYPE_SOPHIE_GERMAIN, QTEST_SIEVE, |
if (qfileout(out, QTYPE_SOPHIE_GERMAINE, QTEST_SIEVE, |
largetries, (power - 1) /* MSB */, (0), q) == -1) { |
largetries, (power - 1) /* MSB */, (0), q) == -1) { |
ret = -1; |
ret = -1; |
break; |
break; |
|
|
* The result is a list of so-call "safe" primes |
* The result is a list of so-call "safe" primes |
*/ |
*/ |
int |
int |
prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted) |
prime_test(FILE *in, FILE *out, u_int32_t trials, |
|
u_int32_t generator_wanted) |
{ |
{ |
BIGNUM *q, *p, *a; |
BIGNUM *q, *p, *a; |
BN_CTX *ctx; |
BN_CTX *ctx; |
|
|
time_t time_start, time_stop; |
time_t time_start, time_stop; |
int res; |
int res; |
|
|
if (trials < TRIAL_MINIMUM) { |
|
error("Minimum primality trials is %d", TRIAL_MINIMUM); |
|
return (-1); |
|
} |
|
|
|
time(&time_start); |
time(&time_start); |
|
|
p = BN_new(); |
p = BN_new(); |
|
|
debug2("%10u: known composite", count_in); |
debug2("%10u: known composite", count_in); |
continue; |
continue; |
} |
} |
|
|
/* tries */ |
/* tries */ |
in_tries = strtoul(cp, &cp, 10); |
in_tries = strtoul(cp, &cp, 10); |
|
|
|
|
|
|
/* modulus (hex) */ |
/* modulus (hex) */ |
switch (in_type) { |
switch (in_type) { |
case QTYPE_SOPHIE_GERMAIN: |
case QTYPE_SOPHIE_GERMAINE: |
debug2("%10u: (%u) Sophie-Germain", count_in, in_type); |
debug2("%10u: (%u) Sophie-Germaine", count_in, in_type); |
a = q; |
a = q; |
BN_hex2bn(&a, cp); |
BN_hex2bn(&a, cp); |
/* p = 2*q + 1 */ |
/* p = 2*q + 1 */ |
|
|
in_size += 1; |
in_size += 1; |
generator_known = 0; |
generator_known = 0; |
break; |
break; |
case QTYPE_UNSTRUCTURED: |
default: |
case QTYPE_SAFE: |
|
case QTYPE_SCHNOOR: |
|
case QTYPE_STRONG: |
|
case QTYPE_UNKNOWN: |
|
debug2("%10u: (%u)", count_in, in_type); |
debug2("%10u: (%u)", count_in, in_type); |
a = p; |
a = p; |
BN_hex2bn(&a, cp); |
BN_hex2bn(&a, cp); |
/* q = (p-1) / 2 */ |
/* q = (p-1) / 2 */ |
BN_rshift(q, p, 1); |
BN_rshift(q, p, 1); |
break; |
break; |
default: |
|
debug2("Unknown prime type"); |
|
break; |
|
} |
} |
|
|
/* |
/* |
|
|
in_tries += trials; |
in_tries += trials; |
else |
else |
in_tries = trials; |
in_tries = trials; |
|
|
/* |
/* |
* guess unknown generator |
* guess unknown generator |
*/ |
*/ |
|
|
else { |
else { |
u_int32_t r = BN_mod_word(p, 10); |
u_int32_t r = BN_mod_word(p, 10); |
|
|
if (r == 3 || r == 7) |
if (r == 3 || r == 7) { |
generator_known = 5; |
generator_known = 5; |
|
} |
} |
} |
} |
} |
/* |
/* |
|
|
continue; |
continue; |
} |
} |
|
|
/* |
|
* Primes with no known generator are useless for DH, so |
|
* skip those. |
|
*/ |
|
if (generator_known == 0) { |
|
debug2("%10u: no known generator", count_in); |
|
continue; |
|
} |
|
|
|
count_possible++; |
count_possible++; |
|
|
/* |
/* |
|
|
* vast majority of composite q's. |
* vast majority of composite q's. |
*/ |
*/ |
if (BN_is_prime(q, 1, NULL, ctx, NULL) <= 0) { |
if (BN_is_prime(q, 1, NULL, ctx, NULL) <= 0) { |
debug("%10u: q failed first possible prime test", |
debug2("%10u: q failed first possible prime test", |
count_in); |
count_in); |
continue; |
continue; |
} |
} |
|
|
* doesn't hurt to specify a high iteration count. |
* doesn't hurt to specify a high iteration count. |
*/ |
*/ |
if (!BN_is_prime(p, trials, NULL, ctx, NULL)) { |
if (!BN_is_prime(p, trials, NULL, ctx, NULL)) { |
debug("%10u: p is not prime", count_in); |
debug2("%10u: p is not prime", count_in); |
continue; |
continue; |
} |
} |
debug("%10u: p is almost certainly prime", count_in); |
debug("%10u: p is almost certainly prime", count_in); |