xref: /optee_os/lib/libmbedtls/mbedtls/library/bignum.c (revision b0563631928755fe864b97785160fb3088e9efdc)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Multi-precision integer library
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
5*b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6817466cbSJens Wiklander  */
7817466cbSJens Wiklander 
8817466cbSJens Wiklander /*
9817466cbSJens Wiklander  *  The following sources were referenced in the design of this Multi-precision
10817466cbSJens Wiklander  *  Integer library:
11817466cbSJens Wiklander  *
12817466cbSJens Wiklander  *  [1] Handbook of Applied Cryptography - 1997
13817466cbSJens Wiklander  *      Menezes, van Oorschot and Vanstone
14817466cbSJens Wiklander  *
15817466cbSJens Wiklander  *  [2] Multi-Precision Math
16817466cbSJens Wiklander  *      Tom St Denis
17817466cbSJens Wiklander  *      https://github.com/libtom/libtommath/blob/develop/tommath.pdf
18817466cbSJens Wiklander  *
19817466cbSJens Wiklander  *  [3] GNU Multi-Precision Arithmetic Library
20817466cbSJens Wiklander  *      https://gmplib.org/manual/index.html
21817466cbSJens Wiklander  *
22817466cbSJens Wiklander  */
23817466cbSJens Wiklander 
247901324dSJerome Forissier #include "common.h"
25817466cbSJens Wiklander 
26817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C)
27817466cbSJens Wiklander 
28817466cbSJens Wiklander #include "mbedtls/bignum.h"
2932b31808SJens Wiklander #include "bignum_core.h"
3032b31808SJens Wiklander #include "bn_mul.h"
313d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
3211fa71b9SJerome Forissier #include "mbedtls/error.h"
33039e02dfSJerome Forissier #include "constant_time_internal.h"
34817466cbSJens Wiklander 
35039e02dfSJerome Forissier #include <limits.h>
36817466cbSJens Wiklander #include <string.h>
37817466cbSJens Wiklander 
38817466cbSJens Wiklander #include "mbedtls/platform.h"
39817466cbSJens Wiklander 
4098bd5fe3SJens Wiklander #include <mempool.h>
41817466cbSJens Wiklander 
4298bd5fe3SJens Wiklander void *mbedtls_mpi_mempool;
4398bd5fe3SJens Wiklander 
44*b0563631STom Van Eyck 
45*b0563631STom Van Eyck /*
46*b0563631STom Van Eyck  * Conditionally select an MPI sign in constant time.
47*b0563631STom Van Eyck  * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid
48*b0563631STom Van Eyck  * values.)
49*b0563631STom Van Eyck  */
50*b0563631STom Van Eyck static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,
51*b0563631STom Van Eyck                                                   signed short sign1, signed short sign2)
523d3b0591SJens Wiklander {
53*b0563631STom Van Eyck     return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;
543d3b0591SJens Wiklander }
553d3b0591SJens Wiklander 
56817466cbSJens Wiklander /*
57*b0563631STom Van Eyck  * Compare signed values in constant time
58*b0563631STom Van Eyck  */
59*b0563631STom Van Eyck int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
60*b0563631STom Van Eyck                           const mbedtls_mpi *Y,
61*b0563631STom Van Eyck                           unsigned *ret)
62*b0563631STom Van Eyck {
63*b0563631STom Van Eyck     mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
64*b0563631STom Van Eyck 
65*b0563631STom Van Eyck     if (X->n != Y->n) {
66*b0563631STom Van Eyck         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
67*b0563631STom Van Eyck     }
68*b0563631STom Van Eyck 
69*b0563631STom Van Eyck     /*
70*b0563631STom Van Eyck      * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.
71*b0563631STom Van Eyck      * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
72*b0563631STom Van Eyck      */
73*b0563631STom Van Eyck     X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
74*b0563631STom Van Eyck     Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
75*b0563631STom Van Eyck 
76*b0563631STom Van Eyck     /*
77*b0563631STom Van Eyck      * If the signs are different, then the positive operand is the bigger.
78*b0563631STom Van Eyck      * That is if X is negative (X_is_negative == 1), then X < Y is true and it
79*b0563631STom Van Eyck      * is false if X is positive (X_is_negative == 0).
80*b0563631STom Van Eyck      */
81*b0563631STom Van Eyck     different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
82*b0563631STom Van Eyck     result = mbedtls_ct_bool_and(different_sign, X_is_negative);
83*b0563631STom Van Eyck 
84*b0563631STom Van Eyck     /*
85*b0563631STom Van Eyck      * Assuming signs are the same, compare X and Y. We switch the comparison
86*b0563631STom Van Eyck      * order if they are negative so that we get the right result, regardles of
87*b0563631STom Van Eyck      * sign.
88*b0563631STom Van Eyck      */
89*b0563631STom Van Eyck 
90*b0563631STom Van Eyck     /* This array is used to conditionally swap the pointers in const time */
91*b0563631STom Van Eyck     void * const p[2] = { X->p, Y->p };
92*b0563631STom Van Eyck     size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
93*b0563631STom Van Eyck     mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
94*b0563631STom Van Eyck 
95*b0563631STom Van Eyck     /*
96*b0563631STom Van Eyck      * Store in result iff the signs are the same (i.e., iff different_sign == false). If
97*b0563631STom Van Eyck      * the signs differ, result has already been set, so we don't change it.
98*b0563631STom Van Eyck      */
99*b0563631STom Van Eyck     result = mbedtls_ct_bool_or(result,
100*b0563631STom Van Eyck                                 mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
101*b0563631STom Van Eyck 
102*b0563631STom Van Eyck     *ret = mbedtls_ct_uint_if_else_0(result, 1);
103*b0563631STom Van Eyck 
104*b0563631STom Van Eyck     return 0;
105*b0563631STom Van Eyck }
106*b0563631STom Van Eyck 
107*b0563631STom Van Eyck /*
108*b0563631STom Van Eyck  * Conditionally assign X = Y, without leaking information
109*b0563631STom Van Eyck  * about whether the assignment was made or not.
110*b0563631STom Van Eyck  * (Leaking information about the respective sizes of X and Y is ok however.)
111*b0563631STom Van Eyck  */
112*b0563631STom Van Eyck #if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
113*b0563631STom Van Eyck     (_MSC_FULL_VER < 193131103)
114*b0563631STom Van Eyck /*
115*b0563631STom Van Eyck  * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
116*b0563631STom Van Eyck  * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
117*b0563631STom Van Eyck  */
118*b0563631STom Van Eyck __declspec(noinline)
119*b0563631STom Van Eyck #endif
120*b0563631STom Van Eyck int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
121*b0563631STom Van Eyck                                  const mbedtls_mpi *Y,
122*b0563631STom Van Eyck                                  unsigned char assign)
123*b0563631STom Van Eyck {
124*b0563631STom Van Eyck     int ret = 0;
125*b0563631STom Van Eyck 
126*b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
127*b0563631STom Van Eyck 
128*b0563631STom Van Eyck     {
129*b0563631STom Van Eyck         mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
130*b0563631STom Van Eyck 
131*b0563631STom Van Eyck         X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);
132*b0563631STom Van Eyck 
133*b0563631STom Van Eyck         mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
134*b0563631STom Van Eyck 
135*b0563631STom Van Eyck         mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
136*b0563631STom Van Eyck         for (size_t i = Y->n; i < X->n; i++) {
137*b0563631STom Van Eyck             X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
138*b0563631STom Van Eyck         }
139*b0563631STom Van Eyck     }
140*b0563631STom Van Eyck 
141*b0563631STom Van Eyck cleanup:
142*b0563631STom Van Eyck     return ret;
143*b0563631STom Van Eyck }
144*b0563631STom Van Eyck 
145*b0563631STom Van Eyck /*
146*b0563631STom Van Eyck  * Conditionally swap X and Y, without leaking information
147*b0563631STom Van Eyck  * about whether the swap was made or not.
148*b0563631STom Van Eyck  * Here it is not ok to simply swap the pointers, which would lead to
149*b0563631STom Van Eyck  * different memory access patterns when X and Y are used afterwards.
150*b0563631STom Van Eyck  */
151*b0563631STom Van Eyck int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
152*b0563631STom Van Eyck                                mbedtls_mpi *Y,
153*b0563631STom Van Eyck                                unsigned char swap)
154*b0563631STom Van Eyck {
155*b0563631STom Van Eyck     int ret = 0;
156*b0563631STom Van Eyck     int s;
157*b0563631STom Van Eyck 
158*b0563631STom Van Eyck     if (X == Y) {
159*b0563631STom Van Eyck         return 0;
160*b0563631STom Van Eyck     }
161*b0563631STom Van Eyck 
162*b0563631STom Van Eyck     mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
163*b0563631STom Van Eyck 
164*b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
165*b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
166*b0563631STom Van Eyck 
167*b0563631STom Van Eyck     s = X->s;
168*b0563631STom Van Eyck     X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);
169*b0563631STom Van Eyck     Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);
170*b0563631STom Van Eyck 
171*b0563631STom Van Eyck     mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
172*b0563631STom Van Eyck 
173*b0563631STom Van Eyck cleanup:
174*b0563631STom Van Eyck     return ret;
175*b0563631STom Van Eyck }
176*b0563631STom Van Eyck 
177*b0563631STom Van Eyck /* Implementation that should never be optimized out by the compiler */
178*b0563631STom Van Eyck #define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
179*b0563631STom Van Eyck 
180*b0563631STom Van Eyck /*
181*b0563631STom Van Eyck  * Implementation that should never be optimized out by the compiler.
182*b0563631STom Van Eyck  * Reintroduced to allow use of mempool.
183*b0563631STom Van Eyck  */
184*b0563631STom Van Eyck #define mbedtls_mpi_zeroize(v, n) mbedtls_platform_zeroize(v, ciL * (n))
185*b0563631STom Van Eyck 
186*b0563631STom Van Eyck /*
187817466cbSJens Wiklander  * Initialize one MPI
188817466cbSJens Wiklander  */
1893d3b0591SJens Wiklander static void mpi_init(mbedtls_mpi *X, short use_mempool)
190817466cbSJens Wiklander {
1913d3b0591SJens Wiklander     X->s = 1;
1923d3b0591SJens Wiklander     X->use_mempool = use_mempool;
1933d3b0591SJens Wiklander     X->n = 0;
1943d3b0591SJens Wiklander     X->p = NULL;
195817466cbSJens Wiklander }
196817466cbSJens Wiklander 
19798bd5fe3SJens Wiklander void mbedtls_mpi_init(mbedtls_mpi *X)
19898bd5fe3SJens Wiklander {
1993d3b0591SJens Wiklander     mpi_init(X, 0 /*use_mempool*/);
20098bd5fe3SJens Wiklander }
20198bd5fe3SJens Wiklander 
20298bd5fe3SJens Wiklander void mbedtls_mpi_init_mempool(mbedtls_mpi *X)
20398bd5fe3SJens Wiklander {
2043d3b0591SJens Wiklander     mpi_init(X, !!mbedtls_mpi_mempool /*use_mempool*/);
20598bd5fe3SJens Wiklander }
20698bd5fe3SJens Wiklander 
207817466cbSJens Wiklander /*
208817466cbSJens Wiklander  * Unallocate one MPI
209817466cbSJens Wiklander  */
210817466cbSJens Wiklander void mbedtls_mpi_free(mbedtls_mpi *X)
211817466cbSJens Wiklander {
21232b31808SJens Wiklander     if (X == NULL) {
213817466cbSJens Wiklander         return;
21432b31808SJens Wiklander     }
215817466cbSJens Wiklander 
21632b31808SJens Wiklander     if (X->p != NULL) {
217*b0563631STom Van Eyck         if(X->use_mempool) {
218817466cbSJens Wiklander             mbedtls_mpi_zeroize(X->p, X->n);
21918c5148dSJens Wiklander             mempool_free(mbedtls_mpi_mempool, X->p);
220*b0563631STom Van Eyck         } else {
221*b0563631STom Van Eyck             mbedtls_mpi_zeroize_and_free(X->p, X->n);
222*b0563631STom Van Eyck         }
223817466cbSJens Wiklander     }
224817466cbSJens Wiklander 
225817466cbSJens Wiklander     X->s = 1;
226817466cbSJens Wiklander     X->n = 0;
2273d3b0591SJens Wiklander     X->p = NULL;
228817466cbSJens Wiklander }
229817466cbSJens Wiklander 
230817466cbSJens Wiklander /*
231817466cbSJens Wiklander  * Enlarge to the specified number of limbs
232817466cbSJens Wiklander  */
233817466cbSJens Wiklander int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
234817466cbSJens Wiklander {
235817466cbSJens Wiklander     mbedtls_mpi_uint *p;
236817466cbSJens Wiklander 
23732b31808SJens Wiklander     if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
23832b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
23932b31808SJens Wiklander     }
240817466cbSJens Wiklander 
24132b31808SJens Wiklander     if (X->n < nblimbs) {
24232b31808SJens Wiklander         if(X->use_mempool) {
2433d3b0591SJens Wiklander             p = mempool_alloc(mbedtls_mpi_mempool, nblimbs * ciL);
24418c5148dSJens Wiklander             if(p == NULL)
24532b31808SJens Wiklander                 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
2463d3b0591SJens Wiklander             memset(p, 0, nblimbs * ciL);
24732b31808SJens Wiklander         } else {
2483d3b0591SJens Wiklander                 p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL);
2493d3b0591SJens Wiklander                 if (p == NULL)
25032b31808SJens Wiklander                     return MBEDTLS_ERR_MPI_ALLOC_FAILED;
251817466cbSJens Wiklander         }
252817466cbSJens Wiklander 
25332b31808SJens Wiklander         if (X->p != NULL) {
2543d3b0591SJens Wiklander             memcpy(p, X->p, X->n * ciL);
255*b0563631STom Van Eyck 
256*b0563631STom Van Eyck             if (X->use_mempool) {
2573d3b0591SJens Wiklander                 mbedtls_mpi_zeroize(X->p, X->n);
25818c5148dSJens Wiklander                 mempool_free(mbedtls_mpi_mempool, X->p);
259*b0563631STom Van Eyck             } else {
260*b0563631STom Van Eyck                 mbedtls_mpi_zeroize_and_free(X->p, X->n);
261*b0563631STom Van Eyck             }
2623d3b0591SJens Wiklander         }
26318c5148dSJens Wiklander 
264*b0563631STom Van Eyck         /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
265*b0563631STom Van Eyck          * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
266*b0563631STom Van Eyck         X->n = (unsigned short) nblimbs;
2673d3b0591SJens Wiklander         X->p = p;
2683d3b0591SJens Wiklander     }
269817466cbSJens Wiklander 
27032b31808SJens Wiklander     return 0;
271817466cbSJens Wiklander }
272817466cbSJens Wiklander 
273817466cbSJens Wiklander /*
274817466cbSJens Wiklander  * Resize down as much as possible,
275817466cbSJens Wiklander  * while keeping at least the specified number of limbs
276817466cbSJens Wiklander  */
277817466cbSJens Wiklander int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
278817466cbSJens Wiklander {
279817466cbSJens Wiklander     mbedtls_mpi_uint *p;
280817466cbSJens Wiklander     size_t i;
2813d3b0591SJens Wiklander 
28232b31808SJens Wiklander     if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
28332b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
28432b31808SJens Wiklander     }
285817466cbSJens Wiklander 
2865b25c76aSJerome Forissier     /* Actually resize up if there are currently fewer than nblimbs limbs. */
28732b31808SJens Wiklander     if (X->n <= nblimbs) {
28832b31808SJens Wiklander         return mbedtls_mpi_grow(X, nblimbs);
28932b31808SJens Wiklander     }
2905b25c76aSJerome Forissier     /* After this point, then X->n > nblimbs and in particular X->n > 0. */
291817466cbSJens Wiklander 
29232b31808SJens Wiklander     for (i = X->n - 1; i > 0; i--) {
29332b31808SJens Wiklander         if (X->p[i] != 0) {
294817466cbSJens Wiklander             break;
29532b31808SJens Wiklander         }
29632b31808SJens Wiklander     }
297817466cbSJens Wiklander     i++;
298817466cbSJens Wiklander 
29932b31808SJens Wiklander     if (i < nblimbs) {
300817466cbSJens Wiklander         i = nblimbs;
30132b31808SJens Wiklander     }
302817466cbSJens Wiklander 
30332b31808SJens Wiklander     if (X->use_mempool) {
304ed3fa831SJerome Forissier         p = mempool_alloc(mbedtls_mpi_mempool, i * ciL);
3053d3b0591SJens Wiklander         if (p == NULL)
30632b31808SJens Wiklander             return MBEDTLS_ERR_MPI_ALLOC_FAILED;
307ed3fa831SJerome Forissier         memset(p, 0, i * ciL);
30832b31808SJens Wiklander     } else {
30932b31808SJens Wiklander         if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL)
31032b31808SJens Wiklander             return MBEDTLS_ERR_MPI_ALLOC_FAILED;
3113d3b0591SJens Wiklander     }
31218c5148dSJens Wiklander 
31332b31808SJens Wiklander     if (X->p != NULL) {
314817466cbSJens Wiklander         memcpy(p, X->p, i * ciL);
315*b0563631STom Van Eyck 
316*b0563631STom Van Eyck         if (X->use_mempool) {
317817466cbSJens Wiklander             mbedtls_mpi_zeroize(X->p, X->n);
31818c5148dSJens Wiklander             mempool_free(mbedtls_mpi_mempool, X->p);
319*b0563631STom Van Eyck         }
320*b0563631STom Van Eyck         else {
321*b0563631STom Van Eyck             mbedtls_mpi_zeroize_and_free(X->p, X->n);
322*b0563631STom Van Eyck         }
323817466cbSJens Wiklander     }
324817466cbSJens Wiklander 
325*b0563631STom Van Eyck     /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
326*b0563631STom Van Eyck      * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
327*b0563631STom Van Eyck     X->n = (unsigned short) i;
3283d3b0591SJens Wiklander     X->p = p;
329817466cbSJens Wiklander 
33032b31808SJens Wiklander     return 0;
331817466cbSJens Wiklander }
332817466cbSJens Wiklander 
3337901324dSJerome Forissier /* Resize X to have exactly n limbs and set it to 0. */
3347901324dSJerome Forissier static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
3357901324dSJerome Forissier {
33632b31808SJens Wiklander     if (limbs == 0) {
3377901324dSJerome Forissier         mbedtls_mpi_free(X);
33832b31808SJens Wiklander         return 0;
33932b31808SJens Wiklander     } else if (X->n == limbs) {
3407901324dSJerome Forissier         memset(X->p, 0, limbs * ciL);
3417901324dSJerome Forissier         X->s = 1;
34232b31808SJens Wiklander         return 0;
34332b31808SJens Wiklander     } else {
3447901324dSJerome Forissier         mbedtls_mpi_free(X);
34532b31808SJens Wiklander         return mbedtls_mpi_grow(X, limbs);
3467901324dSJerome Forissier     }
3477901324dSJerome Forissier }
3487901324dSJerome Forissier 
349817466cbSJens Wiklander /*
3507901324dSJerome Forissier  * Copy the contents of Y into X.
3517901324dSJerome Forissier  *
3527901324dSJerome Forissier  * This function is not constant-time. Leading zeros in Y may be removed.
3537901324dSJerome Forissier  *
3547901324dSJerome Forissier  * Ensure that X does not shrink. This is not guaranteed by the public API,
355*b0563631STom Van Eyck  * but some code in the bignum module might still rely on this property.
356817466cbSJens Wiklander  */
357817466cbSJens Wiklander int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
358817466cbSJens Wiklander {
3593d3b0591SJens Wiklander     int ret = 0;
360817466cbSJens Wiklander     size_t i;
361817466cbSJens Wiklander 
36232b31808SJens Wiklander     if (X == Y) {
36332b31808SJens Wiklander         return 0;
36432b31808SJens Wiklander     }
365817466cbSJens Wiklander 
36632b31808SJens Wiklander     if (Y->n == 0) {
36732b31808SJens Wiklander         if (X->n != 0) {
3687901324dSJerome Forissier             X->s = 1;
3697901324dSJerome Forissier             memset(X->p, 0, X->n * ciL);
3707901324dSJerome Forissier         }
37132b31808SJens Wiklander         return 0;
372817466cbSJens Wiklander     }
373817466cbSJens Wiklander 
37432b31808SJens Wiklander     for (i = Y->n - 1; i > 0; i--) {
37532b31808SJens Wiklander         if (Y->p[i] != 0) {
376817466cbSJens Wiklander             break;
37732b31808SJens Wiklander         }
37832b31808SJens Wiklander     }
379817466cbSJens Wiklander     i++;
380817466cbSJens Wiklander 
381817466cbSJens Wiklander     X->s = Y->s;
382817466cbSJens Wiklander 
38332b31808SJens Wiklander     if (X->n < i) {
384817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
38532b31808SJens Wiklander     } else {
3863d3b0591SJens Wiklander         memset(X->p + i, 0, (X->n - i) * ciL);
3873d3b0591SJens Wiklander     }
388817466cbSJens Wiklander 
389817466cbSJens Wiklander     memcpy(X->p, Y->p, i * ciL);
390817466cbSJens Wiklander 
391817466cbSJens Wiklander cleanup:
392817466cbSJens Wiklander 
39332b31808SJens Wiklander     return ret;
394817466cbSJens Wiklander }
395817466cbSJens Wiklander 
396817466cbSJens Wiklander /*
397817466cbSJens Wiklander  * Swap the contents of X and Y
398817466cbSJens Wiklander  */
399817466cbSJens Wiklander void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
400817466cbSJens Wiklander {
401817466cbSJens Wiklander     mbedtls_mpi T;
402817466cbSJens Wiklander 
403817466cbSJens Wiklander     memcpy(&T,  X, sizeof(mbedtls_mpi));
404817466cbSJens Wiklander     memcpy(X,  Y, sizeof(mbedtls_mpi));
405817466cbSJens Wiklander     memcpy(Y, &T, sizeof(mbedtls_mpi));
406817466cbSJens Wiklander }
407817466cbSJens Wiklander 
40832b31808SJens Wiklander static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
40932b31808SJens Wiklander {
41032b31808SJens Wiklander     if (z >= 0) {
41132b31808SJens Wiklander         return z;
41232b31808SJens Wiklander     }
41332b31808SJens Wiklander     /* Take care to handle the most negative value (-2^(biL-1)) correctly.
41432b31808SJens Wiklander      * A naive -z would have undefined behavior.
41532b31808SJens Wiklander      * Write this in a way that makes popular compilers happy (GCC, Clang,
41632b31808SJens Wiklander      * MSVC). */
41732b31808SJens Wiklander     return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
41832b31808SJens Wiklander }
41932b31808SJens Wiklander 
420*b0563631STom Van Eyck /* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
421*b0563631STom Van Eyck  * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
422*b0563631STom Van Eyck #define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
423*b0563631STom Van Eyck 
424817466cbSJens Wiklander /*
425817466cbSJens Wiklander  * Set value from integer
426817466cbSJens Wiklander  */
427817466cbSJens Wiklander int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
428817466cbSJens Wiklander {
42911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
430817466cbSJens Wiklander 
431817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
432817466cbSJens Wiklander     memset(X->p, 0, X->n * ciL);
433817466cbSJens Wiklander 
43432b31808SJens Wiklander     X->p[0] = mpi_sint_abs(z);
435*b0563631STom Van Eyck     X->s    = TO_SIGN(z);
436817466cbSJens Wiklander 
437817466cbSJens Wiklander cleanup:
438817466cbSJens Wiklander 
43932b31808SJens Wiklander     return ret;
440817466cbSJens Wiklander }
441817466cbSJens Wiklander 
442817466cbSJens Wiklander /*
443817466cbSJens Wiklander  * Get a specific bit
444817466cbSJens Wiklander  */
445817466cbSJens Wiklander int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
446817466cbSJens Wiklander {
44732b31808SJens Wiklander     if (X->n * biL <= pos) {
44832b31808SJens Wiklander         return 0;
449817466cbSJens Wiklander     }
450817466cbSJens Wiklander 
45132b31808SJens Wiklander     return (X->p[pos / biL] >> (pos % biL)) & 0x01;
45232b31808SJens Wiklander }
4533d3b0591SJens Wiklander 
454817466cbSJens Wiklander /*
455817466cbSJens Wiklander  * Set a bit to a specific value of 0 or 1
456817466cbSJens Wiklander  */
457817466cbSJens Wiklander int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
458817466cbSJens Wiklander {
459817466cbSJens Wiklander     int ret = 0;
460817466cbSJens Wiklander     size_t off = pos / biL;
461817466cbSJens Wiklander     size_t idx = pos % biL;
462817466cbSJens Wiklander 
46332b31808SJens Wiklander     if (val != 0 && val != 1) {
46432b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
46532b31808SJens Wiklander     }
466817466cbSJens Wiklander 
46732b31808SJens Wiklander     if (X->n * biL <= pos) {
46832b31808SJens Wiklander         if (val == 0) {
46932b31808SJens Wiklander             return 0;
47032b31808SJens Wiklander         }
471817466cbSJens Wiklander 
472817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
473817466cbSJens Wiklander     }
474817466cbSJens Wiklander 
475817466cbSJens Wiklander     X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
476817466cbSJens Wiklander     X->p[off] |= (mbedtls_mpi_uint) val << idx;
477817466cbSJens Wiklander 
478817466cbSJens Wiklander cleanup:
479817466cbSJens Wiklander 
48032b31808SJens Wiklander     return ret;
481817466cbSJens Wiklander }
482817466cbSJens Wiklander 
483817466cbSJens Wiklander /*
484817466cbSJens Wiklander  * Return the number of less significant zero-bits
485817466cbSJens Wiklander  */
486817466cbSJens Wiklander size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
487817466cbSJens Wiklander {
488*b0563631STom Van Eyck     size_t i;
489817466cbSJens Wiklander 
490*b0563631STom Van Eyck #if defined(__has_builtin)
491*b0563631STom Van Eyck #if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
492*b0563631STom Van Eyck     #define mbedtls_mpi_uint_ctz __builtin_ctz
493*b0563631STom Van Eyck #elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
494*b0563631STom Van Eyck     #define mbedtls_mpi_uint_ctz __builtin_ctzl
495*b0563631STom Van Eyck #elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
496*b0563631STom Van Eyck     #define mbedtls_mpi_uint_ctz __builtin_ctzll
497*b0563631STom Van Eyck #endif
498*b0563631STom Van Eyck #endif
499*b0563631STom Van Eyck 
500*b0563631STom Van Eyck #if defined(mbedtls_mpi_uint_ctz)
50132b31808SJens Wiklander     for (i = 0; i < X->n; i++) {
502*b0563631STom Van Eyck         if (X->p[i] != 0) {
503*b0563631STom Van Eyck             return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
504*b0563631STom Van Eyck         }
505*b0563631STom Van Eyck     }
506*b0563631STom Van Eyck #else
507*b0563631STom Van Eyck     size_t count = 0;
508*b0563631STom Van Eyck     for (i = 0; i < X->n; i++) {
509*b0563631STom Van Eyck         for (size_t j = 0; j < biL; j++, count++) {
51032b31808SJens Wiklander             if (((X->p[i] >> j) & 1) != 0) {
51132b31808SJens Wiklander                 return count;
51232b31808SJens Wiklander             }
51332b31808SJens Wiklander         }
514817466cbSJens Wiklander     }
515*b0563631STom Van Eyck #endif
516817466cbSJens Wiklander 
51732b31808SJens Wiklander     return 0;
518817466cbSJens Wiklander }
519817466cbSJens Wiklander 
520817466cbSJens Wiklander /*
521817466cbSJens Wiklander  * Return the number of bits
522817466cbSJens Wiklander  */
523817466cbSJens Wiklander size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
524817466cbSJens Wiklander {
52532b31808SJens Wiklander     return mbedtls_mpi_core_bitlen(X->p, X->n);
526817466cbSJens Wiklander }
527817466cbSJens Wiklander 
528817466cbSJens Wiklander /*
529817466cbSJens Wiklander  * Return the total size in bytes
530817466cbSJens Wiklander  */
531817466cbSJens Wiklander size_t mbedtls_mpi_size(const mbedtls_mpi *X)
532817466cbSJens Wiklander {
53332b31808SJens Wiklander     return (mbedtls_mpi_bitlen(X) + 7) >> 3;
534817466cbSJens Wiklander }
535817466cbSJens Wiklander 
536817466cbSJens Wiklander /*
537817466cbSJens Wiklander  * Convert an ASCII character to digit value
538817466cbSJens Wiklander  */
539817466cbSJens Wiklander static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
540817466cbSJens Wiklander {
541817466cbSJens Wiklander     *d = 255;
542817466cbSJens Wiklander 
54332b31808SJens Wiklander     if (c >= 0x30 && c <= 0x39) {
54432b31808SJens Wiklander         *d = c - 0x30;
54532b31808SJens Wiklander     }
54632b31808SJens Wiklander     if (c >= 0x41 && c <= 0x46) {
54732b31808SJens Wiklander         *d = c - 0x37;
54832b31808SJens Wiklander     }
54932b31808SJens Wiklander     if (c >= 0x61 && c <= 0x66) {
55032b31808SJens Wiklander         *d = c - 0x57;
55132b31808SJens Wiklander     }
552817466cbSJens Wiklander 
55332b31808SJens Wiklander     if (*d >= (mbedtls_mpi_uint) radix) {
55432b31808SJens Wiklander         return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
55532b31808SJens Wiklander     }
556817466cbSJens Wiklander 
55732b31808SJens Wiklander     return 0;
558817466cbSJens Wiklander }
559817466cbSJens Wiklander 
560817466cbSJens Wiklander /*
561817466cbSJens Wiklander  * Import from an ASCII string
562817466cbSJens Wiklander  */
563817466cbSJens Wiklander int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
564817466cbSJens Wiklander {
56511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
566817466cbSJens Wiklander     size_t i, j, slen, n;
5677901324dSJerome Forissier     int sign = 1;
568817466cbSJens Wiklander     mbedtls_mpi_uint d;
569817466cbSJens Wiklander     mbedtls_mpi T;
570817466cbSJens Wiklander 
57132b31808SJens Wiklander     if (radix < 2 || radix > 16) {
57232b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
57332b31808SJens Wiklander     }
574817466cbSJens Wiklander 
57598bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&T);
576817466cbSJens Wiklander 
57732b31808SJens Wiklander     if (s[0] == 0) {
5787901324dSJerome Forissier         mbedtls_mpi_free(X);
57932b31808SJens Wiklander         return 0;
5807901324dSJerome Forissier     }
5817901324dSJerome Forissier 
58232b31808SJens Wiklander     if (s[0] == '-') {
5837901324dSJerome Forissier         ++s;
5847901324dSJerome Forissier         sign = -1;
5857901324dSJerome Forissier     }
5867901324dSJerome Forissier 
587817466cbSJens Wiklander     slen = strlen(s);
588817466cbSJens Wiklander 
58932b31808SJens Wiklander     if (radix == 16) {
590*b0563631STom Van Eyck         if (slen > SIZE_MAX >> 2) {
59132b31808SJens Wiklander             return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
59232b31808SJens Wiklander         }
593817466cbSJens Wiklander 
594817466cbSJens Wiklander         n = BITS_TO_LIMBS(slen << 2);
595817466cbSJens Wiklander 
596817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
597817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
598817466cbSJens Wiklander 
59932b31808SJens Wiklander         for (i = slen, j = 0; i > 0; i--, j++) {
600817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
601817466cbSJens Wiklander             X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
602817466cbSJens Wiklander         }
60332b31808SJens Wiklander     } else {
604817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
605817466cbSJens Wiklander 
60632b31808SJens Wiklander         for (i = 0; i < slen; i++) {
607817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
608817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
609817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
610817466cbSJens Wiklander         }
611817466cbSJens Wiklander     }
6127901324dSJerome Forissier 
61332b31808SJens Wiklander     if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
6147901324dSJerome Forissier         X->s = -1;
61532b31808SJens Wiklander     }
616817466cbSJens Wiklander 
617817466cbSJens Wiklander cleanup:
618817466cbSJens Wiklander 
619817466cbSJens Wiklander     mbedtls_mpi_free(&T);
620817466cbSJens Wiklander 
62132b31808SJens Wiklander     return ret;
622817466cbSJens Wiklander }
623817466cbSJens Wiklander 
624817466cbSJens Wiklander /*
6255b25c76aSJerome Forissier  * Helper to write the digits high-order first.
626817466cbSJens Wiklander  */
6275b25c76aSJerome Forissier static int mpi_write_hlp(mbedtls_mpi *X, int radix,
6285b25c76aSJerome Forissier                          char **p, const size_t buflen)
629817466cbSJens Wiklander {
63011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
631817466cbSJens Wiklander     mbedtls_mpi_uint r;
6325b25c76aSJerome Forissier     size_t length = 0;
6335b25c76aSJerome Forissier     char *p_end = *p + buflen;
634817466cbSJens Wiklander 
63532b31808SJens Wiklander     do {
63632b31808SJens Wiklander         if (length >= buflen) {
63732b31808SJens Wiklander             return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
6385b25c76aSJerome Forissier         }
639817466cbSJens Wiklander 
640817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
641817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
6425b25c76aSJerome Forissier         /*
6435b25c76aSJerome Forissier          * Write the residue in the current position, as an ASCII character.
6445b25c76aSJerome Forissier          */
64532b31808SJens Wiklander         if (r < 0xA) {
6465b25c76aSJerome Forissier             *(--p_end) = (char) ('0' + r);
64732b31808SJens Wiklander         } else {
6485b25c76aSJerome Forissier             *(--p_end) = (char) ('A' + (r - 0xA));
64932b31808SJens Wiklander         }
6505b25c76aSJerome Forissier 
6515b25c76aSJerome Forissier         length++;
6525b25c76aSJerome Forissier     } while (mbedtls_mpi_cmp_int(X, 0) != 0);
6535b25c76aSJerome Forissier 
6545b25c76aSJerome Forissier     memmove(*p, p_end, length);
6555b25c76aSJerome Forissier     *p += length;
656817466cbSJens Wiklander 
657817466cbSJens Wiklander cleanup:
658817466cbSJens Wiklander 
65932b31808SJens Wiklander     return ret;
660817466cbSJens Wiklander }
661817466cbSJens Wiklander 
662817466cbSJens Wiklander /*
663817466cbSJens Wiklander  * Export into an ASCII string
664817466cbSJens Wiklander  */
665817466cbSJens Wiklander int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
666817466cbSJens Wiklander                              char *buf, size_t buflen, size_t *olen)
667817466cbSJens Wiklander {
668817466cbSJens Wiklander     int ret = 0;
669817466cbSJens Wiklander     size_t n;
670817466cbSJens Wiklander     char *p;
671817466cbSJens Wiklander     mbedtls_mpi T;
672817466cbSJens Wiklander 
67332b31808SJens Wiklander     if (radix < 2 || radix > 16) {
67432b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
67532b31808SJens Wiklander     }
676817466cbSJens Wiklander 
6775b25c76aSJerome Forissier     n = mbedtls_mpi_bitlen(X);   /* Number of bits necessary to present `n`. */
67832b31808SJens Wiklander     if (radix >=  4) {
67932b31808SJens Wiklander         n >>= 1;                 /* Number of 4-adic digits necessary to present
6805b25c76aSJerome Forissier                                   * `n`. If radix > 4, this might be a strict
6815b25c76aSJerome Forissier                                   * overapproximation of the number of
6825b25c76aSJerome Forissier                                   * radix-adic digits needed to present `n`. */
68332b31808SJens Wiklander     }
68432b31808SJens Wiklander     if (radix >= 16) {
68532b31808SJens Wiklander         n >>= 1;                 /* Number of hexadecimal digits necessary to
6865b25c76aSJerome Forissier                                   * present `n`. */
6875b25c76aSJerome Forissier 
68832b31808SJens Wiklander     }
6895b25c76aSJerome Forissier     n += 1; /* Terminating null byte */
6905b25c76aSJerome Forissier     n += 1; /* Compensate for the divisions above, which round down `n`
6915b25c76aSJerome Forissier              * in case it's not even. */
6925b25c76aSJerome Forissier     n += 1; /* Potential '-'-sign. */
6935b25c76aSJerome Forissier     n += (n & 1);   /* Make n even to have enough space for hexadecimal writing,
6945b25c76aSJerome Forissier                      * which always uses an even number of hex-digits. */
695817466cbSJens Wiklander 
69632b31808SJens Wiklander     if (buflen < n) {
697817466cbSJens Wiklander         *olen = n;
69832b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
699817466cbSJens Wiklander     }
700817466cbSJens Wiklander 
701817466cbSJens Wiklander     p = buf;
70298bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&T);
703817466cbSJens Wiklander 
70432b31808SJens Wiklander     if (X->s == -1) {
705817466cbSJens Wiklander         *p++ = '-';
7065b25c76aSJerome Forissier         buflen--;
7075b25c76aSJerome Forissier     }
708817466cbSJens Wiklander 
70932b31808SJens Wiklander     if (radix == 16) {
710817466cbSJens Wiklander         int c;
711817466cbSJens Wiklander         size_t i, j, k;
712817466cbSJens Wiklander 
71332b31808SJens Wiklander         for (i = X->n, k = 0; i > 0; i--) {
71432b31808SJens Wiklander             for (j = ciL; j > 0; j--) {
715817466cbSJens Wiklander                 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
716817466cbSJens Wiklander 
71732b31808SJens Wiklander                 if (c == 0 && k == 0 && (i + j) != 2) {
718817466cbSJens Wiklander                     continue;
71932b31808SJens Wiklander                 }
720817466cbSJens Wiklander 
721817466cbSJens Wiklander                 *(p++) = "0123456789ABCDEF" [c / 16];
722817466cbSJens Wiklander                 *(p++) = "0123456789ABCDEF" [c % 16];
723817466cbSJens Wiklander                 k = 1;
724817466cbSJens Wiklander             }
725817466cbSJens Wiklander         }
72632b31808SJens Wiklander     } else {
727817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
728817466cbSJens Wiklander 
72932b31808SJens Wiklander         if (T.s == -1) {
730817466cbSJens Wiklander             T.s = 1;
73132b31808SJens Wiklander         }
732817466cbSJens Wiklander 
7335b25c76aSJerome Forissier         MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
734817466cbSJens Wiklander     }
735817466cbSJens Wiklander 
736817466cbSJens Wiklander     *p++ = '\0';
737*b0563631STom Van Eyck     *olen = (size_t) (p - buf);
738817466cbSJens Wiklander 
739817466cbSJens Wiklander cleanup:
740817466cbSJens Wiklander 
741817466cbSJens Wiklander     mbedtls_mpi_free(&T);
742817466cbSJens Wiklander 
74332b31808SJens Wiklander     return ret;
744817466cbSJens Wiklander }
745817466cbSJens Wiklander 
746817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
747817466cbSJens Wiklander /*
748817466cbSJens Wiklander  * Read X from an opened file
749817466cbSJens Wiklander  */
750817466cbSJens Wiklander int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
751817466cbSJens Wiklander {
752817466cbSJens Wiklander     mbedtls_mpi_uint d;
753817466cbSJens Wiklander     size_t slen;
754817466cbSJens Wiklander     char *p;
755817466cbSJens Wiklander     /*
756817466cbSJens Wiklander      * Buffer should have space for (short) label and decimal formatted MPI,
757817466cbSJens Wiklander      * newline characters and '\0'
758817466cbSJens Wiklander      */
759817466cbSJens Wiklander     char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
760817466cbSJens Wiklander 
76132b31808SJens Wiklander     if (radix < 2 || radix > 16) {
76232b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
76332b31808SJens Wiklander     }
7643d3b0591SJens Wiklander 
765817466cbSJens Wiklander     memset(s, 0, sizeof(s));
76632b31808SJens Wiklander     if (fgets(s, sizeof(s) - 1, fin) == NULL) {
76732b31808SJens Wiklander         return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
76832b31808SJens Wiklander     }
769817466cbSJens Wiklander 
770817466cbSJens Wiklander     slen = strlen(s);
77132b31808SJens Wiklander     if (slen == sizeof(s) - 2) {
77232b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
77332b31808SJens Wiklander     }
774817466cbSJens Wiklander 
77532b31808SJens Wiklander     if (slen > 0 && s[slen - 1] == '\n') {
77632b31808SJens Wiklander         slen--; s[slen] = '\0';
77732b31808SJens Wiklander     }
77832b31808SJens Wiklander     if (slen > 0 && s[slen - 1] == '\r') {
77932b31808SJens Wiklander         slen--; s[slen] = '\0';
78032b31808SJens Wiklander     }
781817466cbSJens Wiklander 
782817466cbSJens Wiklander     p = s + slen;
78332b31808SJens Wiklander     while (p-- > s) {
78432b31808SJens Wiklander         if (mpi_get_digit(&d, radix, *p) != 0) {
785817466cbSJens Wiklander             break;
78632b31808SJens Wiklander         }
78732b31808SJens Wiklander     }
788817466cbSJens Wiklander 
78932b31808SJens Wiklander     return mbedtls_mpi_read_string(X, radix, p + 1);
790817466cbSJens Wiklander }
791817466cbSJens Wiklander 
792817466cbSJens Wiklander /*
793817466cbSJens Wiklander  * Write X into an opened file (or stdout if fout == NULL)
794817466cbSJens Wiklander  */
795817466cbSJens Wiklander int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
796817466cbSJens Wiklander {
79711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
798817466cbSJens Wiklander     size_t n, slen, plen;
799817466cbSJens Wiklander     /*
800817466cbSJens Wiklander      * Buffer should have space for (short) label and decimal formatted MPI,
801817466cbSJens Wiklander      * newline characters and '\0'
802817466cbSJens Wiklander      */
803817466cbSJens Wiklander     char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
8043d3b0591SJens Wiklander 
80532b31808SJens Wiklander     if (radix < 2 || radix > 16) {
80632b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
80732b31808SJens Wiklander     }
808817466cbSJens Wiklander 
809817466cbSJens Wiklander     memset(s, 0, sizeof(s));
810817466cbSJens Wiklander 
811817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
812817466cbSJens Wiklander 
81332b31808SJens Wiklander     if (p == NULL) {
81432b31808SJens Wiklander         p = "";
81532b31808SJens Wiklander     }
816817466cbSJens Wiklander 
817817466cbSJens Wiklander     plen = strlen(p);
818817466cbSJens Wiklander     slen = strlen(s);
819817466cbSJens Wiklander     s[slen++] = '\r';
820817466cbSJens Wiklander     s[slen++] = '\n';
821817466cbSJens Wiklander 
82232b31808SJens Wiklander     if (fout != NULL) {
823817466cbSJens Wiklander         if (fwrite(p, 1, plen, fout) != plen ||
82432b31808SJens Wiklander             fwrite(s, 1, slen, fout) != slen) {
82532b31808SJens Wiklander             return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
826817466cbSJens Wiklander         }
82732b31808SJens Wiklander     } else {
828817466cbSJens Wiklander         mbedtls_printf("%s%s", p, s);
82932b31808SJens Wiklander     }
830817466cbSJens Wiklander 
831817466cbSJens Wiklander cleanup:
832817466cbSJens Wiklander 
83332b31808SJens Wiklander     return ret;
834817466cbSJens Wiklander }
835817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
836817466cbSJens Wiklander 
837817466cbSJens Wiklander /*
83811fa71b9SJerome Forissier  * Import X from unsigned binary data, little endian
83932b31808SJens Wiklander  *
84032b31808SJens Wiklander  * This function is guaranteed to return an MPI with exactly the necessary
84132b31808SJens Wiklander  * number of limbs (in particular, it does not skip 0s in the input).
84211fa71b9SJerome Forissier  */
84311fa71b9SJerome Forissier int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
84411fa71b9SJerome Forissier                                const unsigned char *buf, size_t buflen)
84511fa71b9SJerome Forissier {
84611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
84732b31808SJens Wiklander     const size_t limbs = CHARS_TO_LIMBS(buflen);
84811fa71b9SJerome Forissier 
84911fa71b9SJerome Forissier     /* Ensure that target MPI has exactly the necessary number of limbs */
8507901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
85111fa71b9SJerome Forissier 
85232b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
85311fa71b9SJerome Forissier 
85411fa71b9SJerome Forissier cleanup:
85511fa71b9SJerome Forissier 
85611fa71b9SJerome Forissier     /*
85711fa71b9SJerome Forissier      * This function is also used to import keys. However, wiping the buffers
85811fa71b9SJerome Forissier      * upon failure is not necessary because failure only can happen before any
85911fa71b9SJerome Forissier      * input is copied.
86011fa71b9SJerome Forissier      */
86132b31808SJens Wiklander     return ret;
86211fa71b9SJerome Forissier }
86311fa71b9SJerome Forissier 
86411fa71b9SJerome Forissier /*
865817466cbSJens Wiklander  * Import X from unsigned binary data, big endian
86632b31808SJens Wiklander  *
86732b31808SJens Wiklander  * This function is guaranteed to return an MPI with exactly the necessary
86832b31808SJens Wiklander  * number of limbs (in particular, it does not skip 0s in the input).
869817466cbSJens Wiklander  */
870817466cbSJens Wiklander int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
871817466cbSJens Wiklander {
87211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
87332b31808SJens Wiklander     const size_t limbs = CHARS_TO_LIMBS(buflen);
874817466cbSJens Wiklander 
8753d3b0591SJens Wiklander     /* Ensure that target MPI has exactly the necessary number of limbs */
8767901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
8772976273fSJens Wiklander 
87832b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
879817466cbSJens Wiklander 
880817466cbSJens Wiklander cleanup:
881817466cbSJens Wiklander 
88211fa71b9SJerome Forissier     /*
88311fa71b9SJerome Forissier      * This function is also used to import keys. However, wiping the buffers
88411fa71b9SJerome Forissier      * upon failure is not necessary because failure only can happen before any
88511fa71b9SJerome Forissier      * input is copied.
88611fa71b9SJerome Forissier      */
88732b31808SJens Wiklander     return ret;
888817466cbSJens Wiklander }
889817466cbSJens Wiklander 
890817466cbSJens Wiklander /*
89111fa71b9SJerome Forissier  * Export X into unsigned binary data, little endian
89211fa71b9SJerome Forissier  */
89311fa71b9SJerome Forissier int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
89411fa71b9SJerome Forissier                                 unsigned char *buf, size_t buflen)
89511fa71b9SJerome Forissier {
89632b31808SJens Wiklander     return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
89711fa71b9SJerome Forissier }
89811fa71b9SJerome Forissier 
89911fa71b9SJerome Forissier /*
900817466cbSJens Wiklander  * Export X into unsigned binary data, big endian
901817466cbSJens Wiklander  */
9023d3b0591SJens Wiklander int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
9033d3b0591SJens Wiklander                              unsigned char *buf, size_t buflen)
904817466cbSJens Wiklander {
90532b31808SJens Wiklander     return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
906817466cbSJens Wiklander }
907817466cbSJens Wiklander 
908817466cbSJens Wiklander /*
909817466cbSJens Wiklander  * Left-shift: X <<= count
910817466cbSJens Wiklander  */
911817466cbSJens Wiklander int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
912817466cbSJens Wiklander {
91311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
914*b0563631STom Van Eyck     size_t i;
915817466cbSJens Wiklander 
916817466cbSJens Wiklander     i = mbedtls_mpi_bitlen(X) + count;
917817466cbSJens Wiklander 
91832b31808SJens Wiklander     if (X->n * biL < i) {
919817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
92032b31808SJens Wiklander     }
921817466cbSJens Wiklander 
922817466cbSJens Wiklander     ret = 0;
923817466cbSJens Wiklander 
924*b0563631STom Van Eyck     mbedtls_mpi_core_shift_l(X->p, X->n, count);
925817466cbSJens Wiklander cleanup:
926817466cbSJens Wiklander 
92732b31808SJens Wiklander     return ret;
928817466cbSJens Wiklander }
929817466cbSJens Wiklander 
930817466cbSJens Wiklander /*
931817466cbSJens Wiklander  * Right-shift: X >>= count
932817466cbSJens Wiklander  */
933817466cbSJens Wiklander int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
934817466cbSJens Wiklander {
93532b31808SJens Wiklander     if (X->n != 0) {
93632b31808SJens Wiklander         mbedtls_mpi_core_shift_r(X->p, X->n, count);
937817466cbSJens Wiklander     }
93832b31808SJens Wiklander     return 0;
939817466cbSJens Wiklander }
940817466cbSJens Wiklander 
941817466cbSJens Wiklander /*
942817466cbSJens Wiklander  * Compare unsigned values
943817466cbSJens Wiklander  */
944817466cbSJens Wiklander int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
945817466cbSJens Wiklander {
946817466cbSJens Wiklander     size_t i, j;
947817466cbSJens Wiklander 
94832b31808SJens Wiklander     for (i = X->n; i > 0; i--) {
94932b31808SJens Wiklander         if (X->p[i - 1] != 0) {
950817466cbSJens Wiklander             break;
95132b31808SJens Wiklander         }
952817466cbSJens Wiklander     }
953817466cbSJens Wiklander 
95432b31808SJens Wiklander     for (j = Y->n; j > 0; j--) {
95532b31808SJens Wiklander         if (Y->p[j - 1] != 0) {
95632b31808SJens Wiklander             break;
95732b31808SJens Wiklander         }
95832b31808SJens Wiklander     }
95932b31808SJens Wiklander 
960*b0563631STom Van Eyck     /* If i == j == 0, i.e. abs(X) == abs(Y),
961*b0563631STom Van Eyck      * we end up returning 0 at the end of the function. */
96232b31808SJens Wiklander 
96332b31808SJens Wiklander     if (i > j) {
96432b31808SJens Wiklander         return 1;
96532b31808SJens Wiklander     }
96632b31808SJens Wiklander     if (j > i) {
96732b31808SJens Wiklander         return -1;
96832b31808SJens Wiklander     }
96932b31808SJens Wiklander 
97032b31808SJens Wiklander     for (; i > 0; i--) {
97132b31808SJens Wiklander         if (X->p[i - 1] > Y->p[i - 1]) {
97232b31808SJens Wiklander             return 1;
97332b31808SJens Wiklander         }
97432b31808SJens Wiklander         if (X->p[i - 1] < Y->p[i - 1]) {
97532b31808SJens Wiklander             return -1;
97632b31808SJens Wiklander         }
97732b31808SJens Wiklander     }
97832b31808SJens Wiklander 
97932b31808SJens Wiklander     return 0;
980817466cbSJens Wiklander }
981817466cbSJens Wiklander 
982817466cbSJens Wiklander /*
983817466cbSJens Wiklander  * Compare signed values
984817466cbSJens Wiklander  */
985817466cbSJens Wiklander int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
986817466cbSJens Wiklander {
987817466cbSJens Wiklander     size_t i, j;
988817466cbSJens Wiklander 
98932b31808SJens Wiklander     for (i = X->n; i > 0; i--) {
99032b31808SJens Wiklander         if (X->p[i - 1] != 0) {
991817466cbSJens Wiklander             break;
99232b31808SJens Wiklander         }
993817466cbSJens Wiklander     }
994817466cbSJens Wiklander 
99532b31808SJens Wiklander     for (j = Y->n; j > 0; j--) {
99632b31808SJens Wiklander         if (Y->p[j - 1] != 0) {
99732b31808SJens Wiklander             break;
99832b31808SJens Wiklander         }
99932b31808SJens Wiklander     }
100032b31808SJens Wiklander 
100132b31808SJens Wiklander     if (i == 0 && j == 0) {
100232b31808SJens Wiklander         return 0;
100332b31808SJens Wiklander     }
100432b31808SJens Wiklander 
100532b31808SJens Wiklander     if (i > j) {
100632b31808SJens Wiklander         return X->s;
100732b31808SJens Wiklander     }
100832b31808SJens Wiklander     if (j > i) {
100932b31808SJens Wiklander         return -Y->s;
101032b31808SJens Wiklander     }
101132b31808SJens Wiklander 
101232b31808SJens Wiklander     if (X->s > 0 && Y->s < 0) {
101332b31808SJens Wiklander         return 1;
101432b31808SJens Wiklander     }
101532b31808SJens Wiklander     if (Y->s > 0 && X->s < 0) {
101632b31808SJens Wiklander         return -1;
101732b31808SJens Wiklander     }
101832b31808SJens Wiklander 
101932b31808SJens Wiklander     for (; i > 0; i--) {
102032b31808SJens Wiklander         if (X->p[i - 1] > Y->p[i - 1]) {
102132b31808SJens Wiklander             return X->s;
102232b31808SJens Wiklander         }
102332b31808SJens Wiklander         if (X->p[i - 1] < Y->p[i - 1]) {
102432b31808SJens Wiklander             return -X->s;
102532b31808SJens Wiklander         }
102632b31808SJens Wiklander     }
102732b31808SJens Wiklander 
102832b31808SJens Wiklander     return 0;
1029817466cbSJens Wiklander }
1030817466cbSJens Wiklander 
1031817466cbSJens Wiklander /*
1032817466cbSJens Wiklander  * Compare signed values
1033817466cbSJens Wiklander  */
1034817466cbSJens Wiklander int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
1035817466cbSJens Wiklander {
1036817466cbSJens Wiklander     mbedtls_mpi Y;
1037817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
1038817466cbSJens Wiklander 
103932b31808SJens Wiklander     *p  = mpi_sint_abs(z);
1040*b0563631STom Van Eyck     Y.s = TO_SIGN(z);
1041817466cbSJens Wiklander     Y.n = 1;
1042817466cbSJens Wiklander     Y.p = p;
1043817466cbSJens Wiklander 
104432b31808SJens Wiklander     return mbedtls_mpi_cmp_mpi(X, &Y);
1045817466cbSJens Wiklander }
1046817466cbSJens Wiklander 
1047817466cbSJens Wiklander /*
1048817466cbSJens Wiklander  * Unsigned addition: X = |A| + |B|  (HAC 14.7)
1049817466cbSJens Wiklander  */
1050817466cbSJens Wiklander int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
1051817466cbSJens Wiklander {
105211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
105332b31808SJens Wiklander     size_t j;
1054*b0563631STom Van Eyck     mbedtls_mpi_uint *p;
1055*b0563631STom Van Eyck     mbedtls_mpi_uint c;
1056817466cbSJens Wiklander 
105732b31808SJens Wiklander     if (X == B) {
1058817466cbSJens Wiklander         const mbedtls_mpi *T = A; A = X; B = T;
1059817466cbSJens Wiklander     }
1060817466cbSJens Wiklander 
106132b31808SJens Wiklander     if (X != A) {
1062817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
106332b31808SJens Wiklander     }
1064817466cbSJens Wiklander 
1065817466cbSJens Wiklander     /*
106632b31808SJens Wiklander      * X must always be positive as a result of unsigned additions.
1067817466cbSJens Wiklander      */
1068817466cbSJens Wiklander     X->s = 1;
1069817466cbSJens Wiklander 
107032b31808SJens Wiklander     for (j = B->n; j > 0; j--) {
107132b31808SJens Wiklander         if (B->p[j - 1] != 0) {
1072817466cbSJens Wiklander             break;
107332b31808SJens Wiklander         }
107432b31808SJens Wiklander     }
107532b31808SJens Wiklander 
107632b31808SJens Wiklander     /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
107732b31808SJens Wiklander      * and B is 0 (of any size). */
107832b31808SJens Wiklander     if (j == 0) {
107932b31808SJens Wiklander         return 0;
108032b31808SJens Wiklander     }
1081817466cbSJens Wiklander 
1082817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
1083817466cbSJens Wiklander 
108432b31808SJens Wiklander     /* j is the number of non-zero limbs of B. Add those to X. */
1085817466cbSJens Wiklander 
1086*b0563631STom Van Eyck     p = X->p;
108732b31808SJens Wiklander 
1088*b0563631STom Van Eyck     c = mbedtls_mpi_core_add(p, p, B->p, j);
108932b31808SJens Wiklander 
109032b31808SJens Wiklander     p += j;
109132b31808SJens Wiklander 
109232b31808SJens Wiklander     /* Now propagate any carry */
109332b31808SJens Wiklander 
109432b31808SJens Wiklander     while (c != 0) {
109532b31808SJens Wiklander         if (j >= X->n) {
109632b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
109732b31808SJens Wiklander             p = X->p + j;
1098817466cbSJens Wiklander         }
1099817466cbSJens Wiklander 
110032b31808SJens Wiklander         *p += c; c = (*p < c); j++; p++;
1101817466cbSJens Wiklander     }
1102817466cbSJens Wiklander 
1103817466cbSJens Wiklander cleanup:
1104817466cbSJens Wiklander 
110532b31808SJens Wiklander     return ret;
1106817466cbSJens Wiklander }
1107817466cbSJens Wiklander 
1108817466cbSJens Wiklander /*
11097901324dSJerome Forissier  * Unsigned subtraction: X = |A| - |B|  (HAC 14.9, 14.10)
1110817466cbSJens Wiklander  */
1111817466cbSJens Wiklander int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
1112817466cbSJens Wiklander {
111311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1114817466cbSJens Wiklander     size_t n;
11157901324dSJerome Forissier     mbedtls_mpi_uint carry;
1116817466cbSJens Wiklander 
111732b31808SJens Wiklander     for (n = B->n; n > 0; n--) {
111832b31808SJens Wiklander         if (B->p[n - 1] != 0) {
1119817466cbSJens Wiklander             break;
112032b31808SJens Wiklander         }
112132b31808SJens Wiklander     }
112232b31808SJens Wiklander     if (n > A->n) {
11237901324dSJerome Forissier         /* B >= (2^ciL)^n > A */
11247901324dSJerome Forissier         ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
11257901324dSJerome Forissier         goto cleanup;
11267901324dSJerome Forissier     }
1127817466cbSJens Wiklander 
11287901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
11297901324dSJerome Forissier 
11307901324dSJerome Forissier     /* Set the high limbs of X to match A. Don't touch the lower limbs
11317901324dSJerome Forissier      * because X might be aliased to B, and we must not overwrite the
11327901324dSJerome Forissier      * significant digits of B. */
113332b31808SJens Wiklander     if (A->n > n && A != X) {
11347901324dSJerome Forissier         memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
113532b31808SJens Wiklander     }
113632b31808SJens Wiklander     if (X->n > A->n) {
11377901324dSJerome Forissier         memset(X->p + A->n, 0, (X->n - A->n) * ciL);
113832b31808SJens Wiklander     }
11397901324dSJerome Forissier 
114032b31808SJens Wiklander     carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
114132b31808SJens Wiklander     if (carry != 0) {
114232b31808SJens Wiklander         /* Propagate the carry through the rest of X. */
114332b31808SJens Wiklander         carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
114432b31808SJens Wiklander 
114532b31808SJens Wiklander         /* If we have further carry/borrow, the result is negative. */
114632b31808SJens Wiklander         if (carry != 0) {
11477901324dSJerome Forissier             ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
11487901324dSJerome Forissier             goto cleanup;
11497901324dSJerome Forissier         }
11507901324dSJerome Forissier     }
11517901324dSJerome Forissier 
11527901324dSJerome Forissier     /* X should always be positive as a result of unsigned subtractions. */
11537901324dSJerome Forissier     X->s = 1;
1154817466cbSJens Wiklander 
1155817466cbSJens Wiklander cleanup:
115632b31808SJens Wiklander     return ret;
115732b31808SJens Wiklander }
115832b31808SJens Wiklander 
115932b31808SJens Wiklander /* Common function for signed addition and subtraction.
116032b31808SJens Wiklander  * Calculate A + B * flip_B where flip_B is 1 or -1.
116132b31808SJens Wiklander  */
116232b31808SJens Wiklander static int add_sub_mpi(mbedtls_mpi *X,
116332b31808SJens Wiklander                        const mbedtls_mpi *A, const mbedtls_mpi *B,
116432b31808SJens Wiklander                        int flip_B)
116532b31808SJens Wiklander {
116632b31808SJens Wiklander     int ret, s;
116732b31808SJens Wiklander 
116832b31808SJens Wiklander     s = A->s;
116932b31808SJens Wiklander     if (A->s * B->s * flip_B < 0) {
117032b31808SJens Wiklander         int cmp = mbedtls_mpi_cmp_abs(A, B);
117132b31808SJens Wiklander         if (cmp >= 0) {
117232b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
117332b31808SJens Wiklander             /* If |A| = |B|, the result is 0 and we must set the sign bit
117432b31808SJens Wiklander              * to +1 regardless of which of A or B was negative. Otherwise,
117532b31808SJens Wiklander              * since |A| > |B|, the sign is the sign of A. */
117632b31808SJens Wiklander             X->s = cmp == 0 ? 1 : s;
117732b31808SJens Wiklander         } else {
117832b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
117932b31808SJens Wiklander             /* Since |A| < |B|, the sign is the opposite of A. */
118032b31808SJens Wiklander             X->s = -s;
118132b31808SJens Wiklander         }
118232b31808SJens Wiklander     } else {
118332b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
118432b31808SJens Wiklander         X->s = s;
118532b31808SJens Wiklander     }
118632b31808SJens Wiklander 
118732b31808SJens Wiklander cleanup:
118832b31808SJens Wiklander 
118932b31808SJens Wiklander     return ret;
1190817466cbSJens Wiklander }
1191817466cbSJens Wiklander 
1192817466cbSJens Wiklander /*
1193817466cbSJens Wiklander  * Signed addition: X = A + B
1194817466cbSJens Wiklander  */
1195817466cbSJens Wiklander int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
1196817466cbSJens Wiklander {
119732b31808SJens Wiklander     return add_sub_mpi(X, A, B, 1);
1198817466cbSJens Wiklander }
1199817466cbSJens Wiklander 
1200817466cbSJens Wiklander /*
1201817466cbSJens Wiklander  * Signed subtraction: X = A - B
1202817466cbSJens Wiklander  */
1203817466cbSJens Wiklander int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
1204817466cbSJens Wiklander {
120532b31808SJens Wiklander     return add_sub_mpi(X, A, B, -1);
1206817466cbSJens Wiklander }
1207817466cbSJens Wiklander 
1208817466cbSJens Wiklander /*
1209817466cbSJens Wiklander  * Signed addition: X = A + b
1210817466cbSJens Wiklander  */
1211817466cbSJens Wiklander int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
1212817466cbSJens Wiklander {
1213039e02dfSJerome Forissier     mbedtls_mpi B;
1214817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
1215817466cbSJens Wiklander 
121632b31808SJens Wiklander     p[0] = mpi_sint_abs(b);
1217*b0563631STom Van Eyck     B.s = TO_SIGN(b);
1218039e02dfSJerome Forissier     B.n = 1;
1219039e02dfSJerome Forissier     B.p = p;
1220817466cbSJens Wiklander 
122132b31808SJens Wiklander     return mbedtls_mpi_add_mpi(X, A, &B);
1222817466cbSJens Wiklander }
1223817466cbSJens Wiklander 
1224817466cbSJens Wiklander /*
1225817466cbSJens Wiklander  * Signed subtraction: X = A - b
1226817466cbSJens Wiklander  */
1227817466cbSJens Wiklander int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
1228817466cbSJens Wiklander {
1229039e02dfSJerome Forissier     mbedtls_mpi B;
1230817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
1231817466cbSJens Wiklander 
123232b31808SJens Wiklander     p[0] = mpi_sint_abs(b);
1233*b0563631STom Van Eyck     B.s = TO_SIGN(b);
1234039e02dfSJerome Forissier     B.n = 1;
1235039e02dfSJerome Forissier     B.p = p;
1236817466cbSJens Wiklander 
123732b31808SJens Wiklander     return mbedtls_mpi_sub_mpi(X, A, &B);
1238817466cbSJens Wiklander }
1239817466cbSJens Wiklander 
1240817466cbSJens Wiklander /*
1241817466cbSJens Wiklander  * Baseline multiplication: X = A * B  (HAC 14.12)
1242817466cbSJens Wiklander  */
1243817466cbSJens Wiklander int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
1244817466cbSJens Wiklander {
124511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1246817466cbSJens Wiklander     size_t i, j;
1247817466cbSJens Wiklander     mbedtls_mpi TA, TB;
12487901324dSJerome Forissier     int result_is_zero = 0;
1249817466cbSJens Wiklander 
1250*b0563631STom Van Eyck     mbedtls_mpi_init_mempool(&TA);
1251*b0563631STom Van Eyck     mbedtls_mpi_init_mempool(&TB);
1252817466cbSJens Wiklander 
125332b31808SJens Wiklander     if (X == A) {
125432b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
125532b31808SJens Wiklander     }
125632b31808SJens Wiklander     if (X == B) {
125732b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
125832b31808SJens Wiklander     }
1259817466cbSJens Wiklander 
126032b31808SJens Wiklander     for (i = A->n; i > 0; i--) {
126132b31808SJens Wiklander         if (A->p[i - 1] != 0) {
1262817466cbSJens Wiklander             break;
126332b31808SJens Wiklander         }
126432b31808SJens Wiklander     }
126532b31808SJens Wiklander     if (i == 0) {
12667901324dSJerome Forissier         result_is_zero = 1;
126732b31808SJens Wiklander     }
1268817466cbSJens Wiklander 
126932b31808SJens Wiklander     for (j = B->n; j > 0; j--) {
127032b31808SJens Wiklander         if (B->p[j - 1] != 0) {
1271817466cbSJens Wiklander             break;
127232b31808SJens Wiklander         }
127332b31808SJens Wiklander     }
127432b31808SJens Wiklander     if (j == 0) {
12757901324dSJerome Forissier         result_is_zero = 1;
127632b31808SJens Wiklander     }
1277817466cbSJens Wiklander 
1278817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1279817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
1280817466cbSJens Wiklander 
1281*b0563631STom Van Eyck     mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
1282817466cbSJens Wiklander 
12837901324dSJerome Forissier     /* If the result is 0, we don't shortcut the operation, which reduces
12847901324dSJerome Forissier      * but does not eliminate side channels leaking the zero-ness. We do
12857901324dSJerome Forissier      * need to take care to set the sign bit properly since the library does
12867901324dSJerome Forissier      * not fully support an MPI object with a value of 0 and s == -1. */
128732b31808SJens Wiklander     if (result_is_zero) {
12887901324dSJerome Forissier         X->s = 1;
128932b31808SJens Wiklander     } else {
1290817466cbSJens Wiklander         X->s = A->s * B->s;
129132b31808SJens Wiklander     }
1292817466cbSJens Wiklander 
1293817466cbSJens Wiklander cleanup:
1294817466cbSJens Wiklander 
1295817466cbSJens Wiklander     mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
1296817466cbSJens Wiklander 
129732b31808SJens Wiklander     return ret;
1298817466cbSJens Wiklander }
1299817466cbSJens Wiklander 
1300817466cbSJens Wiklander /*
1301817466cbSJens Wiklander  * Baseline multiplication: X = A * b
1302817466cbSJens Wiklander  */
1303817466cbSJens Wiklander int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
1304817466cbSJens Wiklander {
13057901324dSJerome Forissier     size_t n = A->n;
130632b31808SJens Wiklander     while (n > 0 && A->p[n - 1] == 0) {
13077901324dSJerome Forissier         --n;
13087901324dSJerome Forissier     }
13097901324dSJerome Forissier 
131032b31808SJens Wiklander     /* The general method below doesn't work if b==0. */
131132b31808SJens Wiklander     if (b == 0 || n == 0) {
131232b31808SJens Wiklander         return mbedtls_mpi_lset(X, 0);
131332b31808SJens Wiklander     }
131432b31808SJens Wiklander 
131532b31808SJens Wiklander     /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
13167901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
13177901324dSJerome Forissier     /* In general, A * b requires 1 limb more than b. If
13187901324dSJerome Forissier      * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
13197901324dSJerome Forissier      * number of limbs as A and the call to grow() is not required since
13207901324dSJerome Forissier      * copy() will take care of the growth if needed. However, experimentally,
13217901324dSJerome Forissier      * making the call to grow() unconditional causes slightly fewer
13227901324dSJerome Forissier      * calls to calloc() in ECP code, presumably because it reuses the
13237901324dSJerome Forissier      * same mpi for a while and this way the mpi is more likely to directly
132432b31808SJens Wiklander      * grow to its final size.
132532b31808SJens Wiklander      *
132632b31808SJens Wiklander      * Note that calculating A*b as 0 + A*b doesn't work as-is because
132732b31808SJens Wiklander      * A,X can be the same. */
13287901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
13297901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
133032b31808SJens Wiklander     mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
13317901324dSJerome Forissier 
13327901324dSJerome Forissier cleanup:
133332b31808SJens Wiklander     return ret;
1334817466cbSJens Wiklander }
1335817466cbSJens Wiklander 
1336817466cbSJens Wiklander /*
1337817466cbSJens Wiklander  * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1338817466cbSJens Wiklander  * mbedtls_mpi_uint divisor, d
1339817466cbSJens Wiklander  */
1340817466cbSJens Wiklander static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
134132b31808SJens Wiklander                                             mbedtls_mpi_uint u0,
134232b31808SJens Wiklander                                             mbedtls_mpi_uint d,
134332b31808SJens Wiklander                                             mbedtls_mpi_uint *r)
1344817466cbSJens Wiklander {
1345817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL)
1346817466cbSJens Wiklander     mbedtls_t_udbl dividend, quotient;
1347817466cbSJens Wiklander #else
1348817466cbSJens Wiklander     const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1349817466cbSJens Wiklander     const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
1350817466cbSJens Wiklander     mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1351817466cbSJens Wiklander     mbedtls_mpi_uint u0_msw, u0_lsw;
1352817466cbSJens Wiklander     size_t s;
1353817466cbSJens Wiklander #endif
1354817466cbSJens Wiklander 
1355817466cbSJens Wiklander     /*
1356817466cbSJens Wiklander      * Check for overflow
1357817466cbSJens Wiklander      */
135832b31808SJens Wiklander     if (0 == d || u1 >= d) {
135932b31808SJens Wiklander         if (r != NULL) {
136032b31808SJens Wiklander             *r = ~(mbedtls_mpi_uint) 0u;
136132b31808SJens Wiklander         }
1362817466cbSJens Wiklander 
136332b31808SJens Wiklander         return ~(mbedtls_mpi_uint) 0u;
1364817466cbSJens Wiklander     }
1365817466cbSJens Wiklander 
1366817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL)
1367817466cbSJens Wiklander     dividend  = (mbedtls_t_udbl) u1 << biL;
1368817466cbSJens Wiklander     dividend |= (mbedtls_t_udbl) u0;
1369817466cbSJens Wiklander     quotient = dividend / d;
137032b31808SJens Wiklander     if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1371817466cbSJens Wiklander         quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
137232b31808SJens Wiklander     }
1373817466cbSJens Wiklander 
137432b31808SJens Wiklander     if (r != NULL) {
1375817466cbSJens Wiklander         *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
137632b31808SJens Wiklander     }
1377817466cbSJens Wiklander 
1378817466cbSJens Wiklander     return (mbedtls_mpi_uint) quotient;
1379817466cbSJens Wiklander #else
1380817466cbSJens Wiklander 
1381817466cbSJens Wiklander     /*
1382817466cbSJens Wiklander      * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1383817466cbSJens Wiklander      *   Vol. 2 - Seminumerical Algorithms, Knuth
1384817466cbSJens Wiklander      */
1385817466cbSJens Wiklander 
1386817466cbSJens Wiklander     /*
1387817466cbSJens Wiklander      * Normalize the divisor, d, and dividend, u0, u1
1388817466cbSJens Wiklander      */
138932b31808SJens Wiklander     s = mbedtls_mpi_core_clz(d);
1390817466cbSJens Wiklander     d = d << s;
1391817466cbSJens Wiklander 
1392817466cbSJens Wiklander     u1 = u1 << s;
1393817466cbSJens Wiklander     u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
1394817466cbSJens Wiklander     u0 =  u0 << s;
1395817466cbSJens Wiklander 
1396817466cbSJens Wiklander     d1 = d >> biH;
1397817466cbSJens Wiklander     d0 = d & uint_halfword_mask;
1398817466cbSJens Wiklander 
1399817466cbSJens Wiklander     u0_msw = u0 >> biH;
1400817466cbSJens Wiklander     u0_lsw = u0 & uint_halfword_mask;
1401817466cbSJens Wiklander 
1402817466cbSJens Wiklander     /*
1403817466cbSJens Wiklander      * Find the first quotient and remainder
1404817466cbSJens Wiklander      */
1405817466cbSJens Wiklander     q1 = u1 / d1;
1406817466cbSJens Wiklander     r0 = u1 - d1 * q1;
1407817466cbSJens Wiklander 
140832b31808SJens Wiklander     while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
1409817466cbSJens Wiklander         q1 -= 1;
1410817466cbSJens Wiklander         r0 += d1;
1411817466cbSJens Wiklander 
141232b31808SJens Wiklander         if (r0 >= radix) {
141332b31808SJens Wiklander             break;
141432b31808SJens Wiklander         }
1415817466cbSJens Wiklander     }
1416817466cbSJens Wiklander 
1417817466cbSJens Wiklander     rAX = (u1 * radix) + (u0_msw - q1 * d);
1418817466cbSJens Wiklander     q0 = rAX / d1;
1419817466cbSJens Wiklander     r0 = rAX - q0 * d1;
1420817466cbSJens Wiklander 
142132b31808SJens Wiklander     while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
1422817466cbSJens Wiklander         q0 -= 1;
1423817466cbSJens Wiklander         r0 += d1;
1424817466cbSJens Wiklander 
142532b31808SJens Wiklander         if (r0 >= radix) {
142632b31808SJens Wiklander             break;
142732b31808SJens Wiklander         }
1428817466cbSJens Wiklander     }
1429817466cbSJens Wiklander 
143032b31808SJens Wiklander     if (r != NULL) {
1431817466cbSJens Wiklander         *r = (rAX * radix + u0_lsw - q0 * d) >> s;
143232b31808SJens Wiklander     }
1433817466cbSJens Wiklander 
1434817466cbSJens Wiklander     quotient = q1 * radix + q0;
1435817466cbSJens Wiklander 
1436817466cbSJens Wiklander     return quotient;
1437817466cbSJens Wiklander #endif
1438817466cbSJens Wiklander }
1439817466cbSJens Wiklander 
1440817466cbSJens Wiklander /*
1441817466cbSJens Wiklander  * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)
1442817466cbSJens Wiklander  */
14433d3b0591SJens Wiklander int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
14443d3b0591SJens Wiklander                         const mbedtls_mpi *B)
1445817466cbSJens Wiklander {
144611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1447817466cbSJens Wiklander     size_t i, n, t, k;
1448817466cbSJens Wiklander     mbedtls_mpi X, Y, Z, T1, T2;
144911fa71b9SJerome Forissier     mbedtls_mpi_uint TP2[3];
1450817466cbSJens Wiklander 
145132b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(B, 0) == 0) {
145232b31808SJens Wiklander         return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
145332b31808SJens Wiklander     }
1454817466cbSJens Wiklander 
145598bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&X); mbedtls_mpi_init_mempool(&Y);
145698bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&Z); mbedtls_mpi_init_mempool(&T1);
145711fa71b9SJerome Forissier     /*
145811fa71b9SJerome Forissier      * Avoid dynamic memory allocations for constant-size T2.
145911fa71b9SJerome Forissier      *
146011fa71b9SJerome Forissier      * T2 is used for comparison only and the 3 limbs are assigned explicitly,
146111fa71b9SJerome Forissier      * so nobody increase the size of the MPI and we're safe to use an on-stack
146211fa71b9SJerome Forissier      * buffer.
146311fa71b9SJerome Forissier      */
146411fa71b9SJerome Forissier     T2.s = 1;
146511fa71b9SJerome Forissier     T2.n = sizeof(TP2) / sizeof(*TP2);
146611fa71b9SJerome Forissier     T2.p = TP2;
1467817466cbSJens Wiklander 
146832b31808SJens Wiklander     if (mbedtls_mpi_cmp_abs(A, B) < 0) {
146932b31808SJens Wiklander         if (Q != NULL) {
147032b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
147132b31808SJens Wiklander         }
147232b31808SJens Wiklander         if (R != NULL) {
147332b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
147432b31808SJens Wiklander         }
147532b31808SJens Wiklander         return 0;
1476817466cbSJens Wiklander     }
1477817466cbSJens Wiklander 
1478817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1479817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
1480817466cbSJens Wiklander     X.s = Y.s = 1;
1481817466cbSJens Wiklander 
1482817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1483817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z,  0));
14847901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
1485817466cbSJens Wiklander 
1486817466cbSJens Wiklander     k = mbedtls_mpi_bitlen(&Y) % biL;
148732b31808SJens Wiklander     if (k < biL - 1) {
1488817466cbSJens Wiklander         k = biL - 1 - k;
1489817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1490817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
149132b31808SJens Wiklander     } else {
149232b31808SJens Wiklander         k = 0;
1493817466cbSJens Wiklander     }
1494817466cbSJens Wiklander 
1495817466cbSJens Wiklander     n = X.n - 1;
1496817466cbSJens Wiklander     t = Y.n - 1;
1497817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
1498817466cbSJens Wiklander 
149932b31808SJens Wiklander     while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
1500817466cbSJens Wiklander         Z.p[n - t]++;
1501817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
1502817466cbSJens Wiklander     }
1503817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
1504817466cbSJens Wiklander 
150532b31808SJens Wiklander     for (i = n; i > t; i--) {
150632b31808SJens Wiklander         if (X.p[i] >= Y.p[t]) {
150732b31808SJens Wiklander             Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
150832b31808SJens Wiklander         } else {
1509817466cbSJens Wiklander             Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1510817466cbSJens Wiklander                                                  Y.p[t], NULL);
1511817466cbSJens Wiklander         }
1512817466cbSJens Wiklander 
151311fa71b9SJerome Forissier         T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
151411fa71b9SJerome Forissier         T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
151511fa71b9SJerome Forissier         T2.p[2] = X.p[i];
151611fa71b9SJerome Forissier 
1517817466cbSJens Wiklander         Z.p[i - t - 1]++;
151832b31808SJens Wiklander         do {
1519817466cbSJens Wiklander             Z.p[i - t - 1]--;
1520817466cbSJens Wiklander 
1521817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1522817466cbSJens Wiklander             T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1523817466cbSJens Wiklander             T1.p[1] = Y.p[t];
1524817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
152532b31808SJens Wiklander         } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
1526817466cbSJens Wiklander 
1527817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1528817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1,  biL * (i - t - 1)));
1529817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
1530817466cbSJens Wiklander 
153132b31808SJens Wiklander         if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1532817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1533817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1534817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
1535817466cbSJens Wiklander             Z.p[i - t - 1]--;
1536817466cbSJens Wiklander         }
1537817466cbSJens Wiklander     }
1538817466cbSJens Wiklander 
153932b31808SJens Wiklander     if (Q != NULL) {
1540817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
1541817466cbSJens Wiklander         Q->s = A->s * B->s;
1542817466cbSJens Wiklander     }
1543817466cbSJens Wiklander 
154432b31808SJens Wiklander     if (R != NULL) {
1545817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
1546817466cbSJens Wiklander         X.s = A->s;
1547817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
1548817466cbSJens Wiklander 
154932b31808SJens Wiklander         if (mbedtls_mpi_cmp_int(R, 0) == 0) {
1550817466cbSJens Wiklander             R->s = 1;
1551817466cbSJens Wiklander         }
155232b31808SJens Wiklander     }
1553817466cbSJens Wiklander 
1554817466cbSJens Wiklander cleanup:
1555817466cbSJens Wiklander 
1556817466cbSJens Wiklander     mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
155711fa71b9SJerome Forissier     mbedtls_mpi_free(&T1);
155811fa71b9SJerome Forissier     mbedtls_platform_zeroize(TP2, sizeof(TP2));
1559817466cbSJens Wiklander 
156032b31808SJens Wiklander     return ret;
1561817466cbSJens Wiklander }
1562817466cbSJens Wiklander 
1563817466cbSJens Wiklander /*
1564817466cbSJens Wiklander  * Division by int: A = Q * b + R
1565817466cbSJens Wiklander  */
15663d3b0591SJens Wiklander int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
15673d3b0591SJens Wiklander                         const mbedtls_mpi *A,
15683d3b0591SJens Wiklander                         mbedtls_mpi_sint b)
1569817466cbSJens Wiklander {
1570039e02dfSJerome Forissier     mbedtls_mpi B;
1571817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
1572817466cbSJens Wiklander 
157332b31808SJens Wiklander     p[0] = mpi_sint_abs(b);
1574*b0563631STom Van Eyck     B.s = TO_SIGN(b);
1575039e02dfSJerome Forissier     B.n = 1;
1576039e02dfSJerome Forissier     B.p = p;
1577817466cbSJens Wiklander 
157832b31808SJens Wiklander     return mbedtls_mpi_div_mpi(Q, R, A, &B);
1579817466cbSJens Wiklander }
1580817466cbSJens Wiklander 
1581817466cbSJens Wiklander /*
1582817466cbSJens Wiklander  * Modulo: R = A mod B
1583817466cbSJens Wiklander  */
1584817466cbSJens Wiklander int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
1585817466cbSJens Wiklander {
158611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1587817466cbSJens Wiklander 
158832b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(B, 0) < 0) {
158932b31808SJens Wiklander         return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
159032b31808SJens Wiklander     }
1591817466cbSJens Wiklander 
1592817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
1593817466cbSJens Wiklander 
159432b31808SJens Wiklander     while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1595817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
159632b31808SJens Wiklander     }
1597817466cbSJens Wiklander 
159832b31808SJens Wiklander     while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1599817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
160032b31808SJens Wiklander     }
1601817466cbSJens Wiklander 
1602817466cbSJens Wiklander cleanup:
1603817466cbSJens Wiklander 
160432b31808SJens Wiklander     return ret;
1605817466cbSJens Wiklander }
1606817466cbSJens Wiklander 
1607817466cbSJens Wiklander /*
1608817466cbSJens Wiklander  * Modulo: r = A mod b
1609817466cbSJens Wiklander  */
1610817466cbSJens Wiklander int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
1611817466cbSJens Wiklander {
1612817466cbSJens Wiklander     size_t i;
1613817466cbSJens Wiklander     mbedtls_mpi_uint x, y, z;
1614817466cbSJens Wiklander 
161532b31808SJens Wiklander     if (b == 0) {
161632b31808SJens Wiklander         return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
161732b31808SJens Wiklander     }
1618817466cbSJens Wiklander 
161932b31808SJens Wiklander     if (b < 0) {
162032b31808SJens Wiklander         return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
162132b31808SJens Wiklander     }
1622817466cbSJens Wiklander 
1623817466cbSJens Wiklander     /*
1624817466cbSJens Wiklander      * handle trivial cases
1625817466cbSJens Wiklander      */
162632b31808SJens Wiklander     if (b == 1 || A->n == 0) {
1627817466cbSJens Wiklander         *r = 0;
162832b31808SJens Wiklander         return 0;
1629817466cbSJens Wiklander     }
1630817466cbSJens Wiklander 
163132b31808SJens Wiklander     if (b == 2) {
1632817466cbSJens Wiklander         *r = A->p[0] & 1;
163332b31808SJens Wiklander         return 0;
1634817466cbSJens Wiklander     }
1635817466cbSJens Wiklander 
1636817466cbSJens Wiklander     /*
1637817466cbSJens Wiklander      * general case
1638817466cbSJens Wiklander      */
163932b31808SJens Wiklander     for (i = A->n, y = 0; i > 0; i--) {
1640817466cbSJens Wiklander         x  = A->p[i - 1];
1641817466cbSJens Wiklander         y  = (y << biH) | (x >> biH);
1642817466cbSJens Wiklander         z  = y / b;
1643817466cbSJens Wiklander         y -= z * b;
1644817466cbSJens Wiklander 
1645817466cbSJens Wiklander         x <<= biH;
1646817466cbSJens Wiklander         y  = (y << biH) | (x >> biH);
1647817466cbSJens Wiklander         z  = y / b;
1648817466cbSJens Wiklander         y -= z * b;
1649817466cbSJens Wiklander     }
1650817466cbSJens Wiklander 
1651817466cbSJens Wiklander     /*
1652817466cbSJens Wiklander      * If A is negative, then the current y represents a negative value.
1653817466cbSJens Wiklander      * Flipping it to the positive side.
1654817466cbSJens Wiklander      */
165532b31808SJens Wiklander     if (A->s < 0 && y != 0) {
1656817466cbSJens Wiklander         y = b - y;
165732b31808SJens Wiklander     }
1658817466cbSJens Wiklander 
1659817466cbSJens Wiklander     *r = y;
1660817466cbSJens Wiklander 
166132b31808SJens Wiklander     return 0;
1662817466cbSJens Wiklander }
1663817466cbSJens Wiklander 
1664*b0563631STom Van Eyck /**
1665*b0563631STom Van Eyck  * \remark Replaced by our own because the original has been removed since
1666*b0563631STom Van Eyck  *         mbedtls v3.6.0.
1667*b0563631STom Van Eyck */
16687901324dSJerome Forissier void mbedtls_mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
16697901324dSJerome Forissier {
1670*b0563631STom Van Eyck     *mm = mbedtls_mpi_core_montmul_init(N->p);
16717901324dSJerome Forissier }
16727901324dSJerome Forissier 
16737901324dSJerome Forissier /** Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
16747901324dSJerome Forissier  *
16757901324dSJerome Forissier  * \param[in,out]   A   One of the numbers to multiply.
16767901324dSJerome Forissier  *                      It must have at least as many limbs as N
16777901324dSJerome Forissier  *                      (A->n >= N->n), and any limbs beyond n are ignored.
16787901324dSJerome Forissier  *                      On successful completion, A contains the result of
16797901324dSJerome Forissier  *                      the multiplication A * B * R^-1 mod N where
16807901324dSJerome Forissier  *                      R = (2^ciL)^n.
16817901324dSJerome Forissier  * \param[in]       B   One of the numbers to multiply.
16827901324dSJerome Forissier  *                      It must be nonzero and must not have more limbs than N
16837901324dSJerome Forissier  *                      (B->n <= N->n).
168432b31808SJens Wiklander  * \param[in]       N   The modulus. \p N must be odd.
16857901324dSJerome Forissier  * \param           mm  The value calculated by `mpi_montg_init(&mm, N)`.
16867901324dSJerome Forissier  *                      This is -N^-1 mod 2^ciL.
16877901324dSJerome Forissier  * \param[in,out]   T   A bignum for temporary storage.
168832b31808SJens Wiklander  *                      It must be at least twice the limb size of N plus 1
168932b31808SJens Wiklander  *                      (T->n >= 2 * N->n + 1).
16907901324dSJerome Forissier  *                      Its initial content is unused and
16917901324dSJerome Forissier  *                      its final content is indeterminate.
169232b31808SJens Wiklander  *                      It does not get reallocated.
1693*b0563631STom Van Eyck  * \remark Replaced by our own because the original has been removed since
1694*b0563631STom Van Eyck  *         mbedtls v3.6.0.
1695817466cbSJens Wiklander  */
1696*b0563631STom Van Eyck void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
169732b31808SJens Wiklander                         const mbedtls_mpi *N, mbedtls_mpi_uint mm,
169832b31808SJens Wiklander                         mbedtls_mpi *T)
1699817466cbSJens Wiklander {
170032b31808SJens Wiklander     mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
1701817466cbSJens Wiklander }
1702817466cbSJens Wiklander 
1703*b0563631STom Van Eyck /**
1704817466cbSJens Wiklander  * Montgomery reduction: A = A * R^-1 mod N
17057901324dSJerome Forissier  *
1706*b0563631STom Van Eyck  * See mbedtls_mpi_montmul() regarding constraints and guarantees on the parameters.
1707*b0563631STom Van Eyck  *
1708*b0563631STom Van Eyck  * \remark Replaced by our own because the original has been removed since
1709*b0563631STom Van Eyck  *         mbedtls v3.6.0.
1710817466cbSJens Wiklander  */
1711*b0563631STom Van Eyck void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
171232b31808SJens Wiklander                         mbedtls_mpi_uint mm, mbedtls_mpi *T)
1713817466cbSJens Wiklander {
1714817466cbSJens Wiklander     mbedtls_mpi_uint z = 1;
1715817466cbSJens Wiklander     mbedtls_mpi U;
1716817466cbSJens Wiklander 
1717817466cbSJens Wiklander     U.n = U.s = (int) z;
1718817466cbSJens Wiklander     U.p = &z;
1719817466cbSJens Wiklander 
1720*b0563631STom Van Eyck     mbedtls_mpi_montmul(A, &U, N, mm, T);
17217901324dSJerome Forissier }
17227901324dSJerome Forissier 
17237901324dSJerome Forissier /**
17247901324dSJerome Forissier  * Select an MPI from a table without leaking the index.
17257901324dSJerome Forissier  *
17267901324dSJerome Forissier  * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
17277901324dSJerome Forissier  * reads the entire table in order to avoid leaking the value of idx to an
17287901324dSJerome Forissier  * attacker able to observe memory access patterns.
17297901324dSJerome Forissier  *
17307901324dSJerome Forissier  * \param[out] R        Where to write the selected MPI.
17317901324dSJerome Forissier  * \param[in] T         The table to read from.
17327901324dSJerome Forissier  * \param[in] T_size    The number of elements in the table.
17337901324dSJerome Forissier  * \param[in] idx       The index of the element to select;
17347901324dSJerome Forissier  *                      this must satisfy 0 <= idx < T_size.
17357901324dSJerome Forissier  *
17367901324dSJerome Forissier  * \return \c 0 on success, or a negative error code.
17377901324dSJerome Forissier  */
17387901324dSJerome Forissier static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
17397901324dSJerome Forissier {
17407901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
17417901324dSJerome Forissier 
174232b31808SJens Wiklander     for (size_t i = 0; i < T_size; i++) {
17437901324dSJerome Forissier         MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
1744*b0563631STom Van Eyck                                                      (unsigned char) mbedtls_ct_uint_eq(i, idx)));
17457901324dSJerome Forissier     }
17467901324dSJerome Forissier cleanup:
174732b31808SJens Wiklander     return ret;
1748817466cbSJens Wiklander }
1749817466cbSJens Wiklander 
1750817466cbSJens Wiklander /*
1751817466cbSJens Wiklander  * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
1752817466cbSJens Wiklander  */
17533d3b0591SJens Wiklander int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
17543d3b0591SJens Wiklander                         const mbedtls_mpi *E, const mbedtls_mpi *N,
1755039e02dfSJerome Forissier                         mbedtls_mpi *prec_RR)
1756817466cbSJens Wiklander {
175711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
175832b31808SJens Wiklander     size_t window_bitsize;
1759817466cbSJens Wiklander     size_t i, j, nblimbs;
1760817466cbSJens Wiklander     size_t bufsize, nbits;
176132b31808SJens Wiklander     size_t exponent_bits_in_window = 0;
1762817466cbSJens Wiklander     mbedtls_mpi_uint ei, mm, state;
1763*b0563631STom Van Eyck     mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
1764817466cbSJens Wiklander     int neg;
1765817466cbSJens Wiklander 
176632b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
176732b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
176832b31808SJens Wiklander     }
1769817466cbSJens Wiklander 
177032b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(E, 0) < 0) {
177132b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
177232b31808SJens Wiklander     }
1773817466cbSJens Wiklander 
17747901324dSJerome Forissier     if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
177532b31808SJens Wiklander         mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
177632b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
177732b31808SJens Wiklander     }
17787901324dSJerome Forissier 
1779817466cbSJens Wiklander     /*
1780817466cbSJens Wiklander      * Init temps and window size
1781817466cbSJens Wiklander      */
1782*b0563631STom Van Eyck     mbedtls_mpi_montg_init(&mm, N);
1783*b0563631STom Van Eyck     mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
1784*b0563631STom Van Eyck     mbedtls_mpi_init(&Apos);
1785*b0563631STom Van Eyck     mbedtls_mpi_init(&WW);
1786*b0563631STom Van Eyck     memset(W, 0, sizeof(W));
1787817466cbSJens Wiklander 
1788817466cbSJens Wiklander     i = mbedtls_mpi_bitlen(E);
1789817466cbSJens Wiklander 
179032b31808SJens Wiklander     window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1791817466cbSJens Wiklander                      (i >  79) ? 4 : (i >  23) ? 3 : 1;
1792817466cbSJens Wiklander 
17935b25c76aSJerome Forissier #if (MBEDTLS_MPI_WINDOW_SIZE < 6)
179432b31808SJens Wiklander     if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
179532b31808SJens Wiklander         window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
179632b31808SJens Wiklander     }
17975b25c76aSJerome Forissier #endif
1798817466cbSJens Wiklander 
179932b31808SJens Wiklander     const size_t w_table_used_size = (size_t) 1 << window_bitsize;
1800817466cbSJens Wiklander 
180132b31808SJens Wiklander     /*
180232b31808SJens Wiklander      * This function is not constant-trace: its memory accesses depend on the
180332b31808SJens Wiklander      * exponent value. To defend against timing attacks, callers (such as RSA
180432b31808SJens Wiklander      * and DHM) should use exponent blinding. However this is not enough if the
180532b31808SJens Wiklander      * adversary can find the exponent in a single trace, so this function
180632b31808SJens Wiklander      * takes extra precautions against adversaries who can observe memory
180732b31808SJens Wiklander      * access patterns.
180832b31808SJens Wiklander      *
180932b31808SJens Wiklander      * This function performs a series of multiplications by table elements and
181032b31808SJens Wiklander      * squarings, and we want the prevent the adversary from finding out which
181132b31808SJens Wiklander      * table element was used, and from distinguishing between multiplications
181232b31808SJens Wiklander      * and squarings. Firstly, when multiplying by an element of the window
181332b31808SJens Wiklander      * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
181432b31808SJens Wiklander      * squarings as having a different memory access patterns from other
1815*b0563631STom Van Eyck      * multiplications. So secondly, we put the accumulator in the table as
1816*b0563631STom Van Eyck      * well, and also do a constant-trace table lookup to multiply by the
1817*b0563631STom Van Eyck      * accumulator which is W[x_index].
181832b31808SJens Wiklander      *
181932b31808SJens Wiklander      * This way, all multiplications take the form of a lookup-and-multiply.
182032b31808SJens Wiklander      * The number of lookup-and-multiply operations inside each iteration of
182132b31808SJens Wiklander      * the main loop still depends on the bits of the exponent, but since the
182232b31808SJens Wiklander      * other operations in the loop don't have an easily recognizable memory
182332b31808SJens Wiklander      * trace, an adversary is unlikely to be able to observe the exact
182432b31808SJens Wiklander      * patterns.
182532b31808SJens Wiklander      *
182632b31808SJens Wiklander      * An adversary may still be able to recover the exponent if they can
182732b31808SJens Wiklander      * observe both memory accesses and branches. However, branch prediction
182832b31808SJens Wiklander      * exploitation typically requires many traces of execution over the same
182932b31808SJens Wiklander      * data, which is defeated by randomized blinding.
183032b31808SJens Wiklander      */
183132b31808SJens Wiklander     const size_t x_index = 0;
1832*b0563631STom Van Eyck     mbedtls_mpi_init(&W[x_index]);
183332b31808SJens Wiklander 
183432b31808SJens Wiklander     j = N->n + 1;
1835*b0563631STom Van Eyck     /* All W[i] including the accumulator must have at least N->n limbs for
1836*b0563631STom Van Eyck      * the mbedtls_mpi_montmul() and mbedtls_mpi_montred() calls later.
1837*b0563631STom Van Eyck      * Here we ensure that
1838*b0563631STom Van Eyck      * W[1] and the accumulator W[x_index] are large enough. later we'll grow
1839*b0563631STom Van Eyck      * other W[i] to the same length. They must not be shrunk midway through
1840*b0563631STom Van Eyck      * this function!
184132b31808SJens Wiklander      */
184232b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1843*b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1],  j));
184432b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
184532b31808SJens Wiklander 
184632b31808SJens Wiklander     /*
184732b31808SJens Wiklander      * Compensate for negative A (and correct at the end)
184832b31808SJens Wiklander      */
184932b31808SJens Wiklander     neg = (A->s == -1);
185032b31808SJens Wiklander     if (neg) {
185132b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
185232b31808SJens Wiklander         Apos.s = 1;
185332b31808SJens Wiklander         A = &Apos;
185432b31808SJens Wiklander     }
185532b31808SJens Wiklander 
185632b31808SJens Wiklander     /*
185732b31808SJens Wiklander      * If 1st call, pre-compute R^2 mod N
185832b31808SJens Wiklander      */
185932b31808SJens Wiklander     if (prec_RR == NULL || prec_RR->p == NULL) {
186032b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
186132b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
186232b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
186332b31808SJens Wiklander 
186432b31808SJens Wiklander         if (prec_RR != NULL) {
186532b31808SJens Wiklander             memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
186632b31808SJens Wiklander         }
186732b31808SJens Wiklander     } else {
186832b31808SJens Wiklander         memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
186932b31808SJens Wiklander     }
187032b31808SJens Wiklander 
1871817466cbSJens Wiklander     /*
1872817466cbSJens Wiklander      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1873817466cbSJens Wiklander      */
187432b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1875817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
18767901324dSJerome Forissier         /* This should be a no-op because W[1] is already that large before
18777901324dSJerome Forissier          * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
1878*b0563631STom Van Eyck          * in mbedtls_mpi_montmul() below, so let's make sure. */
18797901324dSJerome Forissier         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
188032b31808SJens Wiklander     } else {
1881817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
188232b31808SJens Wiklander     }
1883817466cbSJens Wiklander 
18847901324dSJerome Forissier     /* Note that this is safe because W[1] always has at least N->n limbs
18857901324dSJerome Forissier      * (it grew above and was preserved by mbedtls_mpi_copy()). */
1886*b0563631STom Van Eyck     mbedtls_mpi_montmul(&W[1], &RR, N, mm, &T);
1887817466cbSJens Wiklander 
1888817466cbSJens Wiklander     /*
188932b31808SJens Wiklander      * W[x_index] = R^2 * R^-1 mod N = R mod N
1890817466cbSJens Wiklander      */
189132b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1892*b0563631STom Van Eyck     mbedtls_mpi_montred(&W[x_index], N, mm, &T);
1893817466cbSJens Wiklander 
189432b31808SJens Wiklander 
189532b31808SJens Wiklander     if (window_bitsize > 1) {
1896817466cbSJens Wiklander         /*
189732b31808SJens Wiklander          * W[i] = W[1] ^ i
189832b31808SJens Wiklander          *
189932b31808SJens Wiklander          * The first bit of the sliding window is always 1 and therefore we
190032b31808SJens Wiklander          * only need to store the second half of the table.
190132b31808SJens Wiklander          *
190232b31808SJens Wiklander          * (There are two special elements in the table: W[0] for the
190332b31808SJens Wiklander          * accumulator/result and W[1] for A in Montgomery form. Both of these
190432b31808SJens Wiklander          * are already set at this point.)
1905817466cbSJens Wiklander          */
190632b31808SJens Wiklander         j = w_table_used_size / 2;
1907817466cbSJens Wiklander 
1908817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1909817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
1910817466cbSJens Wiklander 
191132b31808SJens Wiklander         for (i = 0; i < window_bitsize - 1; i++) {
1912*b0563631STom Van Eyck             mbedtls_mpi_montmul(&W[j], &W[j], N, mm, &T);
191332b31808SJens Wiklander         }
1914817466cbSJens Wiklander 
1915817466cbSJens Wiklander         /*
1916817466cbSJens Wiklander          * W[i] = W[i - 1] * W[1]
1917817466cbSJens Wiklander          */
191832b31808SJens Wiklander         for (i = j + 1; i < w_table_used_size; i++) {
1919817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1920817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
1921817466cbSJens Wiklander 
1922*b0563631STom Van Eyck             mbedtls_mpi_montmul(&W[i], &W[1], N, mm, &T);
1923817466cbSJens Wiklander         }
1924817466cbSJens Wiklander     }
1925817466cbSJens Wiklander 
1926817466cbSJens Wiklander     nblimbs = E->n;
1927817466cbSJens Wiklander     bufsize = 0;
1928817466cbSJens Wiklander     nbits   = 0;
1929817466cbSJens Wiklander     state   = 0;
1930817466cbSJens Wiklander 
193132b31808SJens Wiklander     while (1) {
193232b31808SJens Wiklander         if (bufsize == 0) {
193332b31808SJens Wiklander             if (nblimbs == 0) {
1934817466cbSJens Wiklander                 break;
193532b31808SJens Wiklander             }
1936817466cbSJens Wiklander 
1937817466cbSJens Wiklander             nblimbs--;
1938817466cbSJens Wiklander 
1939817466cbSJens Wiklander             bufsize = sizeof(mbedtls_mpi_uint) << 3;
1940817466cbSJens Wiklander         }
1941817466cbSJens Wiklander 
1942817466cbSJens Wiklander         bufsize--;
1943817466cbSJens Wiklander 
1944817466cbSJens Wiklander         ei = (E->p[nblimbs] >> bufsize) & 1;
1945817466cbSJens Wiklander 
1946817466cbSJens Wiklander         /*
1947817466cbSJens Wiklander          * skip leading 0s
1948817466cbSJens Wiklander          */
194932b31808SJens Wiklander         if (ei == 0 && state == 0) {
1950817466cbSJens Wiklander             continue;
195132b31808SJens Wiklander         }
1952817466cbSJens Wiklander 
195332b31808SJens Wiklander         if (ei == 0 && state == 1) {
1954817466cbSJens Wiklander             /*
195532b31808SJens Wiklander              * out of window, square W[x_index]
1956817466cbSJens Wiklander              */
195732b31808SJens Wiklander             MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1958*b0563631STom Van Eyck             mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
1959817466cbSJens Wiklander             continue;
1960817466cbSJens Wiklander         }
1961817466cbSJens Wiklander 
1962817466cbSJens Wiklander         /*
1963817466cbSJens Wiklander          * add ei to current window
1964817466cbSJens Wiklander          */
1965817466cbSJens Wiklander         state = 2;
1966817466cbSJens Wiklander 
1967817466cbSJens Wiklander         nbits++;
196832b31808SJens Wiklander         exponent_bits_in_window |= (ei << (window_bitsize - nbits));
1969817466cbSJens Wiklander 
197032b31808SJens Wiklander         if (nbits == window_bitsize) {
1971817466cbSJens Wiklander             /*
197232b31808SJens Wiklander              * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
1973817466cbSJens Wiklander              */
197432b31808SJens Wiklander             for (i = 0; i < window_bitsize; i++) {
197532b31808SJens Wiklander                 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
197632b31808SJens Wiklander                                            x_index));
1977*b0563631STom Van Eyck                 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
197832b31808SJens Wiklander             }
1979817466cbSJens Wiklander 
1980817466cbSJens Wiklander             /*
198132b31808SJens Wiklander              * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
1982817466cbSJens Wiklander              */
198332b31808SJens Wiklander             MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
198432b31808SJens Wiklander                                        exponent_bits_in_window));
1985*b0563631STom Van Eyck             mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
1986817466cbSJens Wiklander 
1987817466cbSJens Wiklander             state--;
1988817466cbSJens Wiklander             nbits = 0;
198932b31808SJens Wiklander             exponent_bits_in_window = 0;
1990817466cbSJens Wiklander         }
1991817466cbSJens Wiklander     }
1992817466cbSJens Wiklander 
1993817466cbSJens Wiklander     /*
1994817466cbSJens Wiklander      * process the remaining bits
1995817466cbSJens Wiklander      */
199632b31808SJens Wiklander     for (i = 0; i < nbits; i++) {
199732b31808SJens Wiklander         MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1998*b0563631STom Van Eyck         mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
1999817466cbSJens Wiklander 
200032b31808SJens Wiklander         exponent_bits_in_window <<= 1;
2001817466cbSJens Wiklander 
200232b31808SJens Wiklander         if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
200332b31808SJens Wiklander             MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
2004*b0563631STom Van Eyck             mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
200532b31808SJens Wiklander         }
2006817466cbSJens Wiklander     }
2007817466cbSJens Wiklander 
2008817466cbSJens Wiklander     /*
200932b31808SJens Wiklander      * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
2010817466cbSJens Wiklander      */
2011*b0563631STom Van Eyck     mbedtls_mpi_montred(&W[x_index], N, mm, &T);
2012817466cbSJens Wiklander 
201332b31808SJens Wiklander     if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
201432b31808SJens Wiklander         W[x_index].s = -1;
201532b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
2016817466cbSJens Wiklander     }
2017817466cbSJens Wiklander 
201832b31808SJens Wiklander     /*
201932b31808SJens Wiklander      * Load the result in the output variable.
202032b31808SJens Wiklander      */
2021*b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
202232b31808SJens Wiklander 
2023817466cbSJens Wiklander cleanup:
2024817466cbSJens Wiklander 
2025*b0563631STom Van Eyck     /* The first bit of the sliding window is always 1 and therefore the first
2026*b0563631STom Van Eyck      * half of the table was unused. */
2027*b0563631STom Van Eyck     for (i = w_table_used_size/2; i < w_table_used_size; i++) {
2028*b0563631STom Van Eyck         mbedtls_mpi_free(&W[i]);
2029*b0563631STom Van Eyck     }
2030817466cbSJens Wiklander 
2031*b0563631STom Van Eyck     mbedtls_mpi_free(&W[x_index]);
2032*b0563631STom Van Eyck     mbedtls_mpi_free(&W[1]);
203332b31808SJens Wiklander     mbedtls_mpi_free(&T);
203432b31808SJens Wiklander     mbedtls_mpi_free(&Apos);
20357901324dSJerome Forissier     mbedtls_mpi_free(&WW);
2036817466cbSJens Wiklander 
203732b31808SJens Wiklander     if (prec_RR == NULL || prec_RR->p == NULL) {
2038817466cbSJens Wiklander         mbedtls_mpi_free(&RR);
203932b31808SJens Wiklander     }
2040817466cbSJens Wiklander 
204132b31808SJens Wiklander     return ret;
2042817466cbSJens Wiklander }
2043817466cbSJens Wiklander 
2044817466cbSJens Wiklander /*
2045817466cbSJens Wiklander  * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
2046817466cbSJens Wiklander  */
2047817466cbSJens Wiklander int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
2048817466cbSJens Wiklander {
204911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2050817466cbSJens Wiklander     size_t lz, lzt;
205111fa71b9SJerome Forissier     mbedtls_mpi TA, TB;
2052817466cbSJens Wiklander 
205311fa71b9SJerome Forissier     mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
2054817466cbSJens Wiklander 
2055817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2056817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
2057817466cbSJens Wiklander 
2058817466cbSJens Wiklander     lz = mbedtls_mpi_lsb(&TA);
2059817466cbSJens Wiklander     lzt = mbedtls_mpi_lsb(&TB);
2060817466cbSJens Wiklander 
20617901324dSJerome Forissier     /* The loop below gives the correct result when A==0 but not when B==0.
20627901324dSJerome Forissier      * So have a special case for B==0. Leverage the fact that we just
20637901324dSJerome Forissier      * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
20647901324dSJerome Forissier      * slightly more efficient than cmp_int(). */
206532b31808SJens Wiklander     if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
20667901324dSJerome Forissier         ret = mbedtls_mpi_copy(G, A);
20677901324dSJerome Forissier         goto cleanup;
20687901324dSJerome Forissier     }
20697901324dSJerome Forissier 
207032b31808SJens Wiklander     if (lzt < lz) {
2071817466cbSJens Wiklander         lz = lzt;
207232b31808SJens Wiklander     }
2073817466cbSJens Wiklander 
2074817466cbSJens Wiklander     TA.s = TB.s = 1;
2075817466cbSJens Wiklander 
20767901324dSJerome Forissier     /* We mostly follow the procedure described in HAC 14.54, but with some
20777901324dSJerome Forissier      * minor differences:
20787901324dSJerome Forissier      * - Sequences of multiplications or divisions by 2 are grouped into a
20797901324dSJerome Forissier      *   single shift operation.
20807901324dSJerome Forissier      * - The procedure in HAC assumes that 0 < TB <= TA.
20817901324dSJerome Forissier      *     - The condition TB <= TA is not actually necessary for correctness.
20827901324dSJerome Forissier      *       TA and TB have symmetric roles except for the loop termination
20837901324dSJerome Forissier      *       condition, and the shifts at the beginning of the loop body
20847901324dSJerome Forissier      *       remove any significance from the ordering of TA vs TB before
20857901324dSJerome Forissier      *       the shifts.
20867901324dSJerome Forissier      *     - If TA = 0, the loop goes through 0 iterations and the result is
20877901324dSJerome Forissier      *       correctly TB.
20887901324dSJerome Forissier      *     - The case TB = 0 was short-circuited above.
20897901324dSJerome Forissier      *
20907901324dSJerome Forissier      * For the correctness proof below, decompose the original values of
20917901324dSJerome Forissier      * A and B as
20927901324dSJerome Forissier      *   A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
20937901324dSJerome Forissier      *   B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
20947901324dSJerome Forissier      * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
20957901324dSJerome Forissier      * and gcd(A',B') is odd or 0.
20967901324dSJerome Forissier      *
20977901324dSJerome Forissier      * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
20987901324dSJerome Forissier      * The code maintains the following invariant:
20997901324dSJerome Forissier      *     gcd(A,B) = 2^k * gcd(TA,TB) for some k   (I)
21007901324dSJerome Forissier      */
21017901324dSJerome Forissier 
21027901324dSJerome Forissier     /* Proof that the loop terminates:
21037901324dSJerome Forissier      * At each iteration, either the right-shift by 1 is made on a nonzero
21047901324dSJerome Forissier      * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
21057901324dSJerome Forissier      * by at least 1, or the right-shift by 1 is made on zero and then
21067901324dSJerome Forissier      * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
21077901324dSJerome Forissier      * since in that case TB is calculated from TB-TA with the condition TB>TA).
21087901324dSJerome Forissier      */
210932b31808SJens Wiklander     while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
21107901324dSJerome Forissier         /* Divisions by 2 preserve the invariant (I). */
2111817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2112817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
2113817466cbSJens Wiklander 
21147901324dSJerome Forissier         /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
21157901324dSJerome Forissier          * TA-TB is even so the division by 2 has an integer result.
21167901324dSJerome Forissier          * Invariant (I) is preserved since any odd divisor of both TA and TB
21177901324dSJerome Forissier          * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2118039e02dfSJerome Forissier          * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
21197901324dSJerome Forissier          * divides TA.
21207901324dSJerome Forissier          */
212132b31808SJens Wiklander         if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2122817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2123817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
212432b31808SJens Wiklander         } else {
2125817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2126817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
2127817466cbSJens Wiklander         }
21287901324dSJerome Forissier         /* Note that one of TA or TB is still odd. */
2129817466cbSJens Wiklander     }
2130817466cbSJens Wiklander 
21317901324dSJerome Forissier     /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
21327901324dSJerome Forissier      * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
21337901324dSJerome Forissier      * - If there was at least one loop iteration, then one of TA or TB is odd,
21347901324dSJerome Forissier      *   and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
21357901324dSJerome Forissier      *   lz = min(a,b) so gcd(A,B) = 2^lz * TB.
21367901324dSJerome Forissier      * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
21377901324dSJerome Forissier      *   In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
21387901324dSJerome Forissier      */
21397901324dSJerome Forissier 
2140817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2141817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
2142817466cbSJens Wiklander 
2143817466cbSJens Wiklander cleanup:
2144817466cbSJens Wiklander 
214511fa71b9SJerome Forissier     mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
2146817466cbSJens Wiklander 
214732b31808SJens Wiklander     return ret;
21487901324dSJerome Forissier }
21497901324dSJerome Forissier 
2150817466cbSJens Wiklander /*
2151817466cbSJens Wiklander  * Fill X with size bytes of random.
215232b31808SJens Wiklander  * The bytes returned from the RNG are used in a specific order which
215332b31808SJens Wiklander  * is suitable for deterministic ECDSA (see the specification of
215432b31808SJens Wiklander  * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
2155817466cbSJens Wiklander  */
2156817466cbSJens Wiklander int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2157817466cbSJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t),
2158817466cbSJens Wiklander                             void *p_rng)
2159817466cbSJens Wiklander {
216011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
216132b31808SJens Wiklander     const size_t limbs = CHARS_TO_LIMBS(size);
21625b25c76aSJerome Forissier 
21635b25c76aSJerome Forissier     /* Ensure that target MPI has exactly the necessary number of limbs */
21647901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
216532b31808SJens Wiklander     if (size == 0) {
216632b31808SJens Wiklander         return 0;
216732b31808SJens Wiklander     }
2168817466cbSJens Wiklander 
216932b31808SJens Wiklander     ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
2170817466cbSJens Wiklander 
2171817466cbSJens Wiklander cleanup:
217232b31808SJens Wiklander     return ret;
2173817466cbSJens Wiklander }
2174817466cbSJens Wiklander 
21757901324dSJerome Forissier int mbedtls_mpi_random(mbedtls_mpi *X,
21767901324dSJerome Forissier                        mbedtls_mpi_sint min,
21777901324dSJerome Forissier                        const mbedtls_mpi *N,
21787901324dSJerome Forissier                        int (*f_rng)(void *, unsigned char *, size_t),
21797901324dSJerome Forissier                        void *p_rng)
21807901324dSJerome Forissier {
218132b31808SJens Wiklander     if (min < 0) {
218232b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
218332b31808SJens Wiklander     }
218432b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(N, min) <= 0) {
218532b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
218632b31808SJens Wiklander     }
21877901324dSJerome Forissier 
21887901324dSJerome Forissier     /* Ensure that target MPI has exactly the same number of limbs
21897901324dSJerome Forissier      * as the upper bound, even if the upper bound has leading zeros.
219032b31808SJens Wiklander      * This is necessary for mbedtls_mpi_core_random. */
219132b31808SJens Wiklander     int ret = mbedtls_mpi_resize_clear(X, N->n);
219232b31808SJens Wiklander     if (ret != 0) {
219332b31808SJens Wiklander         return ret;
21947901324dSJerome Forissier     }
21957901324dSJerome Forissier 
219632b31808SJens Wiklander     return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
21977901324dSJerome Forissier }
21987901324dSJerome Forissier 
2199817466cbSJens Wiklander /*
2200817466cbSJens Wiklander  * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
2201817466cbSJens Wiklander  */
2202817466cbSJens Wiklander int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
2203817466cbSJens Wiklander {
220411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2205817466cbSJens Wiklander     mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
2206817466cbSJens Wiklander 
220732b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
220832b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
220932b31808SJens Wiklander     }
2210817466cbSJens Wiklander 
221198bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TU);
221298bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&U1); mbedtls_mpi_init_mempool(&U2);
221398bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&G); mbedtls_mpi_init_mempool(&TB);
221498bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&TV); mbedtls_mpi_init_mempool(&V1);
221598bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&V2);
2216817466cbSJens Wiklander 
2217817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
2218817466cbSJens Wiklander 
221932b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
2220817466cbSJens Wiklander         ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2221817466cbSJens Wiklander         goto cleanup;
2222817466cbSJens Wiklander     }
2223817466cbSJens Wiklander 
2224817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2225817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2226817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2227817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
2228817466cbSJens Wiklander 
2229817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2230817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2231817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2232817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
2233817466cbSJens Wiklander 
223432b31808SJens Wiklander     do {
223532b31808SJens Wiklander         while ((TU.p[0] & 1) == 0) {
2236817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
2237817466cbSJens Wiklander 
223832b31808SJens Wiklander             if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2239817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2240817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
2241817466cbSJens Wiklander             }
2242817466cbSJens Wiklander 
2243817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2244817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
2245817466cbSJens Wiklander         }
2246817466cbSJens Wiklander 
224732b31808SJens Wiklander         while ((TV.p[0] & 1) == 0) {
2248817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
2249817466cbSJens Wiklander 
225032b31808SJens Wiklander             if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2251817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2252817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
2253817466cbSJens Wiklander             }
2254817466cbSJens Wiklander 
2255817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2256817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
2257817466cbSJens Wiklander         }
2258817466cbSJens Wiklander 
225932b31808SJens Wiklander         if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2260817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2261817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2262817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
226332b31808SJens Wiklander         } else {
2264817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2265817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2266817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
2267817466cbSJens Wiklander         }
226832b31808SJens Wiklander     } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2269817466cbSJens Wiklander 
227032b31808SJens Wiklander     while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2271817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
227232b31808SJens Wiklander     }
2273817466cbSJens Wiklander 
227432b31808SJens Wiklander     while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2275817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
227632b31808SJens Wiklander     }
2277817466cbSJens Wiklander 
2278817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
2279817466cbSJens Wiklander 
2280817466cbSJens Wiklander cleanup:
2281817466cbSJens Wiklander 
2282817466cbSJens Wiklander     mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2283817466cbSJens Wiklander     mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2284817466cbSJens Wiklander     mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
2285817466cbSJens Wiklander 
228632b31808SJens Wiklander     return ret;
2287817466cbSJens Wiklander }
2288817466cbSJens Wiklander 
2289817466cbSJens Wiklander #if defined(MBEDTLS_GENPRIME)
2290817466cbSJens Wiklander 
2291*b0563631STom Van Eyck /* Gaps between primes, starting at 3. https://oeis.org/A001223 */
2292*b0563631STom Van Eyck static const unsigned char small_prime_gaps[] = {
2293*b0563631STom Van Eyck     2, 2, 4, 2, 4, 2, 4, 6,
2294*b0563631STom Van Eyck     2, 6, 4, 2, 4, 6, 6, 2,
2295*b0563631STom Van Eyck     6, 4, 2, 6, 4, 6, 8, 4,
2296*b0563631STom Van Eyck     2, 4, 2, 4, 14, 4, 6, 2,
2297*b0563631STom Van Eyck     10, 2, 6, 6, 4, 6, 6, 2,
2298*b0563631STom Van Eyck     10, 2, 4, 2, 12, 12, 4, 2,
2299*b0563631STom Van Eyck     4, 6, 2, 10, 6, 6, 6, 2,
2300*b0563631STom Van Eyck     6, 4, 2, 10, 14, 4, 2, 4,
2301*b0563631STom Van Eyck     14, 6, 10, 2, 4, 6, 8, 6,
2302*b0563631STom Van Eyck     6, 4, 6, 8, 4, 8, 10, 2,
2303*b0563631STom Van Eyck     10, 2, 6, 4, 6, 8, 4, 2,
2304*b0563631STom Van Eyck     4, 12, 8, 4, 8, 4, 6, 12,
2305*b0563631STom Van Eyck     2, 18, 6, 10, 6, 6, 2, 6,
2306*b0563631STom Van Eyck     10, 6, 6, 2, 6, 6, 4, 2,
2307*b0563631STom Van Eyck     12, 10, 2, 4, 6, 6, 2, 12,
2308*b0563631STom Van Eyck     4, 6, 8, 10, 8, 10, 8, 6,
2309*b0563631STom Van Eyck     6, 4, 8, 6, 4, 8, 4, 14,
2310*b0563631STom Van Eyck     10, 12, 2, 10, 2, 4, 2, 10,
2311*b0563631STom Van Eyck     14, 4, 2, 4, 14, 4, 2, 4,
2312*b0563631STom Van Eyck     20, 4, 8, 10, 8, 4, 6, 6,
2313*b0563631STom Van Eyck     14, 4, 6, 6, 8, 6, /*reaches 997*/
2314*b0563631STom Van Eyck     0 /* the last entry is effectively unused */
2315817466cbSJens Wiklander };
2316817466cbSJens Wiklander 
2317817466cbSJens Wiklander /*
2318817466cbSJens Wiklander  * Small divisors test (X must be positive)
2319817466cbSJens Wiklander  *
2320817466cbSJens Wiklander  * Return values:
2321817466cbSJens Wiklander  * 0: no small factor (possible prime, more tests needed)
2322817466cbSJens Wiklander  * 1: certain prime
2323817466cbSJens Wiklander  * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2324817466cbSJens Wiklander  * other negative: error
2325817466cbSJens Wiklander  */
2326817466cbSJens Wiklander static int mpi_check_small_factors(const mbedtls_mpi *X)
2327817466cbSJens Wiklander {
2328817466cbSJens Wiklander     int ret = 0;
2329817466cbSJens Wiklander     size_t i;
2330817466cbSJens Wiklander     mbedtls_mpi_uint r;
2331*b0563631STom Van Eyck     unsigned p = 3; /* The first odd prime */
2332817466cbSJens Wiklander 
233332b31808SJens Wiklander     if ((X->p[0] & 1) == 0) {
233432b31808SJens Wiklander         return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
233532b31808SJens Wiklander     }
2336817466cbSJens Wiklander 
2337*b0563631STom Van Eyck     for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2338*b0563631STom Van Eyck         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
233932b31808SJens Wiklander         if (r == 0) {
2340*b0563631STom Van Eyck             if (mbedtls_mpi_cmp_int(X, p) == 0) {
2341*b0563631STom Van Eyck                 return 1;
2342*b0563631STom Van Eyck             } else {
234332b31808SJens Wiklander                 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
234432b31808SJens Wiklander             }
2345817466cbSJens Wiklander         }
2346*b0563631STom Van Eyck     }
2347817466cbSJens Wiklander 
2348817466cbSJens Wiklander cleanup:
234932b31808SJens Wiklander     return ret;
2350817466cbSJens Wiklander }
2351817466cbSJens Wiklander 
2352817466cbSJens Wiklander /*
2353817466cbSJens Wiklander  * Miller-Rabin pseudo-primality test  (HAC 4.24)
2354817466cbSJens Wiklander  */
23553d3b0591SJens Wiklander static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2356817466cbSJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t),
2357817466cbSJens Wiklander                             void *p_rng)
2358817466cbSJens Wiklander {
2359817466cbSJens Wiklander     int ret, count;
23603d3b0591SJens Wiklander     size_t i, j, k, s;
2361817466cbSJens Wiklander     mbedtls_mpi W, R, T, A, RR;
2362817466cbSJens Wiklander 
236398bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&W); mbedtls_mpi_init_mempool(&R);
236498bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A);
236598bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&RR);
2366817466cbSJens Wiklander 
2367817466cbSJens Wiklander     /*
2368817466cbSJens Wiklander      * W = |X| - 1
2369817466cbSJens Wiklander      * R = W >> lsb( W )
2370817466cbSJens Wiklander      */
2371817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2372817466cbSJens Wiklander     s = mbedtls_mpi_lsb(&W);
2373817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2374817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
2375817466cbSJens Wiklander 
237632b31808SJens Wiklander     for (i = 0; i < rounds; i++) {
2377817466cbSJens Wiklander         /*
2378817466cbSJens Wiklander          * pick a random A, 1 < A < |X| - 1
2379817466cbSJens Wiklander          */
2380817466cbSJens Wiklander         count = 0;
2381817466cbSJens Wiklander         do {
2382817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
2383817466cbSJens Wiklander 
2384817466cbSJens Wiklander             j = mbedtls_mpi_bitlen(&A);
2385817466cbSJens Wiklander             k = mbedtls_mpi_bitlen(&W);
2386817466cbSJens Wiklander             if (j > k) {
23873d3b0591SJens Wiklander                 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
2388817466cbSJens Wiklander             }
2389817466cbSJens Wiklander 
2390117cce93SJens Wiklander             if (count++ > 300) {
2391336e3299SJens Wiklander                 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2392336e3299SJens Wiklander                 goto cleanup;
2393817466cbSJens Wiklander             }
2394817466cbSJens Wiklander 
2395817466cbSJens Wiklander         } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2396817466cbSJens Wiklander                  mbedtls_mpi_cmp_int(&A, 1)  <= 0);
2397817466cbSJens Wiklander 
2398817466cbSJens Wiklander         /*
2399817466cbSJens Wiklander          * A = A^R mod |X|
2400817466cbSJens Wiklander          */
2401817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
2402817466cbSJens Wiklander 
2403817466cbSJens Wiklander         if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
240432b31808SJens Wiklander             mbedtls_mpi_cmp_int(&A,  1) == 0) {
2405817466cbSJens Wiklander             continue;
240632b31808SJens Wiklander         }
2407817466cbSJens Wiklander 
2408817466cbSJens Wiklander         j = 1;
240932b31808SJens Wiklander         while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
2410817466cbSJens Wiklander             /*
2411817466cbSJens Wiklander              * A = A * A mod |X|
2412817466cbSJens Wiklander              */
2413817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2414817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
2415817466cbSJens Wiklander 
241632b31808SJens Wiklander             if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
2417817466cbSJens Wiklander                 break;
241832b31808SJens Wiklander             }
2419817466cbSJens Wiklander 
2420817466cbSJens Wiklander             j++;
2421817466cbSJens Wiklander         }
2422817466cbSJens Wiklander 
2423817466cbSJens Wiklander         /*
2424817466cbSJens Wiklander          * not prime if A != |X| - 1 or A == 1
2425817466cbSJens Wiklander          */
2426817466cbSJens Wiklander         if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
242732b31808SJens Wiklander             mbedtls_mpi_cmp_int(&A,  1) == 0) {
2428817466cbSJens Wiklander             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2429817466cbSJens Wiklander             break;
2430817466cbSJens Wiklander         }
2431817466cbSJens Wiklander     }
2432817466cbSJens Wiklander 
2433817466cbSJens Wiklander cleanup:
24343d3b0591SJens Wiklander     mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
24353d3b0591SJens Wiklander     mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2436817466cbSJens Wiklander     mbedtls_mpi_free(&RR);
2437817466cbSJens Wiklander 
243832b31808SJens Wiklander     return ret;
2439817466cbSJens Wiklander }
2440817466cbSJens Wiklander 
2441817466cbSJens Wiklander /*
2442817466cbSJens Wiklander  * Pseudo-primality test: small factors, then Miller-Rabin
2443817466cbSJens Wiklander  */
24443d3b0591SJens Wiklander int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2445817466cbSJens Wiklander                              int (*f_rng)(void *, unsigned char *, size_t),
2446817466cbSJens Wiklander                              void *p_rng)
2447817466cbSJens Wiklander {
244811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2449817466cbSJens Wiklander     mbedtls_mpi XX;
2450817466cbSJens Wiklander 
2451817466cbSJens Wiklander     XX.s = 1;
2452817466cbSJens Wiklander     XX.n = X->n;
2453817466cbSJens Wiklander     XX.p = X->p;
2454817466cbSJens Wiklander 
2455817466cbSJens Wiklander     if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
245632b31808SJens Wiklander         mbedtls_mpi_cmp_int(&XX, 1) == 0) {
245732b31808SJens Wiklander         return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2458817466cbSJens Wiklander     }
2459817466cbSJens Wiklander 
246032b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
246132b31808SJens Wiklander         return 0;
2462817466cbSJens Wiklander     }
2463817466cbSJens Wiklander 
246432b31808SJens Wiklander     if ((ret = mpi_check_small_factors(&XX)) != 0) {
246532b31808SJens Wiklander         if (ret == 1) {
246632b31808SJens Wiklander             return 0;
24673d3b0591SJens Wiklander         }
246832b31808SJens Wiklander 
246932b31808SJens Wiklander         return ret;
247032b31808SJens Wiklander     }
247132b31808SJens Wiklander 
247232b31808SJens Wiklander     return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
247332b31808SJens Wiklander }
24743d3b0591SJens Wiklander 
24753d3b0591SJens Wiklander /*
24763d3b0591SJens Wiklander  * Prime number generation
24773d3b0591SJens Wiklander  *
24783d3b0591SJens Wiklander  * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
24793d3b0591SJens Wiklander  * be either 1024 bits or 1536 bits long, and flags must contain
24803d3b0591SJens Wiklander  * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
24813d3b0591SJens Wiklander  */
24823d3b0591SJens Wiklander int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
24833d3b0591SJens Wiklander                           int (*f_rng)(void *, unsigned char *, size_t),
24843d3b0591SJens Wiklander                           void *p_rng)
24853d3b0591SJens Wiklander {
24863d3b0591SJens Wiklander #ifdef MBEDTLS_HAVE_INT64
24873d3b0591SJens Wiklander // ceil(2^63.5)
24883d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
24893d3b0591SJens Wiklander #else
24903d3b0591SJens Wiklander // ceil(2^31.5)
24913d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
24923d3b0591SJens Wiklander #endif
24933d3b0591SJens Wiklander     int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2494817466cbSJens Wiklander     size_t k, n;
24953d3b0591SJens Wiklander     int rounds;
2496817466cbSJens Wiklander     mbedtls_mpi_uint r;
2497817466cbSJens Wiklander     mbedtls_mpi Y;
2498817466cbSJens Wiklander 
249932b31808SJens Wiklander     if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
250032b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
250132b31808SJens Wiklander     }
2502817466cbSJens Wiklander 
250398bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&Y);
2504817466cbSJens Wiklander 
2505817466cbSJens Wiklander     n = BITS_TO_LIMBS(nbits);
2506817466cbSJens Wiklander 
250732b31808SJens Wiklander     if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
25083d3b0591SJens Wiklander         /*
25093d3b0591SJens Wiklander          * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
25103d3b0591SJens Wiklander          */
25113d3b0591SJens Wiklander         rounds = ((nbits >= 1300) ?  2 : (nbits >=  850) ?  3 :
25123d3b0591SJens Wiklander                   (nbits >=  650) ?  4 : (nbits >=  350) ?  8 :
25133d3b0591SJens Wiklander                   (nbits >=  250) ? 12 : (nbits >=  150) ? 18 : 27);
251432b31808SJens Wiklander     } else {
25153d3b0591SJens Wiklander         /*
25163d3b0591SJens Wiklander          * 2^-100 error probability, number of rounds computed based on HAC,
25173d3b0591SJens Wiklander          * fact 4.48
25183d3b0591SJens Wiklander          */
25193d3b0591SJens Wiklander         rounds = ((nbits >= 1450) ?  4 : (nbits >=  1150) ?  5 :
25203d3b0591SJens Wiklander                   (nbits >= 1000) ?  6 : (nbits >=   850) ?  7 :
25213d3b0591SJens Wiklander                   (nbits >=  750) ?  8 : (nbits >=   500) ? 13 :
25223d3b0591SJens Wiklander                   (nbits >=  250) ? 28 : (nbits >=   150) ? 40 : 51);
25233d3b0591SJens Wiklander     }
25243d3b0591SJens Wiklander 
252532b31808SJens Wiklander     while (1) {
2526817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
25273d3b0591SJens Wiklander         /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
252832b31808SJens Wiklander         if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
252932b31808SJens Wiklander             continue;
253032b31808SJens Wiklander         }
2531817466cbSJens Wiklander 
25323d3b0591SJens Wiklander         k = n * biL;
253332b31808SJens Wiklander         if (k > nbits) {
253432b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
253532b31808SJens Wiklander         }
2536817466cbSJens Wiklander         X->p[0] |= 1;
2537817466cbSJens Wiklander 
253832b31808SJens Wiklander         if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
25393d3b0591SJens Wiklander             ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
25403d3b0591SJens Wiklander 
254132b31808SJens Wiklander             if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
2542817466cbSJens Wiklander                 goto cleanup;
2543817466cbSJens Wiklander             }
254432b31808SJens Wiklander         } else {
2545817466cbSJens Wiklander             /*
254632b31808SJens Wiklander              * A necessary condition for Y and X = 2Y + 1 to be prime
2547817466cbSJens Wiklander              * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2548817466cbSJens Wiklander              * Make sure it is satisfied, while keeping X = 3 mod 4
2549817466cbSJens Wiklander              */
2550817466cbSJens Wiklander 
2551817466cbSJens Wiklander             X->p[0] |= 2;
2552817466cbSJens Wiklander 
2553817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
255432b31808SJens Wiklander             if (r == 0) {
2555817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
255632b31808SJens Wiklander             } else if (r == 1) {
2557817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
255832b31808SJens Wiklander             }
2559817466cbSJens Wiklander 
2560817466cbSJens Wiklander             /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2561817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2562817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
2563817466cbSJens Wiklander 
256432b31808SJens Wiklander             while (1) {
2565817466cbSJens Wiklander                 /*
2566817466cbSJens Wiklander                  * First, check small factors for X and Y
2567817466cbSJens Wiklander                  * before doing Miller-Rabin on any of them
2568817466cbSJens Wiklander                  */
2569817466cbSJens Wiklander                 if ((ret = mpi_check_small_factors(X)) == 0 &&
2570817466cbSJens Wiklander                     (ret = mpi_check_small_factors(&Y)) == 0 &&
25713d3b0591SJens Wiklander                     (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
25723d3b0591SJens Wiklander                     == 0 &&
25733d3b0591SJens Wiklander                     (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
257432b31808SJens Wiklander                     == 0) {
25753d3b0591SJens Wiklander                     goto cleanup;
257632b31808SJens Wiklander                 }
2577817466cbSJens Wiklander 
257832b31808SJens Wiklander                 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
2579817466cbSJens Wiklander                     goto cleanup;
258032b31808SJens Wiklander                 }
2581817466cbSJens Wiklander 
2582817466cbSJens Wiklander                 /*
2583817466cbSJens Wiklander                  * Next candidates. We want to preserve Y = (X-1) / 2 and
2584817466cbSJens Wiklander                  * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2585817466cbSJens Wiklander                  * so up Y by 6 and X by 12.
2586817466cbSJens Wiklander                  */
2587817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X,  X, 12));
2588817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
2589817466cbSJens Wiklander             }
2590817466cbSJens Wiklander         }
25913d3b0591SJens Wiklander     }
2592817466cbSJens Wiklander 
2593817466cbSJens Wiklander cleanup:
2594817466cbSJens Wiklander 
2595817466cbSJens Wiklander     mbedtls_mpi_free(&Y);
2596817466cbSJens Wiklander 
259732b31808SJens Wiklander     return ret;
2598817466cbSJens Wiklander }
2599817466cbSJens Wiklander 
2600817466cbSJens Wiklander #endif /* MBEDTLS_GENPRIME */
2601817466cbSJens Wiklander 
2602817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
2603817466cbSJens Wiklander 
2604817466cbSJens Wiklander #define GCD_PAIR_COUNT  3
2605817466cbSJens Wiklander 
2606817466cbSJens Wiklander static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2607817466cbSJens Wiklander {
2608817466cbSJens Wiklander     { 693, 609, 21 },
2609817466cbSJens Wiklander     { 1764, 868, 28 },
2610817466cbSJens Wiklander     { 768454923, 542167814, 1 }
2611817466cbSJens Wiklander };
2612817466cbSJens Wiklander 
2613817466cbSJens Wiklander /*
2614817466cbSJens Wiklander  * Checkup routine
2615817466cbSJens Wiklander  */
2616817466cbSJens Wiklander int mbedtls_mpi_self_test(int verbose)
2617817466cbSJens Wiklander {
2618817466cbSJens Wiklander     int ret, i;
2619817466cbSJens Wiklander     mbedtls_mpi A, E, N, X, Y, U, V;
2620817466cbSJens Wiklander 
262198bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&A); mbedtls_mpi_init_mempool(&E);
262298bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&N); mbedtls_mpi_init_mempool(&X);
262398bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&Y); mbedtls_mpi_init_mempool(&U);
262498bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&V);
2625817466cbSJens Wiklander 
2626817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2627817466cbSJens Wiklander                                             "EFE021C2645FD1DC586E69184AF4A31E" \
2628817466cbSJens Wiklander                                             "D5F53E93B5F123FA41680867BA110131" \
2629817466cbSJens Wiklander                                             "944FE7952E2517337780CB0DB80E61AA" \
2630817466cbSJens Wiklander                                             "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
2631817466cbSJens Wiklander 
2632817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2633817466cbSJens Wiklander                                             "B2E7EFD37075B9F03FF989C7C5051C20" \
2634817466cbSJens Wiklander                                             "34D2A323810251127E7BF8625A4F49A5" \
2635817466cbSJens Wiklander                                             "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2636817466cbSJens Wiklander                                             "5B5C25763222FEFCCFC38B832366C29E"));
2637817466cbSJens Wiklander 
2638817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2639817466cbSJens Wiklander                                             "0066A198186C18C10B2F5ED9B522752A" \
2640817466cbSJens Wiklander                                             "9830B69916E535C8F047518A889A43A5" \
2641817466cbSJens Wiklander                                             "94B6BED27A168D31D4A52F88925AA8F5"));
2642817466cbSJens Wiklander 
2643817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
2644817466cbSJens Wiklander 
2645817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2646817466cbSJens Wiklander                                             "602AB7ECA597A3D6B56FF9829A5E8B85" \
2647817466cbSJens Wiklander                                             "9E857EA95A03512E2BAE7391688D264A" \
2648817466cbSJens Wiklander                                             "A5663B0341DB9CCFD2C4C5F421FEC814" \
2649817466cbSJens Wiklander                                             "8001B72E848A38CAE1C65F78E56ABDEF" \
2650817466cbSJens Wiklander                                             "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2651817466cbSJens Wiklander                                             "ECF677152EF804370C1A305CAF3B5BF1" \
2652817466cbSJens Wiklander                                             "30879B56C61DE584A0F53A2447A51E"));
2653817466cbSJens Wiklander 
265432b31808SJens Wiklander     if (verbose != 0) {
2655817466cbSJens Wiklander         mbedtls_printf("  MPI test #1 (mul_mpi): ");
265632b31808SJens Wiklander     }
2657817466cbSJens Wiklander 
265832b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
265932b31808SJens Wiklander         if (verbose != 0) {
2660817466cbSJens Wiklander             mbedtls_printf("failed\n");
266132b31808SJens Wiklander         }
2662817466cbSJens Wiklander 
2663817466cbSJens Wiklander         ret = 1;
2664817466cbSJens Wiklander         goto cleanup;
2665817466cbSJens Wiklander     }
2666817466cbSJens Wiklander 
266732b31808SJens Wiklander     if (verbose != 0) {
2668817466cbSJens Wiklander         mbedtls_printf("passed\n");
266932b31808SJens Wiklander     }
2670817466cbSJens Wiklander 
2671817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
2672817466cbSJens Wiklander 
2673817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2674817466cbSJens Wiklander                                             "256567336059E52CAE22925474705F39A94"));
2675817466cbSJens Wiklander 
2676817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2677817466cbSJens Wiklander                                             "6613F26162223DF488E9CD48CC132C7A" \
2678817466cbSJens Wiklander                                             "0AC93C701B001B092E4E5B9F73BCD27B" \
2679817466cbSJens Wiklander                                             "9EE50D0657C77F374E903CDFA4C642"));
2680817466cbSJens Wiklander 
268132b31808SJens Wiklander     if (verbose != 0) {
2682817466cbSJens Wiklander         mbedtls_printf("  MPI test #2 (div_mpi): ");
268332b31808SJens Wiklander     }
2684817466cbSJens Wiklander 
2685817466cbSJens Wiklander     if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
268632b31808SJens Wiklander         mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
268732b31808SJens Wiklander         if (verbose != 0) {
2688817466cbSJens Wiklander             mbedtls_printf("failed\n");
268932b31808SJens Wiklander         }
2690817466cbSJens Wiklander 
2691817466cbSJens Wiklander         ret = 1;
2692817466cbSJens Wiklander         goto cleanup;
2693817466cbSJens Wiklander     }
2694817466cbSJens Wiklander 
269532b31808SJens Wiklander     if (verbose != 0) {
2696817466cbSJens Wiklander         mbedtls_printf("passed\n");
269732b31808SJens Wiklander     }
2698817466cbSJens Wiklander 
2699817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
2700817466cbSJens Wiklander 
2701817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2702817466cbSJens Wiklander                                             "36E139AEA55215609D2816998ED020BB" \
2703817466cbSJens Wiklander                                             "BD96C37890F65171D948E9BC7CBAA4D9" \
2704817466cbSJens Wiklander                                             "325D24D6A3C12710F10A09FA08AB87"));
2705817466cbSJens Wiklander 
270632b31808SJens Wiklander     if (verbose != 0) {
2707817466cbSJens Wiklander         mbedtls_printf("  MPI test #3 (exp_mod): ");
270832b31808SJens Wiklander     }
2709817466cbSJens Wiklander 
271032b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
271132b31808SJens Wiklander         if (verbose != 0) {
2712817466cbSJens Wiklander             mbedtls_printf("failed\n");
271332b31808SJens Wiklander         }
2714817466cbSJens Wiklander 
2715817466cbSJens Wiklander         ret = 1;
2716817466cbSJens Wiklander         goto cleanup;
2717817466cbSJens Wiklander     }
2718817466cbSJens Wiklander 
271932b31808SJens Wiklander     if (verbose != 0) {
2720817466cbSJens Wiklander         mbedtls_printf("passed\n");
272132b31808SJens Wiklander     }
2722817466cbSJens Wiklander 
2723817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
2724817466cbSJens Wiklander 
2725817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2726817466cbSJens Wiklander                                             "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2727817466cbSJens Wiklander                                             "C3DBA76456363A10869622EAC2DD84EC" \
2728817466cbSJens Wiklander                                             "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
2729817466cbSJens Wiklander 
273032b31808SJens Wiklander     if (verbose != 0) {
2731817466cbSJens Wiklander         mbedtls_printf("  MPI test #4 (inv_mod): ");
273232b31808SJens Wiklander     }
2733817466cbSJens Wiklander 
273432b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
273532b31808SJens Wiklander         if (verbose != 0) {
2736817466cbSJens Wiklander             mbedtls_printf("failed\n");
273732b31808SJens Wiklander         }
2738817466cbSJens Wiklander 
2739817466cbSJens Wiklander         ret = 1;
2740817466cbSJens Wiklander         goto cleanup;
2741817466cbSJens Wiklander     }
2742817466cbSJens Wiklander 
274332b31808SJens Wiklander     if (verbose != 0) {
2744817466cbSJens Wiklander         mbedtls_printf("passed\n");
274532b31808SJens Wiklander     }
2746817466cbSJens Wiklander 
274732b31808SJens Wiklander     if (verbose != 0) {
2748817466cbSJens Wiklander         mbedtls_printf("  MPI test #5 (simple gcd): ");
274932b31808SJens Wiklander     }
2750817466cbSJens Wiklander 
275132b31808SJens Wiklander     for (i = 0; i < GCD_PAIR_COUNT; i++) {
2752817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2753817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
2754817466cbSJens Wiklander 
2755817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
2756817466cbSJens Wiklander 
275732b31808SJens Wiklander         if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
275832b31808SJens Wiklander             if (verbose != 0) {
2759817466cbSJens Wiklander                 mbedtls_printf("failed at %d\n", i);
276032b31808SJens Wiklander             }
2761817466cbSJens Wiklander 
2762817466cbSJens Wiklander             ret = 1;
2763817466cbSJens Wiklander             goto cleanup;
2764817466cbSJens Wiklander         }
2765817466cbSJens Wiklander     }
2766817466cbSJens Wiklander 
276732b31808SJens Wiklander     if (verbose != 0) {
2768817466cbSJens Wiklander         mbedtls_printf("passed\n");
276932b31808SJens Wiklander     }
2770817466cbSJens Wiklander 
2771817466cbSJens Wiklander cleanup:
2772817466cbSJens Wiklander 
277332b31808SJens Wiklander     if (ret != 0 && verbose != 0) {
27747901324dSJerome Forissier         mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
277532b31808SJens Wiklander     }
2776817466cbSJens Wiklander 
2777817466cbSJens Wiklander     mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2778817466cbSJens Wiklander     mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
2779817466cbSJens Wiklander 
278032b31808SJens Wiklander     if (verbose != 0) {
2781817466cbSJens Wiklander         mbedtls_printf("\n");
278232b31808SJens Wiklander     }
2783817466cbSJens Wiklander 
278432b31808SJens Wiklander     return ret;
2785817466cbSJens Wiklander }
2786817466cbSJens Wiklander 
2787817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
2788817466cbSJens Wiklander 
2789817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */
2790