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

265 lines
11 KiB
C
Raw Normal View History

/*
* sshkeygen.h: routines used internally to key generation.
*/
Refactor generation of candidate integers in primegen. I've replaced the random number generation and small delta-finding loop in primegen() with a much more elaborate system in its own source file, with unit tests and everything. Immediate benefits: - fixes a theoretical possibility of overflowing the target number of bits, if the random number was so close to the top of the range that the addition of delta * factor pushed it over. However, this only happened with negligible probability. - fixes a directional bias in delta-finding. The previous code incremented the number repeatedly until it found a value coprime to all the right things, which meant that a prime preceded by a particularly long sequence of numbers with tiny factors was more likely to be chosen. Now we select candidate delta values at random, that bias should be eliminated. - changes the semantics of the outermost primegen() function to make them easier to use, because now the caller specifies the 'bits' and 'firstbits' values for the actual returned prime, rather than having to account for the factor you're multiplying it by in DSA. DSA client code is correspondingly adjusted. Future benefits: - having the candidate generation in a separate function makes it easy to reuse in alternative prime generation strategies - the available constraints support applications such as Maurer's algorithm for generating provable primes, or strong primes for RSA in which both p-1 and p+1 have a large factor. So those become things we could experiment with in future.
2020-02-23 14:30:03 +00:00
/* ----------------------------------------------------------------------
* A table of all the primes that fit in a 16-bit integer. Call
* init_primes_array to make sure it's been initialised.
*/
#define NSMALLPRIMES 6542 /* number of primes < 65536 */
extern const unsigned short *const smallprimes;
void init_smallprimes(void);
Refactor generation of candidate integers in primegen. I've replaced the random number generation and small delta-finding loop in primegen() with a much more elaborate system in its own source file, with unit tests and everything. Immediate benefits: - fixes a theoretical possibility of overflowing the target number of bits, if the random number was so close to the top of the range that the addition of delta * factor pushed it over. However, this only happened with negligible probability. - fixes a directional bias in delta-finding. The previous code incremented the number repeatedly until it found a value coprime to all the right things, which meant that a prime preceded by a particularly long sequence of numbers with tiny factors was more likely to be chosen. Now we select candidate delta values at random, that bias should be eliminated. - changes the semantics of the outermost primegen() function to make them easier to use, because now the caller specifies the 'bits' and 'firstbits' values for the actual returned prime, rather than having to account for the factor you're multiplying it by in DSA. DSA client code is correspondingly adjusted. Future benefits: - having the candidate generation in a separate function makes it easy to reuse in alternative prime generation strategies - the available constraints support applications such as Maurer's algorithm for generating provable primes, or strong primes for RSA in which both p-1 and p+1 have a large factor. So those become things we could experiment with in future.
2020-02-23 14:30:03 +00:00
/* ----------------------------------------------------------------------
* A system for making up random candidate integers during prime
* generation. This unconditionally ensures that the numbers have the
* right number of bits and are not divisible by any prime in the
* smallprimes[] array above. It can also impose further constraints,
* as documented below.
*/
typedef struct PrimeCandidateSource PrimeCandidateSource;
/*
* pcs_new: you say how many bits you want the prime to have (with the
* usual semantics that an n-bit number is in the range [2^{n-1},2^n))
* and also optionally specify what you want its topmost 'nfirst' bits
* to be.
Refactor generation of candidate integers in primegen. I've replaced the random number generation and small delta-finding loop in primegen() with a much more elaborate system in its own source file, with unit tests and everything. Immediate benefits: - fixes a theoretical possibility of overflowing the target number of bits, if the random number was so close to the top of the range that the addition of delta * factor pushed it over. However, this only happened with negligible probability. - fixes a directional bias in delta-finding. The previous code incremented the number repeatedly until it found a value coprime to all the right things, which meant that a prime preceded by a particularly long sequence of numbers with tiny factors was more likely to be chosen. Now we select candidate delta values at random, that bias should be eliminated. - changes the semantics of the outermost primegen() function to make them easier to use, because now the caller specifies the 'bits' and 'firstbits' values for the actual returned prime, rather than having to account for the factor you're multiplying it by in DSA. DSA client code is correspondingly adjusted. Future benefits: - having the candidate generation in a separate function makes it easy to reuse in alternative prime generation strategies - the available constraints support applications such as Maurer's algorithm for generating provable primes, or strong primes for RSA in which both p-1 and p+1 have a large factor. So those become things we could experiment with in future.
2020-02-23 14:30:03 +00:00
*
* (The 'first' system is used for RSA keys, where you need to arrange
* that the product of your two primes is in a more tightly
* constrained range than the factor of 4 you'd get by just generating
* two (n/2)-bit primes and multiplying them.)
Refactor generation of candidate integers in primegen. I've replaced the random number generation and small delta-finding loop in primegen() with a much more elaborate system in its own source file, with unit tests and everything. Immediate benefits: - fixes a theoretical possibility of overflowing the target number of bits, if the random number was so close to the top of the range that the addition of delta * factor pushed it over. However, this only happened with negligible probability. - fixes a directional bias in delta-finding. The previous code incremented the number repeatedly until it found a value coprime to all the right things, which meant that a prime preceded by a particularly long sequence of numbers with tiny factors was more likely to be chosen. Now we select candidate delta values at random, that bias should be eliminated. - changes the semantics of the outermost primegen() function to make them easier to use, because now the caller specifies the 'bits' and 'firstbits' values for the actual returned prime, rather than having to account for the factor you're multiplying it by in DSA. DSA client code is correspondingly adjusted. Future benefits: - having the candidate generation in a separate function makes it easy to reuse in alternative prime generation strategies - the available constraints support applications such as Maurer's algorithm for generating provable primes, or strong primes for RSA in which both p-1 and p+1 have a large factor. So those become things we could experiment with in future.
2020-02-23 14:30:03 +00:00
*/
PrimeCandidateSource *pcs_new(unsigned bits);
PrimeCandidateSource *pcs_new_with_firstbits(unsigned bits,
unsigned first, unsigned nfirst);
Refactor generation of candidate integers in primegen. I've replaced the random number generation and small delta-finding loop in primegen() with a much more elaborate system in its own source file, with unit tests and everything. Immediate benefits: - fixes a theoretical possibility of overflowing the target number of bits, if the random number was so close to the top of the range that the addition of delta * factor pushed it over. However, this only happened with negligible probability. - fixes a directional bias in delta-finding. The previous code incremented the number repeatedly until it found a value coprime to all the right things, which meant that a prime preceded by a particularly long sequence of numbers with tiny factors was more likely to be chosen. Now we select candidate delta values at random, that bias should be eliminated. - changes the semantics of the outermost primegen() function to make them easier to use, because now the caller specifies the 'bits' and 'firstbits' values for the actual returned prime, rather than having to account for the factor you're multiplying it by in DSA. DSA client code is correspondingly adjusted. Future benefits: - having the candidate generation in a separate function makes it easy to reuse in alternative prime generation strategies - the available constraints support applications such as Maurer's algorithm for generating provable primes, or strong primes for RSA in which both p-1 and p+1 have a large factor. So those become things we could experiment with in future.
2020-02-23 14:30:03 +00:00
/* Insist that generated numbers must be congruent to 'res' mod 'mod' */
void pcs_require_residue(PrimeCandidateSource *s, mp_int *mod, mp_int *res);
/* Convenience wrapper for the common case where res = 1 */
void pcs_require_residue_1(PrimeCandidateSource *s, mp_int *mod);
/* Same as pcs_require_residue_1, but also records that the modulus is
* known to be prime */
void pcs_require_residue_1_mod_prime(PrimeCandidateSource *s, mp_int *mod);
Refactor generation of candidate integers in primegen. I've replaced the random number generation and small delta-finding loop in primegen() with a much more elaborate system in its own source file, with unit tests and everything. Immediate benefits: - fixes a theoretical possibility of overflowing the target number of bits, if the random number was so close to the top of the range that the addition of delta * factor pushed it over. However, this only happened with negligible probability. - fixes a directional bias in delta-finding. The previous code incremented the number repeatedly until it found a value coprime to all the right things, which meant that a prime preceded by a particularly long sequence of numbers with tiny factors was more likely to be chosen. Now we select candidate delta values at random, that bias should be eliminated. - changes the semantics of the outermost primegen() function to make them easier to use, because now the caller specifies the 'bits' and 'firstbits' values for the actual returned prime, rather than having to account for the factor you're multiplying it by in DSA. DSA client code is correspondingly adjusted. Future benefits: - having the candidate generation in a separate function makes it easy to reuse in alternative prime generation strategies - the available constraints support applications such as Maurer's algorithm for generating provable primes, or strong primes for RSA in which both p-1 and p+1 have a large factor. So those become things we could experiment with in future.
2020-02-23 14:30:03 +00:00
/* Insist that generated numbers must _not_ be congruent to 'res' mod
* 'mod'. This is used to avoid being 1 mod the RSA public exponent,
* which is small, so it only needs ordinary integer parameters. */
void pcs_avoid_residue_small(PrimeCandidateSource *s,
unsigned mod, unsigned res);
/* Prepare a PrimeCandidateSource to actually generate numbers. This
* function does last-minute computation that has to be delayed until
* all constraints have been input. */
void pcs_ready(PrimeCandidateSource *s);
/* Actually generate a candidate integer. You must free the result, of
* course. */
mp_int *pcs_generate(PrimeCandidateSource *s);
/* Free a PrimeCandidateSource. */
void pcs_free(PrimeCandidateSource *s);
/* Return some internal fields of the PCS. Used by testcrypt for
* unit-testing this system. */
void pcs_inspect(PrimeCandidateSource *pcs, mp_int **limit_out,
mp_int **factor_out, mp_int **addend_out);
/* Query functions for primegen to use */
unsigned pcs_get_bits(PrimeCandidateSource *pcs);
unsigned pcs_get_bits_remaining(PrimeCandidateSource *pcs);
mp_int *pcs_get_upper_bound(PrimeCandidateSource *pcs);
mp_int **pcs_get_known_prime_factors(PrimeCandidateSource *pcs, size_t *nout);
/* ----------------------------------------------------------------------
* A system for doing Miller-Rabin probabilistic primality tests.
* These benefit from having set up some context beforehand, if you're
* going to do more than one of them on the same candidate prime, so
* we declare an object type here to store that context.
*/
typedef struct MillerRabin MillerRabin;
/* Make and free a Miller-Rabin context. */
MillerRabin *miller_rabin_new(mp_int *p);
void miller_rabin_free(MillerRabin *mr);
/* Perform a single Miller-Rabin test, using a random witness value. */
bool miller_rabin_test_random(MillerRabin *mr);
/* Suggest how many tests are needed to make it sufficiently unlikely
* that a composite number will pass them all */
unsigned miller_rabin_checks_needed(unsigned bits);
/* An extension to the M-R test, which iterates until it either finds
* a witness value that is potentially a primitive root, or one
* that proves the number to be composite. */
mp_int *miller_rabin_find_potential_primitive_root(MillerRabin *mr);
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.
2020-02-23 15:16:30 +00:00
/* ----------------------------------------------------------------------
* 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.
*/
typedef struct ProgressReceiverVtable ProgressReceiverVtable;
typedef struct ProgressReceiver ProgressReceiver;
typedef union ProgressPhase ProgressPhase;
union ProgressPhase {
int n;
void *p;
};
struct ProgressReceiver {
const ProgressReceiverVtable *vt;
};
struct ProgressReceiverVtable {
ProgressPhase (*add_probabilistic)(ProgressReceiver *prog,
double cost_per_attempt,
double attempt_probability);
void (*ready)(ProgressReceiver *prog);
void (*start_phase)(ProgressReceiver *prog, ProgressPhase phase);
void (*report_attempt)(ProgressReceiver *prog);
void (*report_phase_complete)(ProgressReceiver *prog);
};
static inline ProgressPhase progress_add_probabilistic(ProgressReceiver *prog,
double c, double p)
{ return prog->vt->add_probabilistic(prog, c, p); }
static inline void progress_ready(ProgressReceiver *prog)
{ prog->vt->ready(prog); }
static inline void progress_start_phase(
ProgressReceiver *prog, ProgressPhase phase)
{ prog->vt->start_phase(prog, phase); }
static inline void progress_report_attempt(ProgressReceiver *prog)
{ prog->vt->report_attempt(prog); }
static inline void progress_report_phase_complete(ProgressReceiver *prog)
{ prog->vt->report_phase_complete(prog); }
ProgressPhase null_progress_add_probabilistic(
ProgressReceiver *prog, double c, double p);
void null_progress_ready(ProgressReceiver *prog);
void null_progress_start_phase(ProgressReceiver *prog, ProgressPhase phase);
void null_progress_report_attempt(ProgressReceiver *prog);
void null_progress_report_phase_complete(ProgressReceiver *prog);
extern const ProgressReceiverVtable null_progress_vt;
/* A helper function for dreaming up progress cost estimates. */
double estimate_modexp_cost(unsigned bits);
/* ----------------------------------------------------------------------
* The top-level API for generating primes.
*/
typedef struct PrimeGenerationPolicy PrimeGenerationPolicy;
typedef struct PrimeGenerationContext PrimeGenerationContext;
struct PrimeGenerationContext {
const PrimeGenerationPolicy *vt;
};
struct PrimeGenerationPolicy {
ProgressPhase (*add_progress_phase)(const PrimeGenerationPolicy *policy,
ProgressReceiver *prog, unsigned bits);
PrimeGenerationContext *(*new_context)(
const PrimeGenerationPolicy *policy);
void (*free_context)(PrimeGenerationContext *ctx);
mp_int *(*generate)(
PrimeGenerationContext *ctx,
PrimeCandidateSource *pcs, ProgressReceiver *prog);
const void *extra; /* additional data a particular impl might need */
};
static inline ProgressPhase primegen_add_progress_phase(
PrimeGenerationContext *ctx, ProgressReceiver *prog, unsigned bits)
{ return ctx->vt->add_progress_phase(ctx->vt, prog, bits); }
static inline PrimeGenerationContext *primegen_new_context(
const PrimeGenerationPolicy *policy)
{ return policy->new_context(policy); }
static inline void primegen_free_context(PrimeGenerationContext *ctx)
{ ctx->vt->free_context(ctx); }
static inline mp_int *primegen_generate(
PrimeGenerationContext *ctx,
PrimeCandidateSource *pcs, ProgressReceiver *prog)
{ return ctx->vt->generate(ctx, pcs, prog); }
extern const PrimeGenerationPolicy primegen_probabilistic;
/* ----------------------------------------------------------------------
* The overall top-level API for generating entire key pairs.
*/
int rsa_generate(RSAKey *key, int bits, PrimeGenerationContext *pgc,
ProgressReceiver *prog);
int dsa_generate(struct dss_key *key, int bits, PrimeGenerationContext *pgc,
ProgressReceiver *prog);
int ecdsa_generate(struct ecdsa_key *key, int bits);
int eddsa_generate(struct eddsa_key *key, int bits);