123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*
- * sshkeygen.h: routines used internally to key generation.
- */
- /* ----------------------------------------------------------------------
- * 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);
- /* ----------------------------------------------------------------------
- * 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.
- *
- * (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.)
- */
- PrimeCandidateSource *pcs_new(unsigned bits);
- PrimeCandidateSource *pcs_new_with_firstbits(unsigned bits,
- unsigned first, unsigned nfirst);
- /* 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);
- /* 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);
- /* 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. */
- 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 specified witness value.
- * Used in the test suite. */
- struct mr_result {
- unsigned passed;
- unsigned potential_primitive_root;
- };
- struct mr_result miller_rabin_test(MillerRabin *mr, mp_int *w);
- /* 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);
- /* ----------------------------------------------------------------------
- * 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);
- /* Generate a certificate of primality for a prime already known to
- * the Pockle, in a format acceptable to Math::Prime::Util. */
- strbuf *pockle_mpu(Pockle *pockle, mp_int *p);
- /* ----------------------------------------------------------------------
- * 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_linear)(ProgressReceiver *prog, double overall_cost);
- 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)(ProgressReceiver *prog, double progress);
- void (*report_attempt)(ProgressReceiver *prog);
- void (*report_phase_complete)(ProgressReceiver *prog);
- };
- static inline ProgressPhase progress_add_linear(ProgressReceiver *prog,
- double c)
- { return prog->vt->add_linear(prog, c); }
- 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(ProgressReceiver *prog, double progress)
- { prog->vt->report(prog, progress); }
- 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_linear(
- ProgressReceiver *prog, double c);
- 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(ProgressReceiver *prog, double progress);
- 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);
- strbuf *(*mpu_certificate)(PrimeGenerationContext *ctx, mp_int *p);
- 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); }
- static inline strbuf *primegen_mpu_certificate(
- PrimeGenerationContext *ctx, mp_int *p)
- { return ctx->vt->mpu_certificate(ctx, p); }
- extern const PrimeGenerationPolicy primegen_probabilistic;
- extern const PrimeGenerationPolicy primegen_provable_fast;
- extern const PrimeGenerationPolicy primegen_provable_maurer_simple;
- extern const PrimeGenerationPolicy primegen_provable_maurer_complex;
- /* ----------------------------------------------------------------------
- * The overall top-level API for generating entire key pairs.
- */
- int rsa_generate(RSAKey *key, int bits, bool strong,
- PrimeGenerationContext *pgc, ProgressReceiver *prog);
- int dsa_generate(struct dsa_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);
|