1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

New 'Pockle' object, for verifying primality.

This implements an extended form of primality verification using
certificates based on Pocklington's theorem. You make a Pockle object,
and then try to convince it that one number after another is prime, by
means of providing it with a list of prime factors of p-1 and a
primitive root. (Or just by saying 'this prime is small enough for you
to check yourself'.)

Pocklington's theorem requires you to have factors of p-1 whose
product is at least the square root of p. I've extended that to
support factorisations only as big as the cube root, via an extension
of the theorem given in Maurer's paper on generating provable primes.

The Pockle object is more or less write-only: it has no methods for
reading out its contents. Its only output channel is the return value
when you try to insert a prime into it: if it isn't sufficiently
convinced that your prime is prime, it will return an error code. So
anything for which it returns POCKLE_OK you can be confident of.

I'm going to use this for provable prime generation. But exposing this
part of the system as an object in its own right means I can write a
set of unit tests for this specifically. My negative tests exercise
all the different ways a certification can be erroneous or inadequate;
the positive tests include proofs of primality of various primes used
in elliptic-curve crypto. The Poly1305 proof in particular is taken
from a proof in DJB's paper, which has exactly the form of a
Pocklington certificate only written in English.
This commit is contained in:
Simon Tatham 2020-02-23 15:16:30 +00:00
parent 20a9912c7c
commit 2be70baa0d
7 changed files with 621 additions and 6 deletions

2
Recipe
View File

@ -282,7 +282,7 @@ UXSSH = SSH uxnoise uxagentc uxgss uxshare
SFTP = psftpcommon sftp sftpcommon logging cmdline SFTP = psftpcommon sftp sftpcommon logging cmdline
# Components of the prime-generation system. # 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 # Miscellaneous objects appearing in all the utilities, or all the
# network ones, or the Unix or Windows subsets of those in turn. # network ones, or the Unix or Windows subsets of those in turn.

343
pockle.c Normal file
View File

@ -0,0 +1,343 @@
#include <assert.h>
#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;
}

View File

@ -92,6 +92,68 @@ unsigned miller_rabin_checks_needed(unsigned bits);
* that proves the number to be composite. */ * that proves the number to be composite. */
mp_int *miller_rabin_find_potential_primitive_root(MillerRabin *mr); 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 * Callback API that allows key generation to report progress to its
* caller. * caller.

View File

@ -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]: 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) 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): class crypt(MyTestBase):
def testSSH1Fingerprint(self): def testSSH1Fingerprint(self):
# Example key and reference fingerprint value generated by # Example key and reference fingerprint value generated by

View File

@ -105,6 +105,7 @@ method_prefixes = {
'val_rsakex': 'ssh_rsakex_', 'val_rsakex': 'ssh_rsakex_',
'val_prng': 'prng_', 'val_prng': 'prng_',
'val_pcs': 'pcs_', 'val_pcs': 'pcs_',
'val_pockle': 'pockle_',
} }
method_lists = {t: [] for t in method_prefixes} 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) arg = unicode_to_bytes(arg)
if isinstance(arg, bytes) and b" " not in arg: if isinstance(arg, bytes) and b" " not in arg:
return 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( raise TypeError(
"Can't convert {}() argument {:d} to {} (value was {!r})".format( "Can't convert {}() argument {:d} to {} (value was {!r})".format(
fnname, argindex, typename, arg)) fnname, argindex, typename, arg))
@ -227,6 +235,8 @@ def make_retval(rettype, word, unpack_strings):
elif rettype == "boolean": elif rettype == "boolean":
assert word == b"true" or word == b"false" assert word == b"true" or word == b"false"
return word == b"true" return word == b"true"
elif rettype == "pocklestatus":
return word.decode("ASCII")
raise TypeError("Can't deal with return value {!r} of type {!r}" raise TypeError("Can't deal with return value {!r} of type {!r}"
.format(word, rettype)) .format(word, rettype))

View File

@ -96,6 +96,7 @@ uint64_t prng_reseed_time_ms(void)
X(keycomponents, key_components *, key_components_free(v)) \ X(keycomponents, key_components *, key_components_free(v)) \
X(pcs, PrimeCandidateSource *, pcs_free(v)) \ X(pcs, PrimeCandidateSource *, pcs_free(v)) \
X(pgc, PrimeGenerationContext *, primegen_free_context(v)) \ X(pgc, PrimeGenerationContext *, primegen_free_context(v)) \
X(pockle, Pockle *, pockle_free(v)) \
/* end of list */ /* end of list */
typedef struct Value Value; typedef struct Value Value;
@ -440,6 +441,11 @@ static void finaliser_return_value(strbuf *out, void *ctx)
put_byte(out, '\n'); put_byte(out, '\n');
} }
static void finaliser_sfree(strbuf *out, void *ctx)
{
sfree(ctx);
}
#define VALTYPE_GETFN(n,t,f) \ #define VALTYPE_GETFN(n,t,f) \
static Value *unwrap_value_##n(Value *val) { \ static Value *unwrap_value_##n(Value *val) { \
ValueType expected = VT_##n; \ ValueType expected = VT_##n; \
@ -483,6 +489,26 @@ static mp_int **get_out_val_mpint(BinarySource *in)
return &val->vu_mpint; 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) static void finaliser_return_uint(strbuf *out, void *ctx)
{ {
unsigned *uval = (unsigned *)ctx; unsigned *uval = (unsigned *)ctx;
@ -546,11 +572,6 @@ static const char **get_out_opt_val_string_asciz_const(BinarySource *in)
return valp; return valp;
} }
static void finaliser_sfree(strbuf *out, void *ctx)
{
sfree(ctx);
}
static BinarySource *get_val_string_binarysource(BinarySource *in) static BinarySource *get_val_string_binarysource(BinarySource *in)
{ {
strbuf *sb = get_val_string(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"); 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) static void return_val_string_asciz_const(strbuf *out, const char *s)
{ {
strbuf *sb = strbuf_new(); 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)); 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) \ #define OPTIONAL_PTR_FUNC(type) \
typedef TD_val_##type TD_opt_val_##type; \ typedef TD_val_##type TD_opt_val_##type; \
static TD_opt_val_##type get_opt_val_##type(BinarySource *in) { \ 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 RsaSsh1Order TD_rsaorder;
typedef key_components *TD_keycomponents; typedef key_components *TD_keycomponents;
typedef const PrimeGenerationPolicy *TD_primegenpolicy; typedef const PrimeGenerationPolicy *TD_primegenpolicy;
typedef struct mpint_list TD_mpint_list;
typedef PockleStatus TD_pocklestatus;
#define FUNC0(rettype, function) \ #define FUNC0(rettype, function) \
static void handle_##function(BinarySource *in, strbuf *out) { \ static void handle_##function(BinarySource *in, strbuf *out) { \

View File

@ -277,6 +277,11 @@ FUNC3(void, pcs_avoid_residue_small, val_pcs, uint, uint)
FUNC1(void, pcs_ready, val_pcs) FUNC1(void, pcs_ready, val_pcs)
FUNC4(void, pcs_inspect, val_pcs, out_val_mpint, out_val_mpint, out_val_mpint) FUNC4(void, pcs_inspect, val_pcs, out_val_mpint, out_val_mpint, out_val_mpint)
FUNC1(val_mpint, pcs_generate, val_pcs) 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. * Miscellaneous.