aboutsummaryrefslogtreecommitdiff
path: root/library/bignum_mod.h
blob: 963d8881ace57b188ccd26c303b4ea3935bb0dc4 (plain)
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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
/**
 *  Modular bignum functions
 *
 * This module implements operations on integers modulo some fixed modulus.
 *
 * The functions in this module obey the following conventions unless
 * explicitly indicated otherwise:
 *
 * - **Modulus parameters**: the modulus is passed as a pointer to a structure
 *   of type #mbedtls_mpi_mod_modulus. The structure must be set up with an
 *   array of limbs storing the bignum value of the modulus. The modulus must
 *   be odd and is assumed to have no leading zeroes. The modulus is usually
 *   named \c N and is usually input-only. Functions which take a parameter
 *   of type \c const #mbedtls_mpi_mod_modulus* must not modify its value.
 * - **Bignum parameters**: Bignums are passed as pointers to an array of
 *   limbs or to a #mbedtls_mpi_mod_residue structure. A limb has the type
 *   #mbedtls_mpi_uint. Residues must be initialized before use, and must be
 *   associated with the modulus \c N. Unless otherwise specified:
 *     - Bignum parameters called \c A, \c B, ... are inputs and are not
 *       modified by the function. Functions which take a parameter of
 *       type \c const #mbedtls_mpi_mod_residue* must not modify its value.
 *     - Bignum parameters called \c X, \c Y, ... are outputs or input-output.
 *       The initial bignum value of output-only parameters is ignored, but
 *       they must be set up and associated with the modulus \c N. Some
 *       functions (typically constant-flow) require that the limbs in an
 *       output residue are initialized.
 *     - Bignum parameters called \c p are inputs used to set up a modulus or
 *       residue. These must be pointers to an array of limbs.
 *     - \c T is a temporary storage area. The initial content of such a
 *       parameter is ignored and the final content is unspecified.
 *     - Some functions use different names, such as \c r for the residue.
 * - **Bignum sizes**: bignum sizes are always expressed in limbs. Both
 *   #mbedtls_mpi_mod_modulus and #mbedtls_mpi_mod_residue have a \c limbs
 *   member storing its size. All bignum parameters must have the same
 *   number of limbs as the modulus. All bignum sizes must be at least 1 and
 *   must be significantly less than #SIZE_MAX. The behavior if a size is 0 is
 *   undefined.
 * - **Bignum representation**: the representation of inputs and outputs is
 *   specified by the \c int_rep field of the modulus.
 * - **Parameter ordering**: for bignum parameters, outputs come before inputs.
 *   The modulus is passed after residues. Temporaries come last.
 * - **Aliasing**: in general, output bignums may be aliased to one or more
 *   inputs. Modulus values may not be aliased to any other parameter. Outputs
 *   may not be aliased to one another. Temporaries may not be aliased to any
 *   other parameter.
 * - **Overlap**: apart from aliasing of residue pointers (where two residue
 *   arguments are equal pointers), overlap is not supported and may result
 *   in undefined behavior.
 * - **Error handling**: functions generally check compatibility of input
 *   sizes. Most functions will not check that input values are in canonical
 *   form (i.e. that \c A < \c N), this is only checked during setup of a
 *   residue structure.
 * - **Modular representatives**: all functions expect inputs to be in the
 *   range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1].
 *   Residues are set up with an associated modulus, and operations are only
 *   guaranteed to work if the modulus is associated with all residue
 *   parameters. If a residue is passed with a modulus other than the one it
 *   is associated with, then it may be out of range. If an input is out of
 *   range, outputs are fully unspecified, though bignum values out of range
 *   should not cause buffer overflows (beware that this is not extensively
 *   tested).
 */

/*
 *  Copyright The Mbed TLS Contributors
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 */

#ifndef MBEDTLS_BIGNUM_MOD_H
#define MBEDTLS_BIGNUM_MOD_H

#include "common.h"

#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#endif

/** How residues associated with a modulus are represented.
 *
 * This also determines which fields of the modulus structure are valid and
 * what their contents are (see #mbedtls_mpi_mod_modulus).
 */
typedef enum {
    /** Representation not chosen (makes the modulus structure invalid). */
    MBEDTLS_MPI_MOD_REP_INVALID    = 0,
    /* Skip 1 as it is slightly easier to accidentally pass to functions. */
    /** Montgomery representation. */
    MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2,
    /* Optimised reduction available. This indicates a coordinate modulus (P)
     * and one or more of the following have been configured:
     * - A nist curve (MBEDTLS_ECP_DP_SECPXXXR1_ENABLED) & MBEDTLS_ECP_NIST_OPTIM.
     * - A Kobliz Curve.
     * - A Fast Reduction Curve CURVE25519 or CURVE448. */
    MBEDTLS_MPI_MOD_REP_OPT_RED,
} mbedtls_mpi_mod_rep_selector;

/* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to
 * make it easier to catch when they are accidentally swapped. */
typedef enum {
    MBEDTLS_MPI_MOD_EXT_REP_INVALID = 0,
    MBEDTLS_MPI_MOD_EXT_REP_LE      = 8,
    MBEDTLS_MPI_MOD_EXT_REP_BE
} mbedtls_mpi_mod_ext_rep;

typedef struct {
    mbedtls_mpi_uint *p;
    size_t limbs;
} mbedtls_mpi_mod_residue;

typedef struct {
    mbedtls_mpi_uint const *rr;  /* The residue for 2^{2*n*biL} mod N */
    mbedtls_mpi_uint mm;         /* Montgomery const for -N^{-1} mod 2^{ciL} */
} mbedtls_mpi_mont_struct;

typedef int (*mbedtls_mpi_modp_fn)(mbedtls_mpi_uint *X, size_t X_limbs);

typedef struct {
    mbedtls_mpi_modp_fn modp;    /* The optimised reduction function pointer */
} mbedtls_mpi_opt_red_struct;

typedef struct {
    const mbedtls_mpi_uint *p;
    size_t limbs;                            // number of limbs
    size_t bits;                             // bitlen of p
    mbedtls_mpi_mod_rep_selector int_rep;    // selector to signal the active member of the union
    union rep {
        /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */
        mbedtls_mpi_mont_struct mont;
        /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */
        mbedtls_mpi_opt_red_struct ored;
    } rep;
} mbedtls_mpi_mod_modulus;

/** Setup a residue structure.
 *
 * The residue will be set up with the buffer \p p and modulus \p N.
 *
 * The memory pointed to by \p p will be used by the resulting residue structure.
 * The value at the pointed-to memory will be the initial value of \p r and must
 * hold a value that is less than the modulus. This value will be used as-is
 * and interpreted according to the value of the `N->int_rep` field.
 *
 * The modulus \p N will be the modulus associated with \p r. The residue \p r
 * should only be used in operations where the modulus is \p N.
 *
 * \param[out] r    The address of the residue to setup.
 * \param[in] N     The address of the modulus related to \p r.
 * \param[in] p     The address of the limb array containing the value of \p r.
 *                  The memory pointed to by \p p will be used by \p r and must
 *                  not be modified in any way until after
 *                  mbedtls_mpi_mod_residue_release() is called. The data
 *                  pointed to by \p p must be less than the modulus (the value
 *                  pointed to by `N->p`) and already in the representation
 *                  indicated by `N->int_rep`.
 * \param p_limbs   The number of limbs of \p p. Must be the same as the number
 *                  of limbs in the modulus \p N.
 *
 * \return      \c 0 if successful.
 * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p p_limbs is less than the
 *              limbs in \p N or if \p p is not less than \p N.
 */
int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,
                                  const mbedtls_mpi_mod_modulus *N,
                                  mbedtls_mpi_uint *p,
                                  size_t p_limbs);

/** Unbind elements of a residue structure.
 *
 * This function removes the reference to the limb array that was passed to
 * mbedtls_mpi_mod_residue_setup() to make it safe to free or use again.
 *
 * This function invalidates \p r and it must not be used until after
 * mbedtls_mpi_mod_residue_setup() is called on it again.
 *
 * \param[out] r     The address of residue to release.
 */
void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r);

/** Initialize a modulus structure.
 *
 * \param[out] N     The address of the modulus structure to initialize.
 */
void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N);

/** Setup a modulus structure.
 *
 * \param[out] N    The address of the modulus structure to populate.
 * \param[in] p     The address of the limb array storing the value of \p N.
 *                  The memory pointed to by \p p will be used by \p N and must
 *                  not be modified in any way until after
 *                  mbedtls_mpi_mod_modulus_free() is called.
 * \param p_limbs   The number of limbs of \p p.
 *
 * \return      \c 0 if successful.
 */
int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
                                  const mbedtls_mpi_uint *p,
                                  size_t p_limbs);

/** Setup an optimised-reduction compatible modulus structure.
 *
 * \param[out] N    The address of the modulus structure to populate.
 * \param[in] p     The address of the limb array storing the value of \p N.
 *                  The memory pointed to by \p p will be used by \p N and must
 *                  not be modified in any way until after
 *                  mbedtls_mpi_mod_modulus_free() is called.
 * \param p_limbs   The number of limbs of \p p.
 * \param modp      A pointer to the optimised reduction function to use. \p p.
 *
 * \return      \c 0 if successful.
 */
int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
                                         const mbedtls_mpi_uint *p,
                                         size_t p_limbs,
                                         mbedtls_mpi_modp_fn modp);

/** Free elements of a modulus structure.
 *
 * This function frees any memory allocated by mbedtls_mpi_mod_modulus_setup().
 *
 * \warning This function does not free the limb array passed to
 *          mbedtls_mpi_mod_modulus_setup() only removes the reference to it,
 *          making it safe to free or to use it again.
 *
 * \param[in,out] N     The address of the modulus structure to free.
 */
void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N);

/** \brief  Multiply two residues, returning the residue modulo the specified
 *          modulus.
 *
 * \note Currently handles the case when `N->int_rep` is
 * MBEDTLS_MPI_MOD_REP_MONTGOMERY.
 *
 * The size of the operation is determined by \p N. \p A, \p B and \p X must
 * all be associated with the modulus \p N and must all have the same number
 * of limbs as \p N.
 *
 * \p X may be aliased to \p A or \p B, or even both, but may not overlap
 * either otherwise. They may not alias \p N (since they must be in canonical
 * form, they cannot == \p N).
 *
 * \param[out] X        The address of the result MPI. Must have the same
 *                      number of limbs as \p N.
 *                      On successful completion, \p X contains the result of
 *                      the multiplication `A * B * R^-1` mod N where
 *                      `R = 2^(biL * N->limbs)`.
 * \param[in]  A        The address of the first MPI.
 * \param[in]  B        The address of the second MPI.
 * \param[in]  N        The address of the modulus. Used to perform a modulo
 *                      operation on the result of the multiplication.
 *
 * \return      \c 0 if successful.
 * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not
 *              have the same number of limbs or \p N is invalid.
 * \return      #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
 */
int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
                        const mbedtls_mpi_mod_residue *A,
                        const mbedtls_mpi_mod_residue *B,
                        const mbedtls_mpi_mod_modulus *N);

/**
 * \brief Perform a fixed-size modular subtraction.
 *
 * Calculate `A - B modulo N`.
 *
 * \p A, \p B and \p X must all have the same number of limbs as \p N.
 *
 * \p X may be aliased to \p A or \p B, or even both, but may not overlap
 * either otherwise.
 *
 * \note This function does not check that \p A or \p B are in canonical
 *       form (that is, are < \p N) - that will have been done by
 *       mbedtls_mpi_mod_residue_setup().
 *
 * \param[out] X    The address of the result MPI. Must be initialized.
 *                  Must have the same number of limbs as the modulus \p N.
 * \param[in]  A    The address of the first MPI.
 * \param[in]  B    The address of the second MPI.
 * \param[in]  N    The address of the modulus. Used to perform a modulo
 *                  operation on the result of the subtraction.
 *
 * \return          \c 0 if successful.
 * \return          #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not
 *                  have the correct number of limbs.
 */
int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
                        const mbedtls_mpi_mod_residue *A,
                        const mbedtls_mpi_mod_residue *B,
                        const mbedtls_mpi_mod_modulus *N);

/**
 * \brief Perform modular inversion of an MPI with respect to a modulus \p N.
 *
 * \p A and \p X must be associated with the modulus \p N and will therefore
 * have the same number of limbs as \p N.
 *
 * \p X may be aliased to \p A.
 *
 * \warning  Currently only supports prime moduli, but does not check for them.
 *
 * \param[out] X   The modular inverse of \p A with respect to \p N.
 * \param[in] A    The number to calculate the modular inverse of.
 *                 Must not be 0.
 * \param[in] N    The modulus to use.
 *
 * \return         \c 0 if successful.
 * \return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A and \p N do not
 *                 have the same number of limbs.
 * \return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A is zero.
 * \return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough
 *                 memory (needed for conversion to and from Mongtomery form
 *                 when not in Montgomery form already, and for temporary use
 *                 by the inversion calculation itself).
 */

int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
                        const mbedtls_mpi_mod_residue *A,
                        const mbedtls_mpi_mod_modulus *N);
/**
 * \brief Perform a fixed-size modular addition.
 *
 * Calculate `A + B modulo N`.
 *
 * \p A, \p B and \p X must all be associated with the modulus \p N and must
 * all have the same number of limbs as \p N.
 *
 * \p X may be aliased to \p A or \p B, or even both, but may not overlap
 * either otherwise.
 *
 * \note This function does not check that \p A or \p B are in canonical
 *       form (that is, are < \p N) - that will have been done by
 *       mbedtls_mpi_mod_residue_setup().
 *
 * \param[out] X    The address of the result residue. Must be initialized.
 *                  Must have the same number of limbs as the modulus \p N.
 * \param[in]  A    The address of the first input residue.
 * \param[in]  B    The address of the second input residue.
 * \param[in]  N    The address of the modulus. Used to perform a modulo
 *                  operation on the result of the addition.
 *
 * \return          \c 0 if successful.
 * \return          #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not
 *                  have the correct number of limbs.
 */
int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
                        const mbedtls_mpi_mod_residue *A,
                        const mbedtls_mpi_mod_residue *B,
                        const mbedtls_mpi_mod_modulus *N);

/** Generate a random number uniformly in a range.
 *
 * This function generates a random number between \p min inclusive and
 * \p N exclusive.
 *
 * The procedure complies with RFC 6979 ยง3.3 (deterministic ECDSA)
 * when the RNG is a suitably parametrized instance of HMAC_DRBG
 * and \p min is \c 1.
 *
 * \note           There are `N - min` possible outputs. The lower bound
 *                 \p min can be reached, but the upper bound \p N cannot.
 *
 * \param X        The destination residue.
 * \param min      The minimum value to return. It must be strictly smaller
 *                 than \b N.
 * \param N        The modulus.
 *                 This is the upper bound of the output range, exclusive.
 * \param f_rng    The RNG function to use. This must not be \c NULL.
 * \param p_rng    The RNG parameter to be passed to \p f_rng.
 *
 * \return         \c 0 if successful.
 * \return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
 *                 unable to find a suitable value within a limited number
 *                 of attempts. This has a negligible probability if \p N
 *                 is significantly larger than \p min, which is the case
 *                 for all usual cryptographic applications.
 */
int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
                           mbedtls_mpi_uint min,
                           const mbedtls_mpi_mod_modulus *N,
                           int (*f_rng)(void *, unsigned char *, size_t),
                           void *p_rng);

/** Read a residue from a byte buffer.
 *
 * The residue will be automatically converted to the internal representation
 * based on the value of the `N->int_rep` field.
 *
 * The modulus \p N will be the modulus associated with \p r. The residue \p r
 * should only be used in operations where the modulus is \p N or a modulus
 * equivalent to \p N (in the sense that all their fields or memory pointed by
 * their fields hold the same value).
 *
 * \param[out] r    The address of the residue. It must have exactly the same
 *                  number of limbs as the modulus \p N.
 * \param[in] N     The address of the modulus.
 * \param[in] buf   The input buffer to import from.
 * \param buflen    The length in bytes of \p buf.
 * \param ext_rep   The endianness of the number in the input buffer.
 *
 * \return       \c 0 if successful.
 * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p r isn't
 *               large enough to hold the value in \p buf.
 * \return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep
 *               is invalid or the value in the buffer is not less than \p N.
 */
int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
                         const mbedtls_mpi_mod_modulus *N,
                         const unsigned char *buf,
                         size_t buflen,
                         mbedtls_mpi_mod_ext_rep ext_rep);

/** Write a residue into a byte buffer.
 *
 * The modulus \p N must be the modulus associated with \p r (see
 * mbedtls_mpi_mod_residue_setup() and mbedtls_mpi_mod_read()).
 *
 * The residue will be automatically converted from the internal representation
 * based on the value of `N->int_rep` field.
 *
 * \warning     If the buffer is smaller than `N->bits`, the number of
 *              leading zeroes is leaked through timing. If \p r is
 *              secret, the caller must ensure that \p buflen is at least
 *              (`N->bits`+7)/8.
 *
 * \param[in] r     The address of the residue. It must have the same number of
 *                  limbs as the modulus \p N. (\p r is an input parameter, but
 *                  its value will be modified during execution and restored
 *                  before the function returns.)
 * \param[in] N     The address of the modulus associated with \p r.
 * \param[out] buf  The output buffer to export to.
 * \param buflen    The length in bytes of \p buf.
 * \param ext_rep   The endianness in which the number should be written into
 *                  the output buffer.
 *
 * \return       \c 0 if successful.
 * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't
 *               large enough to hold the value of \p r (without leading
 *               zeroes).
 * \return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep is invalid.
 * \return       #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough
 *               memory for conversion. Can occur only for moduli with
 *               MBEDTLS_MPI_MOD_REP_MONTGOMERY.
 */
int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
                          const mbedtls_mpi_mod_modulus *N,
                          unsigned char *buf,
                          size_t buflen,
                          mbedtls_mpi_mod_ext_rep ext_rep);

#endif /* MBEDTLS_BIGNUM_MOD_H */