mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
8f0f5b69c0
Including mpunsafe.{h,c}, which should be an extra defence against inadvertently using it outside the keygen library.
763 lines
27 KiB
C
763 lines
27 KiB
C
/*
|
||
* Prime generation.
|
||
*/
|
||
|
||
#include <assert.h>
|
||
#include <math.h>
|
||
|
||
#include "ssh.h"
|
||
#include "mpint.h"
|
||
#include "mpunsafe.h"
|
||
#include "sshkeygen.h"
|
||
|
||
/* ----------------------------------------------------------------------
|
||
* Standard probabilistic prime-generation algorithm:
|
||
*
|
||
* - get a number from our PrimeCandidateSource which will at least
|
||
* avoid being divisible by any prime under 2^16
|
||
*
|
||
* - perform the Miller-Rabin primality test enough times to
|
||
* ensure the probability of it being composite is 2^-80 or
|
||
* less
|
||
*
|
||
* - go back to square one if any M-R test fails.
|
||
*/
|
||
|
||
static PrimeGenerationContext *probprime_new_context(
|
||
const PrimeGenerationPolicy *policy)
|
||
{
|
||
PrimeGenerationContext *ctx = snew(PrimeGenerationContext);
|
||
ctx->vt = policy;
|
||
return ctx;
|
||
}
|
||
|
||
static void probprime_free_context(PrimeGenerationContext *ctx)
|
||
{
|
||
sfree(ctx);
|
||
}
|
||
|
||
static ProgressPhase probprime_add_progress_phase(
|
||
const PrimeGenerationPolicy *policy,
|
||
ProgressReceiver *prog, unsigned bits)
|
||
{
|
||
/*
|
||
* The density of primes near x is 1/(log x). When x is about 2^b,
|
||
* that's 1/(b log 2).
|
||
*
|
||
* But we're only doing the expensive part of the process (the M-R
|
||
* checks) for a number that passes the initial winnowing test of
|
||
* having no factor less than 2^16 (at least, unless the prime is
|
||
* so small that PrimeCandidateSource gives up on that winnowing).
|
||
* The density of _those_ numbers is about 1/19.76. So the odds of
|
||
* hitting a prime per expensive attempt are boosted by a factor
|
||
* of 19.76.
|
||
*/
|
||
const double log_2 = 0.693147180559945309417232121458;
|
||
double winnow_factor = (bits < 32 ? 1.0 : 19.76);
|
||
double prob = winnow_factor / (bits * log_2);
|
||
|
||
/*
|
||
* Estimate the cost of prime generation as the cost of the M-R
|
||
* modexps.
|
||
*/
|
||
double cost = (miller_rabin_checks_needed(bits) *
|
||
estimate_modexp_cost(bits));
|
||
return progress_add_probabilistic(prog, cost, prob);
|
||
}
|
||
|
||
static mp_int *probprime_generate(
|
||
PrimeGenerationContext *ctx,
|
||
PrimeCandidateSource *pcs, ProgressReceiver *prog)
|
||
{
|
||
pcs_ready(pcs);
|
||
|
||
while (true) {
|
||
progress_report_attempt(prog);
|
||
|
||
mp_int *p = pcs_generate(pcs);
|
||
if (!p) {
|
||
pcs_free(pcs);
|
||
return NULL;
|
||
}
|
||
|
||
MillerRabin *mr = miller_rabin_new(p);
|
||
bool known_bad = false;
|
||
unsigned nchecks = miller_rabin_checks_needed(mp_get_nbits(p));
|
||
for (unsigned check = 0; check < nchecks; check++) {
|
||
if (!miller_rabin_test_random(mr)) {
|
||
known_bad = true;
|
||
break;
|
||
}
|
||
}
|
||
miller_rabin_free(mr);
|
||
|
||
if (!known_bad) {
|
||
/*
|
||
* We have a prime!
|
||
*/
|
||
pcs_free(pcs);
|
||
return p;
|
||
}
|
||
|
||
mp_free(p);
|
||
}
|
||
}
|
||
|
||
static strbuf *null_mpu_certificate(PrimeGenerationContext *ctx, mp_int *p)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
const PrimeGenerationPolicy primegen_probabilistic = {
|
||
probprime_add_progress_phase,
|
||
probprime_new_context,
|
||
probprime_free_context,
|
||
probprime_generate,
|
||
null_mpu_certificate,
|
||
};
|
||
|
||
/* ----------------------------------------------------------------------
|
||
* Alternative provable-prime algorithm, based on the following paper:
|
||
*
|
||
* [MAURER] Maurer, U.M. Fast generation of prime numbers and secure
|
||
* public-key cryptographic parameters. J. Cryptology 8, 123–155
|
||
* (1995). https://doi.org/10.1007/BF00202269
|
||
*/
|
||
|
||
typedef enum SubprimePolicy {
|
||
SPP_FAST,
|
||
SPP_MAURER_SIMPLE,
|
||
SPP_MAURER_COMPLEX,
|
||
} SubprimePolicy;
|
||
|
||
typedef struct ProvablePrimePolicyExtra {
|
||
SubprimePolicy spp;
|
||
} ProvablePrimePolicyExtra;
|
||
|
||
typedef struct ProvablePrimeContext ProvablePrimeContext;
|
||
struct ProvablePrimeContext {
|
||
Pockle *pockle;
|
||
PrimeGenerationContext pgc;
|
||
const ProvablePrimePolicyExtra *extra;
|
||
};
|
||
|
||
static PrimeGenerationContext *provableprime_new_context(
|
||
const PrimeGenerationPolicy *policy)
|
||
{
|
||
ProvablePrimeContext *ppc = snew(ProvablePrimeContext);
|
||
ppc->pgc.vt = policy;
|
||
ppc->pockle = pockle_new();
|
||
ppc->extra = policy->extra;
|
||
return &ppc->pgc;
|
||
}
|
||
|
||
static void provableprime_free_context(PrimeGenerationContext *ctx)
|
||
{
|
||
ProvablePrimeContext *ppc = container_of(ctx, ProvablePrimeContext, pgc);
|
||
pockle_free(ppc->pockle);
|
||
sfree(ppc);
|
||
}
|
||
|
||
static ProgressPhase provableprime_add_progress_phase(
|
||
const PrimeGenerationPolicy *policy,
|
||
ProgressReceiver *prog, unsigned bits)
|
||
{
|
||
/*
|
||
* Estimating the cost of making a _provable_ prime is difficult
|
||
* because of all the recursions to smaller sizes.
|
||
*
|
||
* Once you have enough factors of p-1 to certify primality of p,
|
||
* the remaining work in provable prime generation is not very
|
||
* different from probabilistic: you generate a random candidate,
|
||
* test its primality probabilistically, and use the witness value
|
||
* generated as a byproduct of that test for the full Pocklington
|
||
* verification. The expensive part, as usual, is made of modpows.
|
||
*
|
||
* The Pocklington test needs at least two modpows (one for the
|
||
* Fermat check, and one per known factor of p-1).
|
||
*
|
||
* The prior M-R step needs an unknown number, because we iterate
|
||
* until we find a value whose order is divisible by the largest
|
||
* power of 2 that divides p-1, say 2^j. That excludes half the
|
||
* possible witness values (specifically, the quadratic residues),
|
||
* so we expect to need on average two M-R operations to find one.
|
||
* But that's only if the number _is_ prime - as usual, it's also
|
||
* possible that we hit a non-prime and have to try again.
|
||
*
|
||
* So, if we were only estimating the cost of that final step, it
|
||
* would look a lot like the probabilistic version: we'd have to
|
||
* estimate the expected total number of modexps by knowing
|
||
* something about the density of primes among our candidate
|
||
* integers, and then multiply that by estimate_modexp_cost(bits).
|
||
* But the problem is that we also have to _find_ a smaller prime,
|
||
* so we have to recurse.
|
||
*
|
||
* In the MAURER_SIMPLE version of the algorithm, you recurse to
|
||
* any one of a range of possible smaller sizes i, each with
|
||
* probability proportional to 1/i. So your expected time to
|
||
* generate an n-bit prime is given by a horrible recurrence of
|
||
* the form E_n = S_n + (sum E_i/i) / (sum 1/i), in which S_n is
|
||
* the expected cost of the final step once you have your smaller
|
||
* primes, and both sums are over ceil(n/2) <= i <= n-20.
|
||
*
|
||
* At this point I ran out of effort to actually do the maths
|
||
* rigorously, so instead I did the empirical experiment of
|
||
* generating that sequence in Python and plotting it on a graph.
|
||
* My Python code is here, in case I need it again:
|
||
|
||
from math import log
|
||
|
||
alpha = log(3)/log(2) + 1 # exponent for modexp using Karatsuba mult
|
||
|
||
E = [1] * 16 # assume generating tiny primes is trivial
|
||
|
||
for n in range(len(E), 4096):
|
||
|
||
# Expected time for sub-generations, as a weighted mean of prior
|
||
# values of the same sequence.
|
||
lo = (n+1)//2
|
||
hi = n-20
|
||
if lo <= hi:
|
||
subrange = range(lo, hi+1)
|
||
num = sum(E[i]/i for i in subrange)
|
||
den = sum(1/i for i in subrange)
|
||
else:
|
||
num, den = 0, 1
|
||
|
||
# Constant term (cost of final step).
|
||
# Similar to probprime_add_progress_phase.
|
||
winnow_factor = 1 if n < 32 else 19.76
|
||
prob = winnow_factor / (n * log(2))
|
||
cost = 4 * n**alpha / prob
|
||
|
||
E.append(cost + num / den)
|
||
|
||
for i, p in enumerate(E):
|
||
try:
|
||
print(log(i), log(p))
|
||
except ValueError:
|
||
continue
|
||
|
||
* The output loop prints the logs of both i and E_i, so that when
|
||
* I plot the resulting data file in gnuplot I get a log-log
|
||
* diagram. That showed me some early noise and then a very
|
||
* straight-looking line; feeding the straight part of the graph
|
||
* to linear-regression analysis reported that it fits the line
|
||
*
|
||
* log E_n = -1.7901825337965498 + 3.6199197179662517 * log(n)
|
||
* => E_n = 0.16692969657466802 * n^3.6199197179662517
|
||
*
|
||
* So my somewhat empirical estimate is that Maurer prime
|
||
* generation costs about 0.167 * bits^3.62, in the same arbitrary
|
||
* time units used by estimate_modexp_cost.
|
||
*/
|
||
|
||
return progress_add_linear(prog, 0.167 * pow(bits, 3.62));
|
||
}
|
||
|
||
static mp_int *primegen_small(Pockle *pockle, PrimeCandidateSource *pcs)
|
||
{
|
||
assert(pcs_get_bits(pcs) <= 32);
|
||
|
||
pcs_ready(pcs);
|
||
|
||
while (true) {
|
||
mp_int *p = pcs_generate(pcs);
|
||
if (!p) {
|
||
pcs_free(pcs);
|
||
return NULL;
|
||
}
|
||
if (pockle_add_small_prime(pockle, p) == POCKLE_OK) {
|
||
pcs_free(pcs);
|
||
return p;
|
||
}
|
||
mp_free(p);
|
||
}
|
||
}
|
||
|
||
#ifdef DEBUG_PRIMEGEN
|
||
static void timestamp(FILE *fp)
|
||
{
|
||
struct timespec ts;
|
||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||
fprintf(fp, "%lu.%09lu: ", (unsigned long)ts.tv_sec,
|
||
(unsigned long)ts.tv_nsec);
|
||
}
|
||
static PRINTF_LIKE(1, 2) void debug_f(const char *fmt, ...)
|
||
{
|
||
va_list ap;
|
||
va_start(ap, fmt);
|
||
timestamp(stderr);
|
||
vfprintf(stderr, fmt, ap);
|
||
fputc('\n', stderr);
|
||
va_end(ap);
|
||
}
|
||
static void debug_f_mp(const char *fmt, mp_int *x, ...)
|
||
{
|
||
va_list ap;
|
||
va_start(ap, x);
|
||
timestamp(stderr);
|
||
vfprintf(stderr, fmt, ap);
|
||
mp_dump(stderr, "", x, "\n");
|
||
va_end(ap);
|
||
}
|
||
#else
|
||
#define debug_f(...) ((void)0)
|
||
#define debug_f_mp(...) ((void)0)
|
||
#endif
|
||
|
||
static double uniform_random_double(void)
|
||
{
|
||
unsigned char randbuf[8];
|
||
random_read(randbuf, 8);
|
||
return GET_64BIT_MSB_FIRST(randbuf) * 0x1.0p-64;
|
||
}
|
||
|
||
static mp_int *mp_ceil_div(mp_int *n, mp_int *d)
|
||
{
|
||
mp_int *nplus = mp_add(n, d);
|
||
mp_sub_integer_into(nplus, nplus, 1);
|
||
mp_int *toret = mp_div(nplus, d);
|
||
mp_free(nplus);
|
||
return toret;
|
||
}
|
||
|
||
static mp_int *provableprime_generate_inner(
|
||
ProvablePrimeContext *ppc, PrimeCandidateSource *pcs,
|
||
ProgressReceiver *prog, double progress_origin, double progress_scale)
|
||
{
|
||
unsigned bits = pcs_get_bits(pcs);
|
||
assert(bits > 1);
|
||
|
||
if (bits <= 32) {
|
||
debug_f("ppgi(%u) -> small", bits);
|
||
return primegen_small(ppc->pockle, pcs);
|
||
}
|
||
|
||
unsigned min_bits_needed, max_bits_needed;
|
||
{
|
||
/*
|
||
* Find the product of all the prime factors we already know
|
||
* about.
|
||
*/
|
||
mp_int *size_got = mp_from_integer(1);
|
||
size_t nfactors;
|
||
mp_int **factors = pcs_get_known_prime_factors(pcs, &nfactors);
|
||
for (size_t i = 0; i < nfactors; i++) {
|
||
mp_int *to_free = size_got;
|
||
size_got = mp_unsafe_shrink(mp_mul(size_got, factors[i]));
|
||
mp_free(to_free);
|
||
}
|
||
|
||
/*
|
||
* Find the largest cofactor we might be able to use, and the
|
||
* smallest one we can get away with.
|
||
*/
|
||
mp_int *upperbound = pcs_get_upper_bound(pcs);
|
||
mp_int *size_needed = mp_nthroot(upperbound, 3, NULL);
|
||
debug_f_mp("upperbound = ", upperbound);
|
||
{
|
||
mp_int *to_free = upperbound;
|
||
upperbound = mp_unsafe_shrink(mp_div(upperbound, size_got));
|
||
mp_free(to_free);
|
||
}
|
||
debug_f_mp("size_needed = ", size_needed);
|
||
{
|
||
mp_int *to_free = size_needed;
|
||
size_needed = mp_unsafe_shrink(mp_ceil_div(size_needed, size_got));
|
||
mp_free(to_free);
|
||
}
|
||
|
||
max_bits_needed = pcs_get_bits_remaining(pcs);
|
||
|
||
/*
|
||
* We need a prime that is greater than or equal to
|
||
* 'size_needed' in order for the product of all our known
|
||
* factors of p-1 to exceed the cube root of the largest value
|
||
* p might take.
|
||
*
|
||
* Since pcs_new wants a size specified in bits, we must count
|
||
* the bits in size_needed and then add 1. Otherwise we might
|
||
* get a value with the same bit count as size_needed but
|
||
* slightly smaller than it.
|
||
*
|
||
* An exception is if size_needed = 1. In that case the
|
||
* product of existing known factors is _already_ enough, so
|
||
* we don't need to generate an extra factor at all.
|
||
*/
|
||
if (mp_hs_integer(size_needed, 2)) {
|
||
min_bits_needed = mp_get_nbits(size_needed) + 1;
|
||
} else {
|
||
min_bits_needed = 0;
|
||
}
|
||
|
||
mp_free(upperbound);
|
||
mp_free(size_needed);
|
||
mp_free(size_got);
|
||
}
|
||
|
||
double progress = 0.0;
|
||
|
||
if (min_bits_needed) {
|
||
debug_f("ppgi(%u) recursing, need [%u,%u] more bits",
|
||
bits, min_bits_needed, max_bits_needed);
|
||
|
||
unsigned *sizes = NULL;
|
||
size_t nsizes = 0, sizesize = 0;
|
||
|
||
unsigned real_min = max_bits_needed / 2;
|
||
unsigned real_max = (max_bits_needed >= 20 ?
|
||
max_bits_needed - 20 : 0);
|
||
if (real_min < min_bits_needed)
|
||
real_min = min_bits_needed;
|
||
if (real_max < real_min)
|
||
real_max = real_min;
|
||
debug_f("ppgi(%u) revised bits interval = [%u,%u]",
|
||
bits, real_min, real_max);
|
||
|
||
switch (ppc->extra->spp) {
|
||
case SPP_FAST:
|
||
/*
|
||
* Always pick the smallest subsidiary prime we can get
|
||
* away with: just over n/3 bits.
|
||
*
|
||
* This is not a good mode for cryptographic prime
|
||
* generation, because it skews the distribution of primes
|
||
* greatly, and worse, it skews them in a direction that
|
||
* heads away from the properties crypto algorithms tend
|
||
* to like.
|
||
*
|
||
* (For both discrete-log systems and RSA, people have
|
||
* tended to recommend in the past that p-1 should have a
|
||
* _large_ factor if possible. There's some disagreement
|
||
* on which algorithms this is really necessary for, but
|
||
* certainly I've never seen anyone recommend arranging a
|
||
* _small_ factor on purpose.)
|
||
*
|
||
* I originally implemented this mode because it was
|
||
* convenient for debugging - it wastes as little time as
|
||
* possible on finding a sub-prime and lets you get to the
|
||
* interesting part! And I leave it in the code because it
|
||
* might still be useful for _something_. Because it's
|
||
* cryptographically questionable, it's not selectable in
|
||
* the UI of either version of PuTTYgen proper; but it can
|
||
* be accessed through testcrypt, and if for some reason a
|
||
* definite prime is needed for non-crypto purposes, it
|
||
* may still be the fastest way to put your hands on one.
|
||
*/
|
||
debug_f("ppgi(%u) fast mode, just ask for %u bits",
|
||
bits, min_bits_needed);
|
||
sgrowarray(sizes, sizesize, nsizes);
|
||
sizes[nsizes++] = min_bits_needed;
|
||
break;
|
||
case SPP_MAURER_SIMPLE: {
|
||
/*
|
||
* Select the size of the subsidiary prime at random from
|
||
* sqrt(outputprime) up to outputprime/2^20, in such a way
|
||
* that the probability distribution matches that of the
|
||
* largest prime factor of a random n-bit number.
|
||
*
|
||
* Per [MAURER] section 3.4, the cumulative distribution
|
||
* function of this relative size is 1+log2(x), for x in
|
||
* [1/2,1]. You can generate a value from the distribution
|
||
* given by a cdf by applying the inverse cdf to a uniform
|
||
* value in [0,1]. Simplifying that in this case, what we
|
||
* have to do is raise 2 to the power of a random real
|
||
* number between -1 and 0. (And that gives you the number
|
||
* of _bits_ in the sub-prime, as a factor of the desired
|
||
* output number of bits.)
|
||
*
|
||
* We also require that the subsidiary prime q is at least
|
||
* 20 bits smaller than the output one, to give us a
|
||
* fighting chance of there being _any_ prime we can find
|
||
* such that q | p-1.
|
||
*
|
||
* (But these rules have to be applied in an order that
|
||
* still leaves us _some_ interval of possible sizes we
|
||
* can pick!)
|
||
*/
|
||
maurer_simple:
|
||
debug_f("ppgi(%u) Maurer simple mode", bits);
|
||
|
||
unsigned sub_bits;
|
||
do {
|
||
double uniform = uniform_random_double();
|
||
sub_bits = real_max * pow(2.0, uniform - 1) + 0.5;
|
||
debug_f(" ... %.6f -> %u?", uniform, sub_bits);
|
||
} while (!(real_min <= sub_bits && sub_bits <= real_max));
|
||
|
||
debug_f("ppgi(%u) asking for %u bits", bits, sub_bits);
|
||
sgrowarray(sizes, sizesize, nsizes);
|
||
sizes[nsizes++] = sub_bits;
|
||
|
||
break;
|
||
}
|
||
case SPP_MAURER_COMPLEX: {
|
||
/*
|
||
* In this mode, we may generate multiple factors of p-1
|
||
* which between them add up to at least n/2 bits, in such
|
||
* a way that those are guaranteed to be the largest
|
||
* factors of p-1 and that they have the same probability
|
||
* distribution as the largest k factors would have in a
|
||
* random integer. The idea is that this more elaborate
|
||
* procedure gets as close as possible to the same
|
||
* probability distribution you'd get by selecting a
|
||
* completely random prime (if you feasibly could).
|
||
*
|
||
* Algorithm from Appendix 1 of [MAURER]: we generate
|
||
* random real numbers that sum to at most 1, by choosing
|
||
* each one uniformly from the range [0, 1 - sum of all
|
||
* the previous ones]. We maintain them in a list in
|
||
* decreasing order, and we stop as soon as we find an
|
||
* initial subsequence of the list s_1,...,s_r such that
|
||
* s_1 + ... + s_{r-1} + 2 s_r > 1. In particular, this
|
||
* guarantees that the sum of that initial subsequence is
|
||
* at least 1/2, so we end up with enough factors to
|
||
* satisfy Pocklington.
|
||
*/
|
||
|
||
if (max_bits_needed / 2 + 1 > real_max) {
|
||
/* Early exit path in the case where this algorithm
|
||
* can't possibly generate a value in the range we
|
||
* need. In that situation, fall back to Maurer
|
||
* simple. */
|
||
debug_f("ppgi(%u) skipping GenerateSizeList, "
|
||
"real_max too small", bits);
|
||
goto maurer_simple; /* sorry! */
|
||
}
|
||
|
||
double *s = NULL;
|
||
size_t ns, ssize = 0;
|
||
|
||
while (true) {
|
||
debug_f("ppgi(%u) starting GenerateSizeList", bits);
|
||
ns = 0;
|
||
double range = 1.0;
|
||
while (true) {
|
||
/* Generate the next number */
|
||
double u = uniform_random_double() * range;
|
||
range -= u;
|
||
debug_f(" u_%"SIZEu" = %g", ns, u);
|
||
|
||
/* Insert it in the list */
|
||
sgrowarray(s, ssize, ns);
|
||
size_t i;
|
||
for (i = ns; i > 0 && s[i-1] < u; i--)
|
||
s[i] = s[i-1];
|
||
s[i] = u;
|
||
ns++;
|
||
debug_f(" inserting as s[%"SIZEu"]", i);
|
||
|
||
/* Look for a suitable initial subsequence */
|
||
double sum = 0;
|
||
for (i = 0; i < ns; i++) {
|
||
sum += s[i];
|
||
if (sum + s[i] > 1.0) {
|
||
debug_f(" s[0..%"SIZEu"] works!", i);
|
||
|
||
/* Truncate the sequence here, and stop
|
||
* generating random real numbers. */
|
||
ns = i+1;
|
||
goto got_list;
|
||
}
|
||
}
|
||
}
|
||
|
||
got_list:;
|
||
/*
|
||
* Now translate those real numbers into actual bit
|
||
* counts, and do a last-minute check to make sure
|
||
* their product is going to be in range.
|
||
*
|
||
* We have to check both the min and max sizes of the
|
||
* total. A b-bit number is in [2^{b-1},2^b). So the
|
||
* product of numbers of sizes b_1,...,b_k is at least
|
||
* 2^{\sum (b_i-1)}, and less than 2^{\sum b_i}.
|
||
*/
|
||
nsizes = 0;
|
||
|
||
unsigned min_total = 0, max_total = 0;
|
||
|
||
for (size_t i = 0; i < ns; i++) {
|
||
/* These sizes are measured in actual entropy, so
|
||
* add 1 bit each time to account for the
|
||
* zero-information leading 1 */
|
||
unsigned this_size = max_bits_needed * s[i] + 1;
|
||
debug_f(" bits[%"SIZEu"] = %u", i, this_size);
|
||
sgrowarray(sizes, sizesize, nsizes);
|
||
sizes[nsizes++] = this_size;
|
||
|
||
min_total += this_size - 1;
|
||
max_total += this_size;
|
||
}
|
||
|
||
debug_f(" total bits = [%u,%u)", min_total, max_total);
|
||
if (min_total < real_min || max_total > real_max+1) {
|
||
debug_f(" total out of range, try again");
|
||
} else {
|
||
debug_f(" success! %"SIZEu" sub-primes totalling [%u,%u) "
|
||
"bits", nsizes, min_total, max_total);
|
||
break;
|
||
}
|
||
}
|
||
|
||
smemclr(s, ssize * sizeof(*s));
|
||
sfree(s);
|
||
break;
|
||
}
|
||
default:
|
||
unreachable("bad subprime policy");
|
||
}
|
||
|
||
for (size_t i = 0; i < nsizes; i++) {
|
||
unsigned sub_bits = sizes[i];
|
||
double progress_in_this_prime = (double)sub_bits / bits;
|
||
mp_int *q = provableprime_generate_inner(
|
||
ppc, pcs_new(sub_bits),
|
||
prog, progress_origin + progress_scale * progress,
|
||
progress_scale * progress_in_this_prime);
|
||
progress += progress_in_this_prime;
|
||
assert(q);
|
||
debug_f_mp("ppgi(%u) got factor ", q, bits);
|
||
pcs_require_residue_1_mod_prime(pcs, q);
|
||
mp_free(q);
|
||
}
|
||
|
||
smemclr(sizes, sizesize * sizeof(*sizes));
|
||
sfree(sizes);
|
||
} else {
|
||
debug_f("ppgi(%u) no need to recurse", bits);
|
||
}
|
||
|
||
debug_f("ppgi(%u) ready, %u bits remaining",
|
||
bits, pcs_get_bits_remaining(pcs));
|
||
pcs_ready(pcs);
|
||
|
||
while (true) {
|
||
mp_int *p = pcs_generate(pcs);
|
||
if (!p) {
|
||
pcs_free(pcs);
|
||
return NULL;
|
||
}
|
||
|
||
debug_f_mp("provable_step p=", p);
|
||
|
||
MillerRabin *mr = miller_rabin_new(p);
|
||
debug_f("provable_step mr setup done");
|
||
mp_int *witness = miller_rabin_find_potential_primitive_root(mr);
|
||
miller_rabin_free(mr);
|
||
|
||
if (!witness) {
|
||
debug_f("provable_step mr failed");
|
||
mp_free(p);
|
||
continue;
|
||
}
|
||
|
||
size_t nfactors;
|
||
mp_int **factors = pcs_get_known_prime_factors(pcs, &nfactors);
|
||
PockleStatus st = pockle_add_prime(
|
||
ppc->pockle, p, factors, nfactors, witness);
|
||
|
||
if (st != POCKLE_OK) {
|
||
debug_f("provable_step proof failed %d", (int)st);
|
||
|
||
/*
|
||
* Check by assertion that the error status is not one of
|
||
* the ones we ought to have ruled out already by
|
||
* construction. If there's a bug in this code that means
|
||
* we can _never_ pass this test (e.g. picking products of
|
||
* factors that never quite reach cbrt(n)), we'd rather
|
||
* fail an assertion than loop forever.
|
||
*/
|
||
assert(st == POCKLE_DISCRIMINANT_IS_SQUARE ||
|
||
st == POCKLE_WITNESS_POWER_IS_1 ||
|
||
st == POCKLE_WITNESS_POWER_NOT_COPRIME);
|
||
|
||
mp_free(p);
|
||
if (witness)
|
||
mp_free(witness);
|
||
continue;
|
||
}
|
||
|
||
mp_free(witness);
|
||
pcs_free(pcs);
|
||
debug_f_mp("ppgi(%u) done, got ", p, bits);
|
||
progress_report(prog, progress_origin + progress_scale);
|
||
return p;
|
||
}
|
||
}
|
||
|
||
static mp_int *provableprime_generate(
|
||
PrimeGenerationContext *ctx,
|
||
PrimeCandidateSource *pcs, ProgressReceiver *prog)
|
||
{
|
||
ProvablePrimeContext *ppc = container_of(ctx, ProvablePrimeContext, pgc);
|
||
mp_int *p = provableprime_generate_inner(ppc, pcs, prog, 0.0, 1.0);
|
||
|
||
return p;
|
||
}
|
||
|
||
static inline strbuf *provableprime_mpu_certificate(
|
||
PrimeGenerationContext *ctx, mp_int *p)
|
||
{
|
||
ProvablePrimeContext *ppc = container_of(ctx, ProvablePrimeContext, pgc);
|
||
return pockle_mpu(ppc->pockle, p);
|
||
}
|
||
|
||
#define DECLARE_POLICY(name, policy) \
|
||
static const struct ProvablePrimePolicyExtra \
|
||
pppextra_##name = {policy}; \
|
||
const PrimeGenerationPolicy name = { \
|
||
provableprime_add_progress_phase, \
|
||
provableprime_new_context, \
|
||
provableprime_free_context, \
|
||
provableprime_generate, \
|
||
provableprime_mpu_certificate, \
|
||
&pppextra_##name, \
|
||
}
|
||
|
||
DECLARE_POLICY(primegen_provable_fast, SPP_FAST);
|
||
DECLARE_POLICY(primegen_provable_maurer_simple, SPP_MAURER_SIMPLE);
|
||
DECLARE_POLICY(primegen_provable_maurer_complex, SPP_MAURER_COMPLEX);
|
||
|
||
/* ----------------------------------------------------------------------
|
||
* Reusable null implementation of the progress-reporting API.
|
||
*/
|
||
|
||
static inline ProgressPhase null_progress_add(void) {
|
||
ProgressPhase ph = { .n = 0 };
|
||
return ph;
|
||
}
|
||
ProgressPhase null_progress_add_linear(
|
||
ProgressReceiver *prog, double c) { return null_progress_add(); }
|
||
ProgressPhase null_progress_add_probabilistic(
|
||
ProgressReceiver *prog, double c, double p) { return null_progress_add(); }
|
||
void null_progress_ready(ProgressReceiver *prog) {}
|
||
void null_progress_start_phase(ProgressReceiver *prog, ProgressPhase phase) {}
|
||
void null_progress_report(ProgressReceiver *prog, double progress) {}
|
||
void null_progress_report_attempt(ProgressReceiver *prog) {}
|
||
void null_progress_report_phase_complete(ProgressReceiver *prog) {}
|
||
const ProgressReceiverVtable null_progress_vt = {
|
||
.add_linear = null_progress_add_linear,
|
||
.add_probabilistic = null_progress_add_probabilistic,
|
||
.ready = null_progress_ready,
|
||
.start_phase = null_progress_start_phase,
|
||
.report = null_progress_report,
|
||
.report_attempt = null_progress_report_attempt,
|
||
.report_phase_complete = null_progress_report_phase_complete,
|
||
};
|
||
|
||
/* ----------------------------------------------------------------------
|
||
* Helper function for progress estimation.
|
||
*/
|
||
|
||
double estimate_modexp_cost(unsigned bits)
|
||
{
|
||
/*
|
||
* A modexp of n bits goes roughly like O(n^2.58), on the grounds
|
||
* that our modmul is O(n^1.58) (Karatsuba) and you need O(n) of
|
||
* them in a modexp.
|
||
*/
|
||
return pow(bits, 2.58);
|
||
}
|