diff --git a/Recipe b/Recipe index 51b8c21c..7d6de75f 100644 --- a/Recipe +++ b/Recipe @@ -282,7 +282,7 @@ UXSSH = SSH uxnoise uxagentc uxgss uxshare SFTP = psftpcommon sftp sftpcommon logging cmdline # Components of the prime-generation system. -SSHPRIME = sshprime smallprimes primecandidate millerrabin mpunsafe +SSHPRIME = sshprime smallprimes primecandidate millerrabin pockle mpunsafe # Miscellaneous objects appearing in all the utilities, or all the # network ones, or the Unix or Windows subsets of those in turn. diff --git a/pockle.c b/pockle.c new file mode 100644 index 00000000..0aca8ecf --- /dev/null +++ b/pockle.c @@ -0,0 +1,343 @@ +#include +#include "ssh.h" +#include "sshkeygen.h" +#include "mpint.h" +#include "mpunsafe.h" +#include "tree234.h" + +struct Pockle { + tree234 *tree; + + mp_int **list; + size_t nlist, listsize; +}; + +static int mpcmp(void *av, void *bv) +{ + mp_int *a = (mp_int *)av, *b = (mp_int *)bv; + return mp_cmp_hs(a, b) - mp_cmp_hs(b, a); +} + +Pockle *pockle_new(void) +{ + Pockle *pockle = snew(Pockle); + pockle->tree = newtree234(mpcmp); + pockle->list = NULL; + pockle->nlist = pockle->listsize = 0; + return pockle; +} + +void pockle_free(Pockle *pockle) +{ + for (mp_int *mp; (mp = delpos234(pockle->tree, 0)) != NULL ;) + mp_free(mp); + freetree234(pockle->tree); + sfree(pockle->list); + sfree(pockle); +} + +static PockleStatus pockle_insert(Pockle *pockle, mp_int *p) +{ + mp_int *copy = mp_copy(p); + mp_int *found = add234(pockle->tree, copy); + if (copy != found) { + mp_free(copy); /* it was already in there */ + return POCKLE_OK; + } + sgrowarray(pockle->list, pockle->listsize, pockle->nlist); + pockle->list[pockle->nlist++] = copy; + return POCKLE_OK; +} + +size_t pockle_mark(Pockle *pockle) +{ + return pockle->nlist; +} + +void pockle_release(Pockle *pockle, size_t mark) +{ + while (pockle->nlist > mark) { + mp_int *val = pockle->list[--pockle->nlist]; + del234(pockle->tree, val); + mp_free(val); + } +} + +PockleStatus pockle_add_small_prime(Pockle *pockle, mp_int *p) +{ + if (mp_hs_integer(p, (1ULL << 32))) + return POCKLE_SMALL_PRIME_NOT_SMALL; + + uint32_t val = mp_get_integer(p); + + if (val < 2) + return POCKLE_PRIME_SMALLER_THAN_2; + + init_smallprimes(); + for (size_t i = 0; i < NSMALLPRIMES; i++) { + if (val == smallprimes[i]) + break; /* success */ + if (val % smallprimes[i] == 0) + return POCKLE_SMALL_PRIME_NOT_PRIME; + } + + return pockle_insert(pockle, p); +} + +PockleStatus pockle_add_prime(Pockle *pockle, mp_int *p, + mp_int **factors, size_t nfactors, + mp_int *witness) +{ + MontyContext *mc = NULL; + mp_int *x = NULL, *f = NULL, *w = NULL; + PockleStatus status; + + /* + * We're going to try to verify that p is prime by using + * Pocklington's theorem. The idea is that we're given w such that + * w^{p-1} == 1 (mod p) (1) + * and for a collection of primes q | p-1, + * w^{(p-1)/q} - 1 is coprime to p. (2) + * + * Suppose r is a prime factor of p itself. Consider the + * multiplicative order of w mod r. By (1), r | w^{p-1}-1. But by + * (2), r does not divide w^{(p-1)/q}-1. So the order of w mod r + * is a factor of p-1, but not a factor of (p-1)/q. Hence, the + * largest power of q that divides p-1 must also divide ord w. + * + * Repeating this reasoning for all q, we find that the product of + * all the q (which we'll denote f) must divide ord w, which in + * turn divides r-1. So f | r-1 for any r | p. + * + * In particular, this means f < r. That is, all primes r | p are + * bigger than f. So if f > sqrt(p), then we've shown p is prime, + * because otherwise it would have to be the product of at least + * two factors bigger than its own square root. + * + * With an extra check, we can also show p to be prime even if + * we're only given enough factors to make f > cbrt(p). See below + * for that part, when we come to it. + */ + + /* + * Start by checking p > 1. It certainly can't be prime otherwise! + * (And since we're going to prove it prime by showing all its + * prime factors are large, we do also have to know it _has_ at + * least one prime factor for that to tell us anything.) + */ + if (!mp_hs_integer(p, 2)) + return POCKLE_PRIME_SMALLER_THAN_2; + + /* + * Check that all the factors we've been given really are primes + * (in the sense that we already had them in our index). Make the + * product f, and check it really does divide p-1. + */ + x = mp_copy(p); + mp_sub_integer_into(x, x, 1); + f = mp_from_integer(1); + for (size_t i = 0; i < nfactors; i++) { + mp_int *q = factors[i]; + + if (!find234(pockle->tree, q, NULL)) { + status = POCKLE_FACTOR_NOT_KNOWN_PRIME; + goto out; + } + + mp_int *quotient = mp_new(mp_max_bits(x)); + mp_int *residue = mp_new(mp_max_bits(q)); + mp_divmod_into(x, q, quotient, residue); + + unsigned exact = mp_eq_integer(residue, 0); + mp_free(residue); + + mp_free(x); + x = quotient; + + if (!exact) { + status = POCKLE_FACTOR_NOT_A_FACTOR; + goto out; + } + + mp_int *tmp = f; + f = mp_unsafe_shrink(mp_mul(tmp, q)); + mp_free(tmp); + } + + /* + * Check that f > cbrt(p). + */ + mp_int *f2 = mp_mul(f, f); + mp_int *f3 = mp_mul(f2, f); + bool too_big = mp_cmp_hs(p, f3); + mp_free(f3); + mp_free(f2); + if (too_big) { + status = POCKLE_PRODUCT_OF_FACTORS_TOO_SMALL; + goto out; + } + + /* + * Now do the extra check that allows us to get away with only + * having f > cbrt(p) instead of f > sqrt(p). + * + * If we can show that f | r-1 for any r | p, then we've ruled out + * p being a product of _more_ than two primes (because then it + * would be the product of at least three things bigger than its + * own cube root). But we still have to rule out it being a + * product of exactly two. + * + * Suppose for the sake of contradiction that p is the product of + * two prime factors. We know both of those factors would have to + * be congruent to 1 mod f. So we'd have to have + * + * p = (uf+1)(vf+1) = (uv)f^2 + (u+v)f + 1 (3) + * + * We can't have uv >= f, or else that expression would come to at + * least f^3, i.e. it would exceed p. So uv < f. Hence, u,v < f as + * well. + * + * Can we have u+v >= f? If we did, then we could write v >= f-u, + * and hence f > uv >= u(f-u). That can be rearranged to show that + * u^2 > (u-1)f; decrementing the LHS makes the inequality no + * longer necessarily strict, so we have u^2-1 >= (u-1)f, and + * dividing off u-1 gives u+1 >= f. But we know u < f, so the only + * way this could happen would be if u=f-1, which makes v=1. But + * _then_ (3) gives us p = (f-1)f^2 + f^2 + 1 = f^3+1. But that + * can't be true if f^3 > p. So we can't have u+v >= f either, by + * contradiction. + * + * After all that, what have we shown? We've shown that we can + * write p = (uv)f^2 + (u+v)f + 1, with both uv and u+v strictly + * less than f. In other words, if you write down p in base f, it + * has exactly three digits, and they are uv, u+v and 1. + * + * But that means we can _find_ u and v: we know p and f, so we + * can just extract those digits of p's base-f representation. + * Once we've done so, they give the sum and product of the + * potential u,v. And given the sum and product of two numbers, + * you can make a quadratic which has those numbers as roots. + * + * We don't actually have to _solve_ the quadratic: all we have to + * do is check if its discriminant is a perfect square. If not, + * we'll know that no integers u,v can match this description. + */ + { + /* We already have x = (p-1)/f. So we just need to write x in + * the form aF + b, and then we have a=uv and b=u+v. */ + mp_int *a = mp_new(mp_max_bits(x)); + mp_int *b = mp_new(mp_max_bits(f)); + mp_divmod_into(x, f, a, b); + assert(!mp_cmp_hs(a, f)); + assert(!mp_cmp_hs(b, f)); + + /* If a=0, then that means p < f^2, so we don't need to do + * this check at all: the straightforward Pocklington theorem + * is all we need. */ + if (!mp_eq_integer(a, 0)) { + /* Compute the discriminant b^2 - 4a. */ + mp_int *bsq = mp_mul(b, b); + mp_lshift_fixed_into(a, a, 2); + mp_int *discriminant = mp_sub(bsq, a); + + /* See if it's a perfect square. */ + mp_int *remainder = mp_new(mp_max_bits(discriminant)); + mp_int *root = mp_nthroot(discriminant, 2, remainder); + unsigned perfect_square = mp_eq_integer(remainder, 0); + mp_free(bsq); + mp_free(discriminant); + mp_free(root); + mp_free(remainder); + + if (perfect_square) { + mp_free(b); + mp_free(a); + status = POCKLE_DISCRIMINANT_IS_SQUARE; + goto out; + } + } + mp_free(b); + mp_free(a); + } + + /* + * Now we've done all the checks that are cheaper than a modpow, + * so we've ruled out as many things as possible before having to + * do any hard work. But there's nothing for it now: make a + * MontyContext. + */ + mc = monty_new(p); + w = monty_import(mc, witness); + + /* + * The initial Fermat check: is w^{p-1} itself congruent to 1 mod + * p? + */ + { + mp_int *pm1 = mp_copy(p); + mp_sub_integer_into(pm1, pm1, 1); + mp_int *power = monty_pow(mc, w, pm1); + unsigned fermat_pass = mp_cmp_eq(power, monty_identity(mc)); + mp_free(power); + mp_free(pm1); + + if (!fermat_pass) { + status = POCKLE_FERMAT_TEST_FAILED; + goto out; + } + } + + /* + * And now, for each factor q, is w^{(p-1)/q}-1 coprime to p? + */ + for (size_t i = 0; i < nfactors; i++) { + mp_int *q = factors[i]; + mp_int *exponent = mp_unsafe_shrink(mp_div(p, q)); + mp_int *power = monty_pow(mc, w, exponent); + mp_int *power_extracted = monty_export(mc, power); + mp_sub_integer_into(power_extracted, power_extracted, 1); + + unsigned coprime = mp_coprime(power_extracted, p); + if (!coprime) { + /* + * If w^{(p-1)/q}-1 is not coprime to p, the test has + * failed. But it makes a difference why. If the power of + * w turned out to be 1, so that we took gcd(1-1,p) = + * gcd(0,p) = p, that's like an inconclusive Fermat or M-R + * test: it might just mean you picked a witness integer + * that wasn't a primitive root. But if the power is any + * _other_ value mod p that is not coprime to p, it means + * we've detected that the number is *actually not prime*! + */ + if (mp_eq_integer(power_extracted, 0)) + status = POCKLE_WITNESS_POWER_IS_1; + else + status = POCKLE_WITNESS_POWER_NOT_COPRIME; + } + + mp_free(exponent); + mp_free(power); + mp_free(power_extracted); + + if (!coprime) + goto out; /* with the status we set up above */ + } + + /* + * Success! p is prime. Insert it into our tree234 of known + * primes, so that future calls to this function can cite it in + * evidence of larger numbers' primality. + */ + status = pockle_insert(pockle, p); + + out: + if (x) + mp_free(x); + if (f) + mp_free(f); + if (w) + mp_free(w); + if (mc) + monty_free(mc); + return status; +} diff --git a/sshkeygen.h b/sshkeygen.h index 2565302a..cccb1fb2 100644 --- a/sshkeygen.h +++ b/sshkeygen.h @@ -92,6 +92,68 @@ unsigned miller_rabin_checks_needed(unsigned bits); * that proves the number to be composite. */ mp_int *miller_rabin_find_potential_primitive_root(MillerRabin *mr); +/* ---------------------------------------------------------------------- + * A system for proving numbers to be prime, using the Pocklington + * test, which requires knowing a partial factorisation of p-1 + * (specifically, factors whose product is at least cbrt(p)) and a + * primitive root. + * + * The API consists of instantiating a 'Pockle' object, which + * internally stores a list of numbers you've already convinced it is + * prime, and can accept further primes if you give a satisfactory + * certificate of their primality based on primes it already knows + * about. + */ + +typedef struct Pockle Pockle; + +/* In real use, you only really need to know whether the Pockle + * successfully accepted your prime. But for testcrypt, it's useful to + * expose many different failure modes so we can try to provoke them + * all in unit tests and check they're working. */ +#define POCKLE_STATUSES(X) \ + X(POCKLE_OK) \ + X(POCKLE_SMALL_PRIME_NOT_SMALL) \ + X(POCKLE_SMALL_PRIME_NOT_PRIME) \ + X(POCKLE_PRIME_SMALLER_THAN_2) \ + X(POCKLE_FACTOR_NOT_KNOWN_PRIME) \ + X(POCKLE_FACTOR_NOT_A_FACTOR) \ + X(POCKLE_PRODUCT_OF_FACTORS_TOO_SMALL) \ + X(POCKLE_FERMAT_TEST_FAILED) \ + X(POCKLE_DISCRIMINANT_IS_SQUARE) \ + X(POCKLE_WITNESS_POWER_IS_1) \ + X(POCKLE_WITNESS_POWER_NOT_COPRIME) \ + /* end of list */ + +#define DEFINE_ENUM(id) id, +typedef enum PockleStatus { POCKLE_STATUSES(DEFINE_ENUM) } PockleStatus; +#undef DEFINE_ENUM + +/* Make a new empty Pockle, containing no primes. */ +Pockle *pockle_new(void); + +/* Insert a prime below 2^32 into the Pockle. No evidence is required: + * Pockle will check it itself. */ +PockleStatus pockle_add_small_prime(Pockle *pockle, mp_int *p); + +/* Insert a general prime into the Pockle. You must provide a list of + * prime factors of p-1, whose product exceeds the cube root of p, and + * also a primitive root mod p. */ +PockleStatus pockle_add_prime(Pockle *pockle, mp_int *p, + mp_int **factors, size_t nfactors, + mp_int *primitive_root); + +/* If you call pockle_mark, and later pass the returned value to + * pockle_release, it will free all the primes that were added to the + * Pockle between those two calls. Useful in recursive algorithms, to + * stop the Pockle growing unboundedly if the recursion keeps having + * to backtrack. */ +size_t pockle_mark(Pockle *pockle); +void pockle_release(Pockle *pockle, size_t mark); + +/* Free a Pockle. */ +void pockle_free(Pockle *pockle); + /* ---------------------------------------------------------------------- * Callback API that allows key generation to report progress to its * caller. diff --git a/test/cryptsuite.py b/test/cryptsuite.py index 190324ef..225b69e4 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -970,6 +970,152 @@ class keygen(MyTestBase): for p in [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61]: self.assertNotEqual(n % p, 0) + def testPocklePositive(self): + def add_small(po, *ps): + for p in ps: + self.assertEqual(pockle_add_small_prime(po, p), 'POCKLE_OK') + def add(po, *args): + self.assertEqual(pockle_add_prime(po, *args), 'POCKLE_OK') + + # Transcription of the proof that 2^130-5 is prime from + # Theorem 3.1 from http://cr.yp.to/mac/poly1305-20050329.pdf + po = pockle_new() + p1 = (2**130 - 6) // 1517314646 + p2 = (p1 - 1) // 222890620702 + add_small(po, 37003, 221101) + add(po, p2, [37003, 221101], 2) + add(po, p1, [p2], 2) + add(po, 2**130 - 5, [p1], 2) + + # My own proof that 2^255-19 is prime + po = pockle_new() + p1 = 8574133 + p2 = 1919519569386763 + p3 = 75445702479781427272750846543864801 + p4 = (2**255 - 20) // (65147*12) + p = 2**255 - 19 + add_small(po, p1) + add(po, p2, [p1], 2) + add(po, p3, [p2], 2) + add(po, p4, [p3], 2) + add(po, p, [p4], 2) + + # And the prime used in Ed448, while I'm here + po = pockle_new() + p1 = 379979 + p2 = 1764234391 + p3 = 97859369123353 + p4 = 34741861125639557 + p5 = 36131535570665139281 + p6 = 167773885276849215533569 + p7 = 596242599987116128415063 + p = 2**448 - 2**224 - 1 + add_small(po, p1, p2) + add(po, p3, [p1], 2) + add(po, p4, [p2], 2) + add(po, p5, [p4], 2) + add(po, p6, [p3], 3) + add(po, p7, [p5], 3) + add(po, p, [p6, p7], 2) + + p = 4095744004479977 + factors = [2, 79999] # just enough factors to exceed cbrt(p) + po = pockle_new() + for q in factors: + add_small(po, q) + add(po, p, factors, 3) + + # The order of the generator in Ed25519 + po = pockle_new() + p1a, p1b = 132667, 137849 + p2 = 3044861653679985063343 + p3 = 198211423230930754013084525763697 + p = 2**252 + 0x14def9dea2f79cd65812631a5cf5d3ed + add_small(po, p1a, p1b) + add(po, p2, [p1a, p1b], 2) + add(po, p3, [p2], 2) + add(po, p, [p3], 2) + + # And the one in Ed448 + po = pockle_new() + p1 = 766223 + p2 = 3009341 + p3 = 7156907 + p4 = 671065561 + p5 = 342682509629 + p6 = 6730519843040614479184435237013 + p = 2**446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d + add_small(po, p1, p2, p3, p4) + add(po, p5, [p1], 2) + add(po, p6, [p3,p4], 2) + add(po, p, [p2,p5,p6], 2) + + def testPockleNegative(self): + def add_small(po, p): + self.assertEqual(pockle_add_small_prime(po, p), 'POCKLE_OK') + + po = pockle_new() + self.assertEqual(pockle_add_small_prime(po, 0), + 'POCKLE_PRIME_SMALLER_THAN_2') + self.assertEqual(pockle_add_small_prime(po, 1), + 'POCKLE_PRIME_SMALLER_THAN_2') + self.assertEqual(pockle_add_small_prime(po, 2**61 - 1), + 'POCKLE_SMALL_PRIME_NOT_SMALL') + self.assertEqual(pockle_add_small_prime(po, 4), + 'POCKLE_SMALL_PRIME_NOT_PRIME') + + po = pockle_new() + self.assertEqual(pockle_add_prime(po, 1919519569386763, [8574133], 2), + 'POCKLE_FACTOR_NOT_KNOWN_PRIME') + + po = pockle_new() + add_small(po, 8574133) + self.assertEqual(pockle_add_prime(po, 1919519569386765, [8574133], 2), + 'POCKLE_FACTOR_NOT_A_FACTOR') + + p = 4095744004479977 + factors = [2, 79997] # not quite enough factors to reach cbrt(p) + po = pockle_new() + for q in factors: + add_small(po, q) + self.assertEqual(pockle_add_prime(po, p, factors, 3), + 'POCKLE_PRODUCT_OF_FACTORS_TOO_SMALL') + + p = 1999527 * 3999053 + factors = [999763] + po = pockle_new() + for q in factors: + add_small(po, q) + self.assertEqual(pockle_add_prime(po, p, factors, 3), + 'POCKLE_DISCRIMINANT_IS_SQUARE') + + p = 9999929 * 9999931 + factors = [257, 2593] + po = pockle_new() + for q in factors: + add_small(po, q) + self.assertEqual(pockle_add_prime(po, p, factors, 3), + 'POCKLE_FERMAT_TEST_FAILED') + + p = 1713000920401 # a Carmichael number + po = pockle_new() + add_small(po, 561787) + self.assertEqual(pockle_add_prime(po, p, [561787], 2), + 'POCKLE_WITNESS_POWER_IS_1') + + p = 4294971121 + factors = [3, 5, 11, 17] + po = pockle_new() + for q in factors: + add_small(po, q) + self.assertEqual(pockle_add_prime(po, p, factors, 17), + 'POCKLE_WITNESS_POWER_NOT_COPRIME') + + po = pockle_new() + add_small(po, 2) + self.assertEqual(pockle_add_prime(po, 1, [2], 1), + 'POCKLE_PRIME_SMALLER_THAN_2') + class crypt(MyTestBase): def testSSH1Fingerprint(self): # Example key and reference fingerprint value generated by diff --git a/test/testcrypt.py b/test/testcrypt.py index de27ee38..5767f558 100644 --- a/test/testcrypt.py +++ b/test/testcrypt.py @@ -105,6 +105,7 @@ method_prefixes = { 'val_rsakex': 'ssh_rsakex_', 'val_prng': 'prng_', 'val_pcs': 'pcs_', + 'val_pockle': 'pockle_', } method_lists = {t: [] for t in method_prefixes} @@ -181,6 +182,13 @@ def make_argword(arg, argtype, fnname, argindex, to_preserve): arg = unicode_to_bytes(arg) if isinstance(arg, bytes) and b" " not in arg: return arg + if typename == "mpint_list": + sublist = [make_argword(len(arg), ("uint", False), + fnname, argindex, to_preserve)] + for val in arg: + sublist.append(make_argword(val, ("val_mpint", False), + fnname, argindex, to_preserve)) + return b" ".join(unicode_to_bytes(sub) for sub in sublist) raise TypeError( "Can't convert {}() argument {:d} to {} (value was {!r})".format( fnname, argindex, typename, arg)) @@ -227,6 +235,8 @@ def make_retval(rettype, word, unpack_strings): elif rettype == "boolean": assert word == b"true" or word == b"false" return word == b"true" + elif rettype == "pocklestatus": + return word.decode("ASCII") raise TypeError("Can't deal with return value {!r} of type {!r}" .format(word, rettype)) diff --git a/testcrypt.c b/testcrypt.c index c2c1e3cd..40108704 100644 --- a/testcrypt.c +++ b/testcrypt.c @@ -96,6 +96,7 @@ uint64_t prng_reseed_time_ms(void) X(keycomponents, key_components *, key_components_free(v)) \ X(pcs, PrimeCandidateSource *, pcs_free(v)) \ X(pgc, PrimeGenerationContext *, primegen_free_context(v)) \ + X(pockle, Pockle *, pockle_free(v)) \ /* end of list */ typedef struct Value Value; @@ -440,6 +441,11 @@ static void finaliser_return_value(strbuf *out, void *ctx) put_byte(out, '\n'); } +static void finaliser_sfree(strbuf *out, void *ctx) +{ + sfree(ctx); +} + #define VALTYPE_GETFN(n,t,f) \ static Value *unwrap_value_##n(Value *val) { \ ValueType expected = VT_##n; \ @@ -483,6 +489,26 @@ static mp_int **get_out_val_mpint(BinarySource *in) return &val->vu_mpint; } +struct mpint_list { + size_t n; + mp_int **integers; +}; + +static struct mpint_list get_mpint_list(BinarySource *in) +{ + size_t n = get_uint(in); + + struct mpint_list mpl; + mpl.n = n; + + mpl.integers = snewn(n, mp_int *); + for (size_t i = 0; i < n; i++) + mpl.integers[i] = get_val_mpint(in); + + add_finaliser(finaliser_sfree, mpl.integers); + return mpl; +} + static void finaliser_return_uint(strbuf *out, void *ctx) { unsigned *uval = (unsigned *)ctx; @@ -546,11 +572,6 @@ static const char **get_out_opt_val_string_asciz_const(BinarySource *in) return valp; } -static void finaliser_sfree(strbuf *out, void *ctx) -{ - sfree(ctx); -} - static BinarySource *get_val_string_binarysource(BinarySource *in) { strbuf *sb = get_val_string(in); @@ -588,6 +609,25 @@ static void return_boolean(strbuf *out, bool b) strbuf_catf(out, "%s\n", b ? "true" : "false"); } +static void return_pocklestatus(strbuf *out, PockleStatus status) +{ + switch (status) { + default: + strbuf_catf(out, "POCKLE_BAD_STATUS_VALUE\n"); + break; + +#define STATUS_CASE(id) \ + case id: \ + strbuf_catf(out, "%s\n", #id); \ + break; + + POCKLE_STATUSES(STATUS_CASE); + +#undef STATUS_CASE + + } +} + static void return_val_string_asciz_const(strbuf *out, const char *s) { strbuf *sb = strbuf_new(); @@ -1147,6 +1187,13 @@ mp_int *key_components_nth_mp(key_components *kc, size_t n) mp_copy(kc->components[n].mp)); } +PockleStatus pockle_add_prime_wrapper(Pockle *pockle, mp_int *p, + struct mpint_list mpl, mp_int *witness) +{ + return pockle_add_prime(pockle, p, mpl.integers, mpl.n, witness); +} +#define pockle_add_prime pockle_add_prime_wrapper + #define OPTIONAL_PTR_FUNC(type) \ typedef TD_val_##type TD_opt_val_##type; \ static TD_opt_val_##type get_opt_val_##type(BinarySource *in) { \ @@ -1179,6 +1226,8 @@ typedef const ssh_kex *TD_ecdh_alg; typedef RsaSsh1Order TD_rsaorder; typedef key_components *TD_keycomponents; typedef const PrimeGenerationPolicy *TD_primegenpolicy; +typedef struct mpint_list TD_mpint_list; +typedef PockleStatus TD_pocklestatus; #define FUNC0(rettype, function) \ static void handle_##function(BinarySource *in, strbuf *out) { \ diff --git a/testcrypt.h b/testcrypt.h index 1eca3759..89cbaadf 100644 --- a/testcrypt.h +++ b/testcrypt.h @@ -277,6 +277,11 @@ FUNC3(void, pcs_avoid_residue_small, val_pcs, uint, uint) 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) +FUNC0(val_pockle, pockle_new) +FUNC1(uint, pockle_mark, val_pockle) +FUNC2(void, pockle_release, val_pockle, uint) +FUNC2(pocklestatus, pockle_add_small_prime, val_pockle, val_mpint) +FUNC4(pocklestatus, pockle_add_prime, val_pockle, val_mpint, mpint_list, val_mpint) /* * Miscellaneous.