-
Notifications
You must be signed in to change notification settings - Fork 2
/
sshkeygen.h
300 lines (251 loc) · 12.4 KB
/
sshkeygen.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/*
* 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);