From bf3aa818e490245622555a37d2f09093a85bfe50 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 2 Mar 2020 18:49:07 +0000 Subject: [PATCH] Fix occasional hang in SPP_MAURER_COMPLEX logic. I generated a list of sizes in bits for factors of p-1, knowing a range of bit sizes that I wanted their product to fall in. But I forgot that when you multiply together two or more numbers of particular bit sizes, you can get more than one possible bit size back. My code was estimating at the low end of the possible range, so sometimes it would end up with more bits of the output prime specified than it expected, and be left without enough variable bits to actually be able to find a prime somewhere in the remaining space. Now when I'm planning the factor list, I compute both the min and max sizes of the product of the factors, and abort if any part of the possible range is outside the safe zone. --- sshprime.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/sshprime.c b/sshprime.c index 30ad4b14..75c4cba9 100644 --- a/sshprime.c +++ b/sshprime.c @@ -556,13 +556,17 @@ static mp_int *provableprime_generate_inner( got_list:; /* * Now translate those real numbers into actual bit - * counts, and do a last-minute check to make sure we - * haven't generated one too close to the final output - * size. + * 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 total = 1; /* account for leading 1 */ + unsigned min_total = 0, max_total = 0; for (size_t i = 0; i < ns; i++) { /* These sizes are measured in actual entropy, so @@ -573,15 +577,16 @@ static mp_int *provableprime_generate_inner( sgrowarray(sizes, sizesize, nsizes); sizes[nsizes++] = this_size; - total += this_size - 1; + min_total += this_size - 1; + max_total += this_size; } - debug_f(" total bits = %u", total); - if (total < real_min || total > real_max) { + 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 bits", - nsizes, total); + debug_f(" success! %"SIZEu" sub-primes totalling [%u,%u) " + "bits", nsizes, min_total, max_total); break; } }