diff --git a/primecandidate.c b/primecandidate.c index cf4416f9..cf55919e 100644 --- a/primecandidate.c +++ b/primecandidate.c @@ -16,6 +16,7 @@ struct avoid { struct PrimeCandidateSource { unsigned bits; bool ready, try_sophie_germain; + bool one_shot, thrown_away_my_shot; /* We'll start by making up a random number strictly less than this ... */ mp_int *limit; @@ -48,6 +49,8 @@ PrimeCandidateSource *pcs_new_with_firstbits(unsigned bits, s->bits = bits; s->ready = false; s->try_sophie_germain = false; + s->one_shot = false; + s->thrown_away_my_shot = false; s->kps = NULL; s->nkps = s->kpsize = 0; @@ -103,6 +106,11 @@ void pcs_try_sophie_germain(PrimeCandidateSource *s) s->try_sophie_germain = true; } +void pcs_set_oneshot(PrimeCandidateSource *s) +{ + s->one_shot = true; +} + static void pcs_require_residue_inner(PrimeCandidateSource *s, mp_int *mod, mp_int *res) { @@ -360,6 +368,11 @@ void pcs_ready(PrimeCandidateSource *s) mp_int *pcs_generate(PrimeCandidateSource *s) { assert(s->ready); + if (s->one_shot) { + if (s->thrown_away_my_shot) + return NULL; + s->thrown_away_my_shot = true; + } while (true) { mp_int *x = mp_random_upto(s->limit); diff --git a/sshkeygen.h b/sshkeygen.h index 99e9ce76..0f0df587 100644 --- a/sshkeygen.h +++ b/sshkeygen.h @@ -54,6 +54,10 @@ void pcs_avoid_residue_small(PrimeCandidateSource *s, /* Exclude any prime that has no chance of being a Sophie Germain prime. */ void pcs_try_sophie_germain(PrimeCandidateSource *s); +/* Mark a PrimeCandidateSource as one-shot, so that the prime generation + * function will return NULL if an attempt fails, rather than looping. */ +void pcs_set_oneshot(PrimeCandidateSource *s); + /* Prepare a PrimeCandidateSource to actually generate numbers. This * function does last-minute computation that has to be delayed until * all constraints have been input. */ diff --git a/sshprime.c b/sshprime.c index 3b37aca0..c2ae94a2 100644 --- a/sshprime.c +++ b/sshprime.c @@ -75,6 +75,10 @@ static mp_int *probprime_generate( 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; @@ -259,6 +263,10 @@ static mp_int *primegen_small(Pockle *pockle, PrimeCandidateSource *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; @@ -627,6 +635,10 @@ static mp_int *provableprime_generate_inner( while (true) { mp_int *p = pcs_generate(pcs); + if (!p) { + pcs_free(pcs); + return NULL; + } debug_f_mp("provable_step p=", p); diff --git a/testcrypt.h b/testcrypt.h index 3040e0c6..1ed0c1c0 100644 --- a/testcrypt.h +++ b/testcrypt.h @@ -277,6 +277,7 @@ FUNC2(void, pcs_require_residue_1, val_pcs, val_mpint) FUNC2(void, pcs_require_residue_1_mod_prime, val_pcs, val_mpint) FUNC3(void, pcs_avoid_residue_small, val_pcs, uint, uint) FUNC1(void, pcs_try_sophie_germain, val_pcs) +FUNC1(void, pcs_set_oneshot, val_pcs) FUNC1(void, pcs_ready, val_pcs) FUNC4(void, pcs_inspect, val_pcs, out_val_mpint, out_val_mpint, out_val_mpint) FUNC1(val_mpint, pcs_generate, val_pcs)