xref: /optee_os/lib/libmbedtls/mbedtls/library/bignum.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Multi-precision integer library
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander 
20817466cbSJens Wiklander /*
21817466cbSJens Wiklander  *  The following sources were referenced in the design of this Multi-precision
22817466cbSJens Wiklander  *  Integer library:
23817466cbSJens Wiklander  *
24817466cbSJens Wiklander  *  [1] Handbook of Applied Cryptography - 1997
25817466cbSJens Wiklander  *      Menezes, van Oorschot and Vanstone
26817466cbSJens Wiklander  *
27817466cbSJens Wiklander  *  [2] Multi-Precision Math
28817466cbSJens Wiklander  *      Tom St Denis
29817466cbSJens Wiklander  *      https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30817466cbSJens Wiklander  *
31817466cbSJens Wiklander  *  [3] GNU Multi-Precision Arithmetic Library
32817466cbSJens Wiklander  *      https://gmplib.org/manual/index.html
33817466cbSJens Wiklander  *
34817466cbSJens Wiklander  */
35817466cbSJens Wiklander 
367901324dSJerome Forissier #include "common.h"
37817466cbSJens Wiklander 
38817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C)
39817466cbSJens Wiklander 
40817466cbSJens Wiklander #include "mbedtls/bignum.h"
41*32b31808SJens Wiklander #include "bignum_core.h"
42*32b31808SJens Wiklander #include "bn_mul.h"
433d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
4411fa71b9SJerome Forissier #include "mbedtls/error.h"
45039e02dfSJerome Forissier #include "constant_time_internal.h"
46817466cbSJens Wiklander 
47039e02dfSJerome Forissier #include <limits.h>
48817466cbSJens Wiklander #include <string.h>
49817466cbSJens Wiklander 
50817466cbSJens Wiklander #include "mbedtls/platform.h"
51817466cbSJens Wiklander 
5298bd5fe3SJens Wiklander #include <mempool.h>
53b99a4a18SJens Wiklander #include <util.h>
5498bd5fe3SJens Wiklander 
553d3b0591SJens Wiklander #define MPI_VALIDATE_RET(cond)                                       \
563d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
573d3b0591SJens Wiklander #define MPI_VALIDATE(cond)                                           \
583d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE(cond)
59817466cbSJens Wiklander 
60817466cbSJens Wiklander #define MPI_SIZE_T_MAX  ((size_t) -1)   /* SIZE_T_MAX is not standard */
61817466cbSJens Wiklander 
6298bd5fe3SJens Wiklander void *mbedtls_mpi_mempool;
6398bd5fe3SJens Wiklander 
643d3b0591SJens Wiklander /* Implementation that should never be optimized out by the compiler */
653d3b0591SJens Wiklander static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
663d3b0591SJens Wiklander {
673d3b0591SJens Wiklander     mbedtls_platform_zeroize(v, ciL * n);
683d3b0591SJens Wiklander }
693d3b0591SJens Wiklander 
70817466cbSJens Wiklander /*
71817466cbSJens Wiklander  * Initialize one MPI
72817466cbSJens Wiklander  */
733d3b0591SJens Wiklander static void mpi_init(mbedtls_mpi *X, short use_mempool)
74817466cbSJens Wiklander {
753d3b0591SJens Wiklander     MPI_VALIDATE(X != NULL);
76817466cbSJens Wiklander 
773d3b0591SJens Wiklander     X->s = 1;
783d3b0591SJens Wiklander     X->use_mempool = use_mempool;
793d3b0591SJens Wiklander     X->n = 0;
803d3b0591SJens Wiklander     X->p = NULL;
81817466cbSJens Wiklander }
82817466cbSJens Wiklander 
8398bd5fe3SJens Wiklander void mbedtls_mpi_init(mbedtls_mpi *X)
8498bd5fe3SJens Wiklander {
853d3b0591SJens Wiklander     mpi_init(X, 0 /*use_mempool*/);
8698bd5fe3SJens Wiklander }
8798bd5fe3SJens Wiklander 
8898bd5fe3SJens Wiklander void mbedtls_mpi_init_mempool(mbedtls_mpi *X)
8998bd5fe3SJens Wiklander {
903d3b0591SJens Wiklander     mpi_init(X, !!mbedtls_mpi_mempool /*use_mempool*/);
9198bd5fe3SJens Wiklander }
9298bd5fe3SJens Wiklander 
93817466cbSJens Wiklander /*
94817466cbSJens Wiklander  * Unallocate one MPI
95817466cbSJens Wiklander  */
96817466cbSJens Wiklander void mbedtls_mpi_free(mbedtls_mpi *X)
97817466cbSJens Wiklander {
98*32b31808SJens Wiklander     if (X == NULL) {
99817466cbSJens Wiklander         return;
100*32b31808SJens Wiklander     }
101817466cbSJens Wiklander 
102*32b31808SJens Wiklander     if (X->p != NULL) {
103817466cbSJens Wiklander         mbedtls_mpi_zeroize(X->p, X->n);
1043d3b0591SJens Wiklander         if(X->use_mempool)
10518c5148dSJens Wiklander             mempool_free(mbedtls_mpi_mempool, X->p);
1063d3b0591SJens Wiklander         else
1073d3b0591SJens Wiklander         mbedtls_free(X->p);
108817466cbSJens Wiklander     }
109817466cbSJens Wiklander 
110817466cbSJens Wiklander     X->s = 1;
111817466cbSJens Wiklander     X->n = 0;
1123d3b0591SJens Wiklander     X->p = NULL;
113817466cbSJens Wiklander }
114817466cbSJens Wiklander 
115817466cbSJens Wiklander /*
116817466cbSJens Wiklander  * Enlarge to the specified number of limbs
117817466cbSJens Wiklander  */
118817466cbSJens Wiklander int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
119817466cbSJens Wiklander {
120817466cbSJens Wiklander     mbedtls_mpi_uint *p;
1213d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
122817466cbSJens Wiklander 
123*32b31808SJens Wiklander     if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
124*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
125*32b31808SJens Wiklander     }
126817466cbSJens Wiklander 
127*32b31808SJens Wiklander     if (X->n < nblimbs) {
128*32b31808SJens Wiklander         if(X->use_mempool) {
1293d3b0591SJens Wiklander             p = mempool_alloc(mbedtls_mpi_mempool, nblimbs * ciL);
13018c5148dSJens Wiklander             if(p == NULL)
131*32b31808SJens Wiklander                 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
1323d3b0591SJens Wiklander             memset(p, 0, nblimbs * ciL);
133*32b31808SJens Wiklander         } else {
1343d3b0591SJens Wiklander                 p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL);
1353d3b0591SJens Wiklander                 if (p == NULL)
136*32b31808SJens Wiklander                     return MBEDTLS_ERR_MPI_ALLOC_FAILED;
137817466cbSJens Wiklander         }
138817466cbSJens Wiklander 
139*32b31808SJens Wiklander         if (X->p != NULL) {
1403d3b0591SJens Wiklander             memcpy(p, X->p, X->n * ciL);
1413d3b0591SJens Wiklander             mbedtls_mpi_zeroize(X->p, X->n);
1423d3b0591SJens Wiklander             if (X->use_mempool)
14318c5148dSJens Wiklander                 mempool_free(mbedtls_mpi_mempool, X->p);
1443d3b0591SJens Wiklander             else
1453d3b0591SJens Wiklander                 mbedtls_free(X->p);
1463d3b0591SJens Wiklander         }
14718c5148dSJens Wiklander 
14818c5148dSJens Wiklander         X->n = nblimbs;
1493d3b0591SJens Wiklander         X->p = p;
1503d3b0591SJens Wiklander     }
151817466cbSJens Wiklander 
152*32b31808SJens Wiklander     return 0;
153817466cbSJens Wiklander }
154817466cbSJens Wiklander 
155817466cbSJens Wiklander /*
156817466cbSJens Wiklander  * Resize down as much as possible,
157817466cbSJens Wiklander  * while keeping at least the specified number of limbs
158817466cbSJens Wiklander  */
159817466cbSJens Wiklander int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
160817466cbSJens Wiklander {
161817466cbSJens Wiklander     mbedtls_mpi_uint *p;
162817466cbSJens Wiklander     size_t i;
1633d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
1643d3b0591SJens Wiklander 
165*32b31808SJens Wiklander     if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
166*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
167*32b31808SJens Wiklander     }
168817466cbSJens Wiklander 
1695b25c76aSJerome Forissier     /* Actually resize up if there are currently fewer than nblimbs limbs. */
170*32b31808SJens Wiklander     if (X->n <= nblimbs) {
171*32b31808SJens Wiklander         return mbedtls_mpi_grow(X, nblimbs);
172*32b31808SJens Wiklander     }
1735b25c76aSJerome Forissier     /* After this point, then X->n > nblimbs and in particular X->n > 0. */
174817466cbSJens Wiklander 
175*32b31808SJens Wiklander     for (i = X->n - 1; i > 0; i--) {
176*32b31808SJens Wiklander         if (X->p[i] != 0) {
177817466cbSJens Wiklander             break;
178*32b31808SJens Wiklander         }
179*32b31808SJens Wiklander     }
180817466cbSJens Wiklander     i++;
181817466cbSJens Wiklander 
182*32b31808SJens Wiklander     if (i < nblimbs) {
183817466cbSJens Wiklander         i = nblimbs;
184*32b31808SJens Wiklander     }
185817466cbSJens Wiklander 
186*32b31808SJens Wiklander     if (X->use_mempool) {
187ed3fa831SJerome Forissier         p = mempool_alloc(mbedtls_mpi_mempool, i * ciL);
1883d3b0591SJens Wiklander         if (p == NULL)
189*32b31808SJens Wiklander             return MBEDTLS_ERR_MPI_ALLOC_FAILED;
190ed3fa831SJerome Forissier         memset(p, 0, i * ciL);
191*32b31808SJens Wiklander     } else {
192*32b31808SJens Wiklander         if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL)
193*32b31808SJens Wiklander             return MBEDTLS_ERR_MPI_ALLOC_FAILED;
1943d3b0591SJens Wiklander     }
19518c5148dSJens Wiklander 
196*32b31808SJens Wiklander     if (X->p != NULL) {
197817466cbSJens Wiklander         memcpy(p, X->p, i * ciL);
198817466cbSJens Wiklander         mbedtls_mpi_zeroize(X->p, X->n);
1993d3b0591SJens Wiklander         if (X->use_mempool)
20018c5148dSJens Wiklander             mempool_free(mbedtls_mpi_mempool, X->p);
2013d3b0591SJens Wiklander         else
2023d3b0591SJens Wiklander             mbedtls_free(X->p);
203817466cbSJens Wiklander     }
204817466cbSJens Wiklander 
20518c5148dSJens Wiklander     X->n = i;
2063d3b0591SJens Wiklander     X->p = p;
207817466cbSJens Wiklander 
208*32b31808SJens Wiklander     return 0;
209817466cbSJens Wiklander }
210817466cbSJens Wiklander 
2117901324dSJerome Forissier /* Resize X to have exactly n limbs and set it to 0. */
2127901324dSJerome Forissier static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
2137901324dSJerome Forissier {
214*32b31808SJens Wiklander     if (limbs == 0) {
2157901324dSJerome Forissier         mbedtls_mpi_free(X);
216*32b31808SJens Wiklander         return 0;
217*32b31808SJens Wiklander     } else if (X->n == limbs) {
2187901324dSJerome Forissier         memset(X->p, 0, limbs * ciL);
2197901324dSJerome Forissier         X->s = 1;
220*32b31808SJens Wiklander         return 0;
221*32b31808SJens Wiklander     } else {
2227901324dSJerome Forissier         mbedtls_mpi_free(X);
223*32b31808SJens Wiklander         return mbedtls_mpi_grow(X, limbs);
2247901324dSJerome Forissier     }
2257901324dSJerome Forissier }
2267901324dSJerome Forissier 
227817466cbSJens Wiklander /*
2287901324dSJerome Forissier  * Copy the contents of Y into X.
2297901324dSJerome Forissier  *
2307901324dSJerome Forissier  * This function is not constant-time. Leading zeros in Y may be removed.
2317901324dSJerome Forissier  *
2327901324dSJerome Forissier  * Ensure that X does not shrink. This is not guaranteed by the public API,
2337901324dSJerome Forissier  * but some code in the bignum module relies on this property, for example
2347901324dSJerome Forissier  * in mbedtls_mpi_exp_mod().
235817466cbSJens Wiklander  */
236817466cbSJens Wiklander int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
237817466cbSJens Wiklander {
2383d3b0591SJens Wiklander     int ret = 0;
239817466cbSJens Wiklander     size_t i;
2403d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
2413d3b0591SJens Wiklander     MPI_VALIDATE_RET(Y != NULL);
242817466cbSJens Wiklander 
243*32b31808SJens Wiklander     if (X == Y) {
244*32b31808SJens Wiklander         return 0;
245*32b31808SJens Wiklander     }
246817466cbSJens Wiklander 
247*32b31808SJens Wiklander     if (Y->n == 0) {
248*32b31808SJens Wiklander         if (X->n != 0) {
2497901324dSJerome Forissier             X->s = 1;
2507901324dSJerome Forissier             memset(X->p, 0, X->n * ciL);
2517901324dSJerome Forissier         }
252*32b31808SJens Wiklander         return 0;
253817466cbSJens Wiklander     }
254817466cbSJens Wiklander 
255*32b31808SJens Wiklander     for (i = Y->n - 1; i > 0; i--) {
256*32b31808SJens Wiklander         if (Y->p[i] != 0) {
257817466cbSJens Wiklander             break;
258*32b31808SJens Wiklander         }
259*32b31808SJens Wiklander     }
260817466cbSJens Wiklander     i++;
261817466cbSJens Wiklander 
262817466cbSJens Wiklander     X->s = Y->s;
263817466cbSJens Wiklander 
264*32b31808SJens Wiklander     if (X->n < i) {
265817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
266*32b31808SJens Wiklander     } else {
2673d3b0591SJens Wiklander         memset(X->p + i, 0, (X->n - i) * ciL);
2683d3b0591SJens Wiklander     }
269817466cbSJens Wiklander 
270817466cbSJens Wiklander     memcpy(X->p, Y->p, i * ciL);
271817466cbSJens Wiklander 
272817466cbSJens Wiklander cleanup:
273817466cbSJens Wiklander 
274*32b31808SJens Wiklander     return ret;
275817466cbSJens Wiklander }
276817466cbSJens Wiklander 
277817466cbSJens Wiklander /*
278817466cbSJens Wiklander  * Swap the contents of X and Y
279817466cbSJens Wiklander  */
280817466cbSJens Wiklander void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
281817466cbSJens Wiklander {
282817466cbSJens Wiklander     mbedtls_mpi T;
2833d3b0591SJens Wiklander     MPI_VALIDATE(X != NULL);
2843d3b0591SJens Wiklander     MPI_VALIDATE(Y != NULL);
285817466cbSJens Wiklander 
286817466cbSJens Wiklander     memcpy(&T,  X, sizeof(mbedtls_mpi));
287817466cbSJens Wiklander     memcpy(X,  Y, sizeof(mbedtls_mpi));
288817466cbSJens Wiklander     memcpy(Y, &T, sizeof(mbedtls_mpi));
289817466cbSJens Wiklander }
290817466cbSJens Wiklander 
291*32b31808SJens Wiklander static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
292*32b31808SJens Wiklander {
293*32b31808SJens Wiklander     if (z >= 0) {
294*32b31808SJens Wiklander         return z;
295*32b31808SJens Wiklander     }
296*32b31808SJens Wiklander     /* Take care to handle the most negative value (-2^(biL-1)) correctly.
297*32b31808SJens Wiklander      * A naive -z would have undefined behavior.
298*32b31808SJens Wiklander      * Write this in a way that makes popular compilers happy (GCC, Clang,
299*32b31808SJens Wiklander      * MSVC). */
300*32b31808SJens Wiklander     return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
301*32b31808SJens Wiklander }
302*32b31808SJens Wiklander 
303817466cbSJens Wiklander /*
304817466cbSJens Wiklander  * Set value from integer
305817466cbSJens Wiklander  */
306817466cbSJens Wiklander int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
307817466cbSJens Wiklander {
30811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3093d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
310817466cbSJens Wiklander 
311817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
312817466cbSJens Wiklander     memset(X->p, 0, X->n * ciL);
313817466cbSJens Wiklander 
314*32b31808SJens Wiklander     X->p[0] = mpi_sint_abs(z);
315817466cbSJens Wiklander     X->s    = (z < 0) ? -1 : 1;
316817466cbSJens Wiklander 
317817466cbSJens Wiklander cleanup:
318817466cbSJens Wiklander 
319*32b31808SJens Wiklander     return ret;
320817466cbSJens Wiklander }
321817466cbSJens Wiklander 
322817466cbSJens Wiklander /*
323817466cbSJens Wiklander  * Get a specific bit
324817466cbSJens Wiklander  */
325817466cbSJens Wiklander int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
326817466cbSJens Wiklander {
3273d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
3283d3b0591SJens Wiklander 
329*32b31808SJens Wiklander     if (X->n * biL <= pos) {
330*32b31808SJens Wiklander         return 0;
331817466cbSJens Wiklander     }
332817466cbSJens Wiklander 
333*32b31808SJens Wiklander     return (X->p[pos / biL] >> (pos % biL)) & 0x01;
334*32b31808SJens Wiklander }
3353d3b0591SJens Wiklander 
336817466cbSJens Wiklander /*
337817466cbSJens Wiklander  * Set a bit to a specific value of 0 or 1
338817466cbSJens Wiklander  */
339817466cbSJens Wiklander int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
340817466cbSJens Wiklander {
341817466cbSJens Wiklander     int ret = 0;
342817466cbSJens Wiklander     size_t off = pos / biL;
343817466cbSJens Wiklander     size_t idx = pos % biL;
3443d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
345817466cbSJens Wiklander 
346*32b31808SJens Wiklander     if (val != 0 && val != 1) {
347*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
348*32b31808SJens Wiklander     }
349817466cbSJens Wiklander 
350*32b31808SJens Wiklander     if (X->n * biL <= pos) {
351*32b31808SJens Wiklander         if (val == 0) {
352*32b31808SJens Wiklander             return 0;
353*32b31808SJens Wiklander         }
354817466cbSJens Wiklander 
355817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
356817466cbSJens Wiklander     }
357817466cbSJens Wiklander 
358817466cbSJens Wiklander     X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
359817466cbSJens Wiklander     X->p[off] |= (mbedtls_mpi_uint) val << idx;
360817466cbSJens Wiklander 
361817466cbSJens Wiklander cleanup:
362817466cbSJens Wiklander 
363*32b31808SJens Wiklander     return ret;
364817466cbSJens Wiklander }
365817466cbSJens Wiklander 
366817466cbSJens Wiklander /*
367817466cbSJens Wiklander  * Return the number of less significant zero-bits
368817466cbSJens Wiklander  */
369817466cbSJens Wiklander size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
370817466cbSJens Wiklander {
371817466cbSJens Wiklander     size_t i, j, count = 0;
3723d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
373817466cbSJens Wiklander 
374*32b31808SJens Wiklander     for (i = 0; i < X->n; i++) {
375*32b31808SJens Wiklander         for (j = 0; j < biL; j++, count++) {
376*32b31808SJens Wiklander             if (((X->p[i] >> j) & 1) != 0) {
377*32b31808SJens Wiklander                 return count;
378*32b31808SJens Wiklander             }
379*32b31808SJens Wiklander         }
380817466cbSJens Wiklander     }
381817466cbSJens Wiklander 
382*32b31808SJens Wiklander     return 0;
383817466cbSJens Wiklander }
384817466cbSJens Wiklander 
385817466cbSJens Wiklander /*
386817466cbSJens Wiklander  * Return the number of bits
387817466cbSJens Wiklander  */
388817466cbSJens Wiklander size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
389817466cbSJens Wiklander {
390*32b31808SJens Wiklander     return mbedtls_mpi_core_bitlen(X->p, X->n);
391817466cbSJens Wiklander }
392817466cbSJens Wiklander 
393817466cbSJens Wiklander /*
394817466cbSJens Wiklander  * Return the total size in bytes
395817466cbSJens Wiklander  */
396817466cbSJens Wiklander size_t mbedtls_mpi_size(const mbedtls_mpi *X)
397817466cbSJens Wiklander {
398*32b31808SJens Wiklander     return (mbedtls_mpi_bitlen(X) + 7) >> 3;
399817466cbSJens Wiklander }
400817466cbSJens Wiklander 
401817466cbSJens Wiklander /*
402817466cbSJens Wiklander  * Convert an ASCII character to digit value
403817466cbSJens Wiklander  */
404817466cbSJens Wiklander static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
405817466cbSJens Wiklander {
406817466cbSJens Wiklander     *d = 255;
407817466cbSJens Wiklander 
408*32b31808SJens Wiklander     if (c >= 0x30 && c <= 0x39) {
409*32b31808SJens Wiklander         *d = c - 0x30;
410*32b31808SJens Wiklander     }
411*32b31808SJens Wiklander     if (c >= 0x41 && c <= 0x46) {
412*32b31808SJens Wiklander         *d = c - 0x37;
413*32b31808SJens Wiklander     }
414*32b31808SJens Wiklander     if (c >= 0x61 && c <= 0x66) {
415*32b31808SJens Wiklander         *d = c - 0x57;
416*32b31808SJens Wiklander     }
417817466cbSJens Wiklander 
418*32b31808SJens Wiklander     if (*d >= (mbedtls_mpi_uint) radix) {
419*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
420*32b31808SJens Wiklander     }
421817466cbSJens Wiklander 
422*32b31808SJens Wiklander     return 0;
423817466cbSJens Wiklander }
424817466cbSJens Wiklander 
425817466cbSJens Wiklander /*
426817466cbSJens Wiklander  * Import from an ASCII string
427817466cbSJens Wiklander  */
428817466cbSJens Wiklander int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
429817466cbSJens Wiklander {
43011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
431817466cbSJens Wiklander     size_t i, j, slen, n;
4327901324dSJerome Forissier     int sign = 1;
433817466cbSJens Wiklander     mbedtls_mpi_uint d;
434817466cbSJens Wiklander     mbedtls_mpi T;
4353d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
4363d3b0591SJens Wiklander     MPI_VALIDATE_RET(s != NULL);
437817466cbSJens Wiklander 
438*32b31808SJens Wiklander     if (radix < 2 || radix > 16) {
439*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
440*32b31808SJens Wiklander     }
441817466cbSJens Wiklander 
44298bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&T);
443817466cbSJens Wiklander 
444*32b31808SJens Wiklander     if (s[0] == 0) {
4457901324dSJerome Forissier         mbedtls_mpi_free(X);
446*32b31808SJens Wiklander         return 0;
4477901324dSJerome Forissier     }
4487901324dSJerome Forissier 
449*32b31808SJens Wiklander     if (s[0] == '-') {
4507901324dSJerome Forissier         ++s;
4517901324dSJerome Forissier         sign = -1;
4527901324dSJerome Forissier     }
4537901324dSJerome Forissier 
454817466cbSJens Wiklander     slen = strlen(s);
455817466cbSJens Wiklander 
456*32b31808SJens Wiklander     if (radix == 16) {
457*32b31808SJens Wiklander         if (slen > MPI_SIZE_T_MAX >> 2) {
458*32b31808SJens Wiklander             return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
459*32b31808SJens Wiklander         }
460817466cbSJens Wiklander 
461817466cbSJens Wiklander         n = BITS_TO_LIMBS(slen << 2);
462817466cbSJens Wiklander 
463817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
464817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
465817466cbSJens Wiklander 
466*32b31808SJens Wiklander         for (i = slen, j = 0; i > 0; i--, j++) {
467817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
468817466cbSJens Wiklander             X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
469817466cbSJens Wiklander         }
470*32b31808SJens Wiklander     } else {
471817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
472817466cbSJens Wiklander 
473*32b31808SJens Wiklander         for (i = 0; i < slen; i++) {
474817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
475817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
476817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
477817466cbSJens Wiklander         }
478817466cbSJens Wiklander     }
4797901324dSJerome Forissier 
480*32b31808SJens Wiklander     if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
4817901324dSJerome Forissier         X->s = -1;
482*32b31808SJens Wiklander     }
483817466cbSJens Wiklander 
484817466cbSJens Wiklander cleanup:
485817466cbSJens Wiklander 
486817466cbSJens Wiklander     mbedtls_mpi_free(&T);
487817466cbSJens Wiklander 
488*32b31808SJens Wiklander     return ret;
489817466cbSJens Wiklander }
490817466cbSJens Wiklander 
491817466cbSJens Wiklander /*
4925b25c76aSJerome Forissier  * Helper to write the digits high-order first.
493817466cbSJens Wiklander  */
4945b25c76aSJerome Forissier static int mpi_write_hlp(mbedtls_mpi *X, int radix,
4955b25c76aSJerome Forissier                          char **p, const size_t buflen)
496817466cbSJens Wiklander {
49711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
498817466cbSJens Wiklander     mbedtls_mpi_uint r;
4995b25c76aSJerome Forissier     size_t length = 0;
5005b25c76aSJerome Forissier     char *p_end = *p + buflen;
501817466cbSJens Wiklander 
502*32b31808SJens Wiklander     do {
503*32b31808SJens Wiklander         if (length >= buflen) {
504*32b31808SJens Wiklander             return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
5055b25c76aSJerome Forissier         }
506817466cbSJens Wiklander 
507817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
508817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
5095b25c76aSJerome Forissier         /*
5105b25c76aSJerome Forissier          * Write the residue in the current position, as an ASCII character.
5115b25c76aSJerome Forissier          */
512*32b31808SJens Wiklander         if (r < 0xA) {
5135b25c76aSJerome Forissier             *(--p_end) = (char) ('0' + r);
514*32b31808SJens Wiklander         } else {
5155b25c76aSJerome Forissier             *(--p_end) = (char) ('A' + (r - 0xA));
516*32b31808SJens Wiklander         }
5175b25c76aSJerome Forissier 
5185b25c76aSJerome Forissier         length++;
5195b25c76aSJerome Forissier     } while (mbedtls_mpi_cmp_int(X, 0) != 0);
5205b25c76aSJerome Forissier 
5215b25c76aSJerome Forissier     memmove(*p, p_end, length);
5225b25c76aSJerome Forissier     *p += length;
523817466cbSJens Wiklander 
524817466cbSJens Wiklander cleanup:
525817466cbSJens Wiklander 
526*32b31808SJens Wiklander     return ret;
527817466cbSJens Wiklander }
528817466cbSJens Wiklander 
529817466cbSJens Wiklander /*
530817466cbSJens Wiklander  * Export into an ASCII string
531817466cbSJens Wiklander  */
532817466cbSJens Wiklander int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
533817466cbSJens Wiklander                              char *buf, size_t buflen, size_t *olen)
534817466cbSJens Wiklander {
535817466cbSJens Wiklander     int ret = 0;
536817466cbSJens Wiklander     size_t n;
537817466cbSJens Wiklander     char *p;
538817466cbSJens Wiklander     mbedtls_mpi T;
5393d3b0591SJens Wiklander     MPI_VALIDATE_RET(X    != NULL);
5403d3b0591SJens Wiklander     MPI_VALIDATE_RET(olen != NULL);
5413d3b0591SJens Wiklander     MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
542817466cbSJens Wiklander 
543*32b31808SJens Wiklander     if (radix < 2 || radix > 16) {
544*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
545*32b31808SJens Wiklander     }
546817466cbSJens Wiklander 
5475b25c76aSJerome Forissier     n = mbedtls_mpi_bitlen(X);   /* Number of bits necessary to present `n`. */
548*32b31808SJens Wiklander     if (radix >=  4) {
549*32b31808SJens Wiklander         n >>= 1;                 /* Number of 4-adic digits necessary to present
5505b25c76aSJerome Forissier                                   * `n`. If radix > 4, this might be a strict
5515b25c76aSJerome Forissier                                   * overapproximation of the number of
5525b25c76aSJerome Forissier                                   * radix-adic digits needed to present `n`. */
553*32b31808SJens Wiklander     }
554*32b31808SJens Wiklander     if (radix >= 16) {
555*32b31808SJens Wiklander         n >>= 1;                 /* Number of hexadecimal digits necessary to
5565b25c76aSJerome Forissier                                   * present `n`. */
5575b25c76aSJerome Forissier 
558*32b31808SJens Wiklander     }
5595b25c76aSJerome Forissier     n += 1; /* Terminating null byte */
5605b25c76aSJerome Forissier     n += 1; /* Compensate for the divisions above, which round down `n`
5615b25c76aSJerome Forissier              * in case it's not even. */
5625b25c76aSJerome Forissier     n += 1; /* Potential '-'-sign. */
5635b25c76aSJerome Forissier     n += (n & 1);   /* Make n even to have enough space for hexadecimal writing,
5645b25c76aSJerome Forissier                      * which always uses an even number of hex-digits. */
565817466cbSJens Wiklander 
566*32b31808SJens Wiklander     if (buflen < n) {
567817466cbSJens Wiklander         *olen = n;
568*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
569817466cbSJens Wiklander     }
570817466cbSJens Wiklander 
571817466cbSJens Wiklander     p = buf;
57298bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&T);
573817466cbSJens Wiklander 
574*32b31808SJens Wiklander     if (X->s == -1) {
575817466cbSJens Wiklander         *p++ = '-';
5765b25c76aSJerome Forissier         buflen--;
5775b25c76aSJerome Forissier     }
578817466cbSJens Wiklander 
579*32b31808SJens Wiklander     if (radix == 16) {
580817466cbSJens Wiklander         int c;
581817466cbSJens Wiklander         size_t i, j, k;
582817466cbSJens Wiklander 
583*32b31808SJens Wiklander         for (i = X->n, k = 0; i > 0; i--) {
584*32b31808SJens Wiklander             for (j = ciL; j > 0; j--) {
585817466cbSJens Wiklander                 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
586817466cbSJens Wiklander 
587*32b31808SJens Wiklander                 if (c == 0 && k == 0 && (i + j) != 2) {
588817466cbSJens Wiklander                     continue;
589*32b31808SJens Wiklander                 }
590817466cbSJens Wiklander 
591817466cbSJens Wiklander                 *(p++) = "0123456789ABCDEF" [c / 16];
592817466cbSJens Wiklander                 *(p++) = "0123456789ABCDEF" [c % 16];
593817466cbSJens Wiklander                 k = 1;
594817466cbSJens Wiklander             }
595817466cbSJens Wiklander         }
596*32b31808SJens Wiklander     } else {
597817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
598817466cbSJens Wiklander 
599*32b31808SJens Wiklander         if (T.s == -1) {
600817466cbSJens Wiklander             T.s = 1;
601*32b31808SJens Wiklander         }
602817466cbSJens Wiklander 
6035b25c76aSJerome Forissier         MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
604817466cbSJens Wiklander     }
605817466cbSJens Wiklander 
606817466cbSJens Wiklander     *p++ = '\0';
607817466cbSJens Wiklander     *olen = p - buf;
608817466cbSJens Wiklander 
609817466cbSJens Wiklander cleanup:
610817466cbSJens Wiklander 
611817466cbSJens Wiklander     mbedtls_mpi_free(&T);
612817466cbSJens Wiklander 
613*32b31808SJens Wiklander     return ret;
614817466cbSJens Wiklander }
615817466cbSJens Wiklander 
616817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
617817466cbSJens Wiklander /*
618817466cbSJens Wiklander  * Read X from an opened file
619817466cbSJens Wiklander  */
620817466cbSJens Wiklander int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
621817466cbSJens Wiklander {
622817466cbSJens Wiklander     mbedtls_mpi_uint d;
623817466cbSJens Wiklander     size_t slen;
624817466cbSJens Wiklander     char *p;
625817466cbSJens Wiklander     /*
626817466cbSJens Wiklander      * Buffer should have space for (short) label and decimal formatted MPI,
627817466cbSJens Wiklander      * newline characters and '\0'
628817466cbSJens Wiklander      */
629817466cbSJens Wiklander     char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
630817466cbSJens Wiklander 
6313d3b0591SJens Wiklander     MPI_VALIDATE_RET(X   != NULL);
6323d3b0591SJens Wiklander     MPI_VALIDATE_RET(fin != NULL);
6333d3b0591SJens Wiklander 
634*32b31808SJens Wiklander     if (radix < 2 || radix > 16) {
635*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
636*32b31808SJens Wiklander     }
6373d3b0591SJens Wiklander 
638817466cbSJens Wiklander     memset(s, 0, sizeof(s));
639*32b31808SJens Wiklander     if (fgets(s, sizeof(s) - 1, fin) == NULL) {
640*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
641*32b31808SJens Wiklander     }
642817466cbSJens Wiklander 
643817466cbSJens Wiklander     slen = strlen(s);
644*32b31808SJens Wiklander     if (slen == sizeof(s) - 2) {
645*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
646*32b31808SJens Wiklander     }
647817466cbSJens Wiklander 
648*32b31808SJens Wiklander     if (slen > 0 && s[slen - 1] == '\n') {
649*32b31808SJens Wiklander         slen--; s[slen] = '\0';
650*32b31808SJens Wiklander     }
651*32b31808SJens Wiklander     if (slen > 0 && s[slen - 1] == '\r') {
652*32b31808SJens Wiklander         slen--; s[slen] = '\0';
653*32b31808SJens Wiklander     }
654817466cbSJens Wiklander 
655817466cbSJens Wiklander     p = s + slen;
656*32b31808SJens Wiklander     while (p-- > s) {
657*32b31808SJens Wiklander         if (mpi_get_digit(&d, radix, *p) != 0) {
658817466cbSJens Wiklander             break;
659*32b31808SJens Wiklander         }
660*32b31808SJens Wiklander     }
661817466cbSJens Wiklander 
662*32b31808SJens Wiklander     return mbedtls_mpi_read_string(X, radix, p + 1);
663817466cbSJens Wiklander }
664817466cbSJens Wiklander 
665817466cbSJens Wiklander /*
666817466cbSJens Wiklander  * Write X into an opened file (or stdout if fout == NULL)
667817466cbSJens Wiklander  */
668817466cbSJens Wiklander int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
669817466cbSJens Wiklander {
67011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
671817466cbSJens Wiklander     size_t n, slen, plen;
672817466cbSJens Wiklander     /*
673817466cbSJens Wiklander      * Buffer should have space for (short) label and decimal formatted MPI,
674817466cbSJens Wiklander      * newline characters and '\0'
675817466cbSJens Wiklander      */
676817466cbSJens Wiklander     char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
6773d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
6783d3b0591SJens Wiklander 
679*32b31808SJens Wiklander     if (radix < 2 || radix > 16) {
680*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
681*32b31808SJens Wiklander     }
682817466cbSJens Wiklander 
683817466cbSJens Wiklander     memset(s, 0, sizeof(s));
684817466cbSJens Wiklander 
685817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
686817466cbSJens Wiklander 
687*32b31808SJens Wiklander     if (p == NULL) {
688*32b31808SJens Wiklander         p = "";
689*32b31808SJens Wiklander     }
690817466cbSJens Wiklander 
691817466cbSJens Wiklander     plen = strlen(p);
692817466cbSJens Wiklander     slen = strlen(s);
693817466cbSJens Wiklander     s[slen++] = '\r';
694817466cbSJens Wiklander     s[slen++] = '\n';
695817466cbSJens Wiklander 
696*32b31808SJens Wiklander     if (fout != NULL) {
697817466cbSJens Wiklander         if (fwrite(p, 1, plen, fout) != plen ||
698*32b31808SJens Wiklander             fwrite(s, 1, slen, fout) != slen) {
699*32b31808SJens Wiklander             return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
700817466cbSJens Wiklander         }
701*32b31808SJens Wiklander     } else {
702817466cbSJens Wiklander         mbedtls_printf("%s%s", p, s);
703*32b31808SJens Wiklander     }
704817466cbSJens Wiklander 
705817466cbSJens Wiklander cleanup:
706817466cbSJens Wiklander 
707*32b31808SJens Wiklander     return ret;
708817466cbSJens Wiklander }
709817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
710817466cbSJens Wiklander 
711817466cbSJens Wiklander /*
71211fa71b9SJerome Forissier  * Import X from unsigned binary data, little endian
713*32b31808SJens Wiklander  *
714*32b31808SJens Wiklander  * This function is guaranteed to return an MPI with exactly the necessary
715*32b31808SJens Wiklander  * number of limbs (in particular, it does not skip 0s in the input).
71611fa71b9SJerome Forissier  */
71711fa71b9SJerome Forissier int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
71811fa71b9SJerome Forissier                                const unsigned char *buf, size_t buflen)
71911fa71b9SJerome Forissier {
72011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
721*32b31808SJens Wiklander     const size_t limbs = CHARS_TO_LIMBS(buflen);
72211fa71b9SJerome Forissier 
72311fa71b9SJerome Forissier     /* Ensure that target MPI has exactly the necessary number of limbs */
7247901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
72511fa71b9SJerome Forissier 
726*32b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
72711fa71b9SJerome Forissier 
72811fa71b9SJerome Forissier cleanup:
72911fa71b9SJerome Forissier 
73011fa71b9SJerome Forissier     /*
73111fa71b9SJerome Forissier      * This function is also used to import keys. However, wiping the buffers
73211fa71b9SJerome Forissier      * upon failure is not necessary because failure only can happen before any
73311fa71b9SJerome Forissier      * input is copied.
73411fa71b9SJerome Forissier      */
735*32b31808SJens Wiklander     return ret;
73611fa71b9SJerome Forissier }
73711fa71b9SJerome Forissier 
73811fa71b9SJerome Forissier /*
739817466cbSJens Wiklander  * Import X from unsigned binary data, big endian
740*32b31808SJens Wiklander  *
741*32b31808SJens Wiklander  * This function is guaranteed to return an MPI with exactly the necessary
742*32b31808SJens Wiklander  * number of limbs (in particular, it does not skip 0s in the input).
743817466cbSJens Wiklander  */
744817466cbSJens Wiklander int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
745817466cbSJens Wiklander {
74611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
747*32b31808SJens Wiklander     const size_t limbs = CHARS_TO_LIMBS(buflen);
748817466cbSJens Wiklander 
7493d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
7503d3b0591SJens Wiklander     MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
751817466cbSJens Wiklander 
7523d3b0591SJens Wiklander     /* Ensure that target MPI has exactly the necessary number of limbs */
7537901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
7542976273fSJens Wiklander 
755*32b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
756817466cbSJens Wiklander 
757817466cbSJens Wiklander cleanup:
758817466cbSJens Wiklander 
75911fa71b9SJerome Forissier     /*
76011fa71b9SJerome Forissier      * This function is also used to import keys. However, wiping the buffers
76111fa71b9SJerome Forissier      * upon failure is not necessary because failure only can happen before any
76211fa71b9SJerome Forissier      * input is copied.
76311fa71b9SJerome Forissier      */
764*32b31808SJens Wiklander     return ret;
765817466cbSJens Wiklander }
766817466cbSJens Wiklander 
767817466cbSJens Wiklander /*
76811fa71b9SJerome Forissier  * Export X into unsigned binary data, little endian
76911fa71b9SJerome Forissier  */
77011fa71b9SJerome Forissier int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
77111fa71b9SJerome Forissier                                 unsigned char *buf, size_t buflen)
77211fa71b9SJerome Forissier {
773*32b31808SJens Wiklander     return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
77411fa71b9SJerome Forissier }
77511fa71b9SJerome Forissier 
77611fa71b9SJerome Forissier /*
777817466cbSJens Wiklander  * Export X into unsigned binary data, big endian
778817466cbSJens Wiklander  */
7793d3b0591SJens Wiklander int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
7803d3b0591SJens Wiklander                              unsigned char *buf, size_t buflen)
781817466cbSJens Wiklander {
782*32b31808SJens Wiklander     return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
783817466cbSJens Wiklander }
784817466cbSJens Wiklander 
785817466cbSJens Wiklander /*
786817466cbSJens Wiklander  * Left-shift: X <<= count
787817466cbSJens Wiklander  */
788817466cbSJens Wiklander int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
789817466cbSJens Wiklander {
79011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
791817466cbSJens Wiklander     size_t i, v0, t1;
792817466cbSJens Wiklander     mbedtls_mpi_uint r0 = 0, r1;
7933d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
794817466cbSJens Wiklander 
795817466cbSJens Wiklander     v0 = count / (biL);
796817466cbSJens Wiklander     t1 = count & (biL - 1);
797817466cbSJens Wiklander 
798817466cbSJens Wiklander     i = mbedtls_mpi_bitlen(X) + count;
799817466cbSJens Wiklander 
800*32b31808SJens Wiklander     if (X->n * biL < i) {
801817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
802*32b31808SJens Wiklander     }
803817466cbSJens Wiklander 
804817466cbSJens Wiklander     ret = 0;
805817466cbSJens Wiklander 
806817466cbSJens Wiklander     /*
807817466cbSJens Wiklander      * shift by count / limb_size
808817466cbSJens Wiklander      */
809*32b31808SJens Wiklander     if (v0 > 0) {
810*32b31808SJens Wiklander         for (i = X->n; i > v0; i--) {
811817466cbSJens Wiklander             X->p[i - 1] = X->p[i - v0 - 1];
812*32b31808SJens Wiklander         }
813817466cbSJens Wiklander 
814*32b31808SJens Wiklander         for (; i > 0; i--) {
815817466cbSJens Wiklander             X->p[i - 1] = 0;
816817466cbSJens Wiklander         }
817*32b31808SJens Wiklander     }
818817466cbSJens Wiklander 
819817466cbSJens Wiklander     /*
820817466cbSJens Wiklander      * shift by count % limb_size
821817466cbSJens Wiklander      */
822*32b31808SJens Wiklander     if (t1 > 0) {
823*32b31808SJens Wiklander         for (i = v0; i < X->n; i++) {
824817466cbSJens Wiklander             r1 = X->p[i] >> (biL - t1);
825817466cbSJens Wiklander             X->p[i] <<= t1;
826817466cbSJens Wiklander             X->p[i] |= r0;
827817466cbSJens Wiklander             r0 = r1;
828817466cbSJens Wiklander         }
829817466cbSJens Wiklander     }
830817466cbSJens Wiklander 
831817466cbSJens Wiklander cleanup:
832817466cbSJens Wiklander 
833*32b31808SJens Wiklander     return ret;
834817466cbSJens Wiklander }
835817466cbSJens Wiklander 
836817466cbSJens Wiklander /*
837817466cbSJens Wiklander  * Right-shift: X >>= count
838817466cbSJens Wiklander  */
839817466cbSJens Wiklander int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
840817466cbSJens Wiklander {
8413d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
842*32b31808SJens Wiklander     if (X->n != 0) {
843*32b31808SJens Wiklander         mbedtls_mpi_core_shift_r(X->p, X->n, count);
844817466cbSJens Wiklander     }
845*32b31808SJens Wiklander     return 0;
846817466cbSJens Wiklander }
847817466cbSJens Wiklander 
848817466cbSJens Wiklander /*
849817466cbSJens Wiklander  * Compare unsigned values
850817466cbSJens Wiklander  */
851817466cbSJens Wiklander int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
852817466cbSJens Wiklander {
853817466cbSJens Wiklander     size_t i, j;
8543d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
8553d3b0591SJens Wiklander     MPI_VALIDATE_RET(Y != NULL);
856817466cbSJens Wiklander 
857*32b31808SJens Wiklander     for (i = X->n; i > 0; i--) {
858*32b31808SJens Wiklander         if (X->p[i - 1] != 0) {
859817466cbSJens Wiklander             break;
860*32b31808SJens Wiklander         }
861817466cbSJens Wiklander     }
862817466cbSJens Wiklander 
863*32b31808SJens Wiklander     for (j = Y->n; j > 0; j--) {
864*32b31808SJens Wiklander         if (Y->p[j - 1] != 0) {
865*32b31808SJens Wiklander             break;
866*32b31808SJens Wiklander         }
867*32b31808SJens Wiklander     }
868*32b31808SJens Wiklander 
869*32b31808SJens Wiklander     if (i == 0 && j == 0) {
870*32b31808SJens Wiklander         return 0;
871*32b31808SJens Wiklander     }
872*32b31808SJens Wiklander 
873*32b31808SJens Wiklander     if (i > j) {
874*32b31808SJens Wiklander         return 1;
875*32b31808SJens Wiklander     }
876*32b31808SJens Wiklander     if (j > i) {
877*32b31808SJens Wiklander         return -1;
878*32b31808SJens Wiklander     }
879*32b31808SJens Wiklander 
880*32b31808SJens Wiklander     for (; i > 0; i--) {
881*32b31808SJens Wiklander         if (X->p[i - 1] > Y->p[i - 1]) {
882*32b31808SJens Wiklander             return 1;
883*32b31808SJens Wiklander         }
884*32b31808SJens Wiklander         if (X->p[i - 1] < Y->p[i - 1]) {
885*32b31808SJens Wiklander             return -1;
886*32b31808SJens Wiklander         }
887*32b31808SJens Wiklander     }
888*32b31808SJens Wiklander 
889*32b31808SJens Wiklander     return 0;
890817466cbSJens Wiklander }
891817466cbSJens Wiklander 
892817466cbSJens Wiklander /*
893817466cbSJens Wiklander  * Compare signed values
894817466cbSJens Wiklander  */
895817466cbSJens Wiklander int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
896817466cbSJens Wiklander {
897817466cbSJens Wiklander     size_t i, j;
8983d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
8993d3b0591SJens Wiklander     MPI_VALIDATE_RET(Y != NULL);
900817466cbSJens Wiklander 
901*32b31808SJens Wiklander     for (i = X->n; i > 0; i--) {
902*32b31808SJens Wiklander         if (X->p[i - 1] != 0) {
903817466cbSJens Wiklander             break;
904*32b31808SJens Wiklander         }
905817466cbSJens Wiklander     }
906817466cbSJens Wiklander 
907*32b31808SJens Wiklander     for (j = Y->n; j > 0; j--) {
908*32b31808SJens Wiklander         if (Y->p[j - 1] != 0) {
909*32b31808SJens Wiklander             break;
910*32b31808SJens Wiklander         }
911*32b31808SJens Wiklander     }
912*32b31808SJens Wiklander 
913*32b31808SJens Wiklander     if (i == 0 && j == 0) {
914*32b31808SJens Wiklander         return 0;
915*32b31808SJens Wiklander     }
916*32b31808SJens Wiklander 
917*32b31808SJens Wiklander     if (i > j) {
918*32b31808SJens Wiklander         return X->s;
919*32b31808SJens Wiklander     }
920*32b31808SJens Wiklander     if (j > i) {
921*32b31808SJens Wiklander         return -Y->s;
922*32b31808SJens Wiklander     }
923*32b31808SJens Wiklander 
924*32b31808SJens Wiklander     if (X->s > 0 && Y->s < 0) {
925*32b31808SJens Wiklander         return 1;
926*32b31808SJens Wiklander     }
927*32b31808SJens Wiklander     if (Y->s > 0 && X->s < 0) {
928*32b31808SJens Wiklander         return -1;
929*32b31808SJens Wiklander     }
930*32b31808SJens Wiklander 
931*32b31808SJens Wiklander     for (; i > 0; i--) {
932*32b31808SJens Wiklander         if (X->p[i - 1] > Y->p[i - 1]) {
933*32b31808SJens Wiklander             return X->s;
934*32b31808SJens Wiklander         }
935*32b31808SJens Wiklander         if (X->p[i - 1] < Y->p[i - 1]) {
936*32b31808SJens Wiklander             return -X->s;
937*32b31808SJens Wiklander         }
938*32b31808SJens Wiklander     }
939*32b31808SJens Wiklander 
940*32b31808SJens Wiklander     return 0;
941817466cbSJens Wiklander }
942817466cbSJens Wiklander 
943817466cbSJens Wiklander /*
944817466cbSJens Wiklander  * Compare signed values
945817466cbSJens Wiklander  */
946817466cbSJens Wiklander int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
947817466cbSJens Wiklander {
948817466cbSJens Wiklander     mbedtls_mpi Y;
949817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
9503d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
951817466cbSJens Wiklander 
952*32b31808SJens Wiklander     *p  = mpi_sint_abs(z);
953817466cbSJens Wiklander     Y.s = (z < 0) ? -1 : 1;
954817466cbSJens Wiklander     Y.n = 1;
955817466cbSJens Wiklander     Y.p = p;
956817466cbSJens Wiklander 
957*32b31808SJens Wiklander     return mbedtls_mpi_cmp_mpi(X, &Y);
958817466cbSJens Wiklander }
959817466cbSJens Wiklander 
960817466cbSJens Wiklander /*
961817466cbSJens Wiklander  * Unsigned addition: X = |A| + |B|  (HAC 14.7)
962817466cbSJens Wiklander  */
963817466cbSJens Wiklander int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
964817466cbSJens Wiklander {
96511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
966*32b31808SJens Wiklander     size_t j;
9673d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
9683d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
9693d3b0591SJens Wiklander     MPI_VALIDATE_RET(B != NULL);
970817466cbSJens Wiklander 
971*32b31808SJens Wiklander     if (X == B) {
972817466cbSJens Wiklander         const mbedtls_mpi *T = A; A = X; B = T;
973817466cbSJens Wiklander     }
974817466cbSJens Wiklander 
975*32b31808SJens Wiklander     if (X != A) {
976817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
977*32b31808SJens Wiklander     }
978817466cbSJens Wiklander 
979817466cbSJens Wiklander     /*
980*32b31808SJens Wiklander      * X must always be positive as a result of unsigned additions.
981817466cbSJens Wiklander      */
982817466cbSJens Wiklander     X->s = 1;
983817466cbSJens Wiklander 
984*32b31808SJens Wiklander     for (j = B->n; j > 0; j--) {
985*32b31808SJens Wiklander         if (B->p[j - 1] != 0) {
986817466cbSJens Wiklander             break;
987*32b31808SJens Wiklander         }
988*32b31808SJens Wiklander     }
989*32b31808SJens Wiklander 
990*32b31808SJens Wiklander     /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
991*32b31808SJens Wiklander      * and B is 0 (of any size). */
992*32b31808SJens Wiklander     if (j == 0) {
993*32b31808SJens Wiklander         return 0;
994*32b31808SJens Wiklander     }
995817466cbSJens Wiklander 
996817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
997817466cbSJens Wiklander 
998*32b31808SJens Wiklander     /* j is the number of non-zero limbs of B. Add those to X. */
999817466cbSJens Wiklander 
1000*32b31808SJens Wiklander     mbedtls_mpi_uint *p = X->p;
1001*32b31808SJens Wiklander 
1002*32b31808SJens Wiklander     mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j);
1003*32b31808SJens Wiklander 
1004*32b31808SJens Wiklander     p += j;
1005*32b31808SJens Wiklander 
1006*32b31808SJens Wiklander     /* Now propagate any carry */
1007*32b31808SJens Wiklander 
1008*32b31808SJens Wiklander     while (c != 0) {
1009*32b31808SJens Wiklander         if (j >= X->n) {
1010*32b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
1011*32b31808SJens Wiklander             p = X->p + j;
1012817466cbSJens Wiklander         }
1013817466cbSJens Wiklander 
1014*32b31808SJens Wiklander         *p += c; c = (*p < c); j++; p++;
1015817466cbSJens Wiklander     }
1016817466cbSJens Wiklander 
1017817466cbSJens Wiklander cleanup:
1018817466cbSJens Wiklander 
1019*32b31808SJens Wiklander     return ret;
1020817466cbSJens Wiklander }
1021817466cbSJens Wiklander 
1022817466cbSJens Wiklander /*
10237901324dSJerome Forissier  * Unsigned subtraction: X = |A| - |B|  (HAC 14.9, 14.10)
1024817466cbSJens Wiklander  */
1025817466cbSJens Wiklander int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
1026817466cbSJens Wiklander {
102711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1028817466cbSJens Wiklander     size_t n;
10297901324dSJerome Forissier     mbedtls_mpi_uint carry;
10303d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
10313d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
10323d3b0591SJens Wiklander     MPI_VALIDATE_RET(B != NULL);
1033817466cbSJens Wiklander 
1034*32b31808SJens Wiklander     for (n = B->n; n > 0; n--) {
1035*32b31808SJens Wiklander         if (B->p[n - 1] != 0) {
1036817466cbSJens Wiklander             break;
1037*32b31808SJens Wiklander         }
1038*32b31808SJens Wiklander     }
1039*32b31808SJens Wiklander     if (n > A->n) {
10407901324dSJerome Forissier         /* B >= (2^ciL)^n > A */
10417901324dSJerome Forissier         ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
10427901324dSJerome Forissier         goto cleanup;
10437901324dSJerome Forissier     }
1044817466cbSJens Wiklander 
10457901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
10467901324dSJerome Forissier 
10477901324dSJerome Forissier     /* Set the high limbs of X to match A. Don't touch the lower limbs
10487901324dSJerome Forissier      * because X might be aliased to B, and we must not overwrite the
10497901324dSJerome Forissier      * significant digits of B. */
1050*32b31808SJens Wiklander     if (A->n > n && A != X) {
10517901324dSJerome Forissier         memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1052*32b31808SJens Wiklander     }
1053*32b31808SJens Wiklander     if (X->n > A->n) {
10547901324dSJerome Forissier         memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1055*32b31808SJens Wiklander     }
10567901324dSJerome Forissier 
1057*32b31808SJens Wiklander     carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1058*32b31808SJens Wiklander     if (carry != 0) {
1059*32b31808SJens Wiklander         /* Propagate the carry through the rest of X. */
1060*32b31808SJens Wiklander         carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
1061*32b31808SJens Wiklander 
1062*32b31808SJens Wiklander         /* If we have further carry/borrow, the result is negative. */
1063*32b31808SJens Wiklander         if (carry != 0) {
10647901324dSJerome Forissier             ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
10657901324dSJerome Forissier             goto cleanup;
10667901324dSJerome Forissier         }
10677901324dSJerome Forissier     }
10687901324dSJerome Forissier 
10697901324dSJerome Forissier     /* X should always be positive as a result of unsigned subtractions. */
10707901324dSJerome Forissier     X->s = 1;
1071817466cbSJens Wiklander 
1072817466cbSJens Wiklander cleanup:
1073*32b31808SJens Wiklander     return ret;
1074*32b31808SJens Wiklander }
1075*32b31808SJens Wiklander 
1076*32b31808SJens Wiklander /* Common function for signed addition and subtraction.
1077*32b31808SJens Wiklander  * Calculate A + B * flip_B where flip_B is 1 or -1.
1078*32b31808SJens Wiklander  */
1079*32b31808SJens Wiklander static int add_sub_mpi(mbedtls_mpi *X,
1080*32b31808SJens Wiklander                        const mbedtls_mpi *A, const mbedtls_mpi *B,
1081*32b31808SJens Wiklander                        int flip_B)
1082*32b31808SJens Wiklander {
1083*32b31808SJens Wiklander     int ret, s;
1084*32b31808SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
1085*32b31808SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
1086*32b31808SJens Wiklander     MPI_VALIDATE_RET(B != NULL);
1087*32b31808SJens Wiklander 
1088*32b31808SJens Wiklander     s = A->s;
1089*32b31808SJens Wiklander     if (A->s * B->s * flip_B < 0) {
1090*32b31808SJens Wiklander         int cmp = mbedtls_mpi_cmp_abs(A, B);
1091*32b31808SJens Wiklander         if (cmp >= 0) {
1092*32b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
1093*32b31808SJens Wiklander             /* If |A| = |B|, the result is 0 and we must set the sign bit
1094*32b31808SJens Wiklander              * to +1 regardless of which of A or B was negative. Otherwise,
1095*32b31808SJens Wiklander              * since |A| > |B|, the sign is the sign of A. */
1096*32b31808SJens Wiklander             X->s = cmp == 0 ? 1 : s;
1097*32b31808SJens Wiklander         } else {
1098*32b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
1099*32b31808SJens Wiklander             /* Since |A| < |B|, the sign is the opposite of A. */
1100*32b31808SJens Wiklander             X->s = -s;
1101*32b31808SJens Wiklander         }
1102*32b31808SJens Wiklander     } else {
1103*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
1104*32b31808SJens Wiklander         X->s = s;
1105*32b31808SJens Wiklander     }
1106*32b31808SJens Wiklander 
1107*32b31808SJens Wiklander cleanup:
1108*32b31808SJens Wiklander 
1109*32b31808SJens Wiklander     return ret;
1110817466cbSJens Wiklander }
1111817466cbSJens Wiklander 
1112817466cbSJens Wiklander /*
1113817466cbSJens Wiklander  * Signed addition: X = A + B
1114817466cbSJens Wiklander  */
1115817466cbSJens Wiklander int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
1116817466cbSJens Wiklander {
1117*32b31808SJens Wiklander     return add_sub_mpi(X, A, B, 1);
1118817466cbSJens Wiklander }
1119817466cbSJens Wiklander 
1120817466cbSJens Wiklander /*
1121817466cbSJens Wiklander  * Signed subtraction: X = A - B
1122817466cbSJens Wiklander  */
1123817466cbSJens Wiklander int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
1124817466cbSJens Wiklander {
1125*32b31808SJens Wiklander     return add_sub_mpi(X, A, B, -1);
1126817466cbSJens Wiklander }
1127817466cbSJens Wiklander 
1128817466cbSJens Wiklander /*
1129817466cbSJens Wiklander  * Signed addition: X = A + b
1130817466cbSJens Wiklander  */
1131817466cbSJens Wiklander int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
1132817466cbSJens Wiklander {
1133039e02dfSJerome Forissier     mbedtls_mpi B;
1134817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
11353d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
11363d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
1137817466cbSJens Wiklander 
1138*32b31808SJens Wiklander     p[0] = mpi_sint_abs(b);
1139039e02dfSJerome Forissier     B.s = (b < 0) ? -1 : 1;
1140039e02dfSJerome Forissier     B.n = 1;
1141039e02dfSJerome Forissier     B.p = p;
1142817466cbSJens Wiklander 
1143*32b31808SJens Wiklander     return mbedtls_mpi_add_mpi(X, A, &B);
1144817466cbSJens Wiklander }
1145817466cbSJens Wiklander 
1146817466cbSJens Wiklander /*
1147817466cbSJens Wiklander  * Signed subtraction: X = A - b
1148817466cbSJens Wiklander  */
1149817466cbSJens Wiklander int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
1150817466cbSJens Wiklander {
1151039e02dfSJerome Forissier     mbedtls_mpi B;
1152817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
11533d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
11543d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
1155817466cbSJens Wiklander 
1156*32b31808SJens Wiklander     p[0] = mpi_sint_abs(b);
1157039e02dfSJerome Forissier     B.s = (b < 0) ? -1 : 1;
1158039e02dfSJerome Forissier     B.n = 1;
1159039e02dfSJerome Forissier     B.p = p;
1160817466cbSJens Wiklander 
1161*32b31808SJens Wiklander     return mbedtls_mpi_sub_mpi(X, A, &B);
1162817466cbSJens Wiklander }
1163817466cbSJens Wiklander 
1164817466cbSJens Wiklander /*
1165817466cbSJens Wiklander  * Baseline multiplication: X = A * B  (HAC 14.12)
1166817466cbSJens Wiklander  */
1167817466cbSJens Wiklander int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
1168817466cbSJens Wiklander {
116911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1170817466cbSJens Wiklander     size_t i, j;
1171817466cbSJens Wiklander     mbedtls_mpi TA, TB;
11727901324dSJerome Forissier     int result_is_zero = 0;
11733d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
11743d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
11753d3b0591SJens Wiklander     MPI_VALIDATE_RET(B != NULL);
1176817466cbSJens Wiklander 
117798bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
1178817466cbSJens Wiklander 
1179*32b31808SJens Wiklander     if (X == A) {
1180*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1181*32b31808SJens Wiklander     }
1182*32b31808SJens Wiklander     if (X == B) {
1183*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1184*32b31808SJens Wiklander     }
1185817466cbSJens Wiklander 
1186*32b31808SJens Wiklander     for (i = A->n; i > 0; i--) {
1187*32b31808SJens Wiklander         if (A->p[i - 1] != 0) {
1188817466cbSJens Wiklander             break;
1189*32b31808SJens Wiklander         }
1190*32b31808SJens Wiklander     }
1191*32b31808SJens Wiklander     if (i == 0) {
11927901324dSJerome Forissier         result_is_zero = 1;
1193*32b31808SJens Wiklander     }
1194817466cbSJens Wiklander 
1195*32b31808SJens Wiklander     for (j = B->n; j > 0; j--) {
1196*32b31808SJens Wiklander         if (B->p[j - 1] != 0) {
1197817466cbSJens Wiklander             break;
1198*32b31808SJens Wiklander         }
1199*32b31808SJens Wiklander     }
1200*32b31808SJens Wiklander     if (j == 0) {
12017901324dSJerome Forissier         result_is_zero = 1;
1202*32b31808SJens Wiklander     }
1203817466cbSJens Wiklander 
1204817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1205817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
1206817466cbSJens Wiklander 
1207*32b31808SJens Wiklander     for (size_t k = 0; k < j; k++) {
1208*32b31808SJens Wiklander         /* We know that there cannot be any carry-out since we're
1209*32b31808SJens Wiklander          * iterating from bottom to top. */
1210*32b31808SJens Wiklander         (void) mbedtls_mpi_core_mla(X->p + k, i + 1,
1211*32b31808SJens Wiklander                                     A->p, i,
1212*32b31808SJens Wiklander                                     B->p[k]);
1213*32b31808SJens Wiklander     }
1214817466cbSJens Wiklander 
12157901324dSJerome Forissier     /* If the result is 0, we don't shortcut the operation, which reduces
12167901324dSJerome Forissier      * but does not eliminate side channels leaking the zero-ness. We do
12177901324dSJerome Forissier      * need to take care to set the sign bit properly since the library does
12187901324dSJerome Forissier      * not fully support an MPI object with a value of 0 and s == -1. */
1219*32b31808SJens Wiklander     if (result_is_zero) {
12207901324dSJerome Forissier         X->s = 1;
1221*32b31808SJens Wiklander     } else {
1222817466cbSJens Wiklander         X->s = A->s * B->s;
1223*32b31808SJens Wiklander     }
1224817466cbSJens Wiklander 
1225817466cbSJens Wiklander cleanup:
1226817466cbSJens Wiklander 
1227817466cbSJens Wiklander     mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
1228817466cbSJens Wiklander 
1229*32b31808SJens Wiklander     return ret;
1230817466cbSJens Wiklander }
1231817466cbSJens Wiklander 
1232817466cbSJens Wiklander /*
1233817466cbSJens Wiklander  * Baseline multiplication: X = A * b
1234817466cbSJens Wiklander  */
1235817466cbSJens Wiklander int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
1236817466cbSJens Wiklander {
12373d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
12383d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
1239817466cbSJens Wiklander 
12407901324dSJerome Forissier     size_t n = A->n;
1241*32b31808SJens Wiklander     while (n > 0 && A->p[n - 1] == 0) {
12427901324dSJerome Forissier         --n;
12437901324dSJerome Forissier     }
12447901324dSJerome Forissier 
1245*32b31808SJens Wiklander     /* The general method below doesn't work if b==0. */
1246*32b31808SJens Wiklander     if (b == 0 || n == 0) {
1247*32b31808SJens Wiklander         return mbedtls_mpi_lset(X, 0);
1248*32b31808SJens Wiklander     }
1249*32b31808SJens Wiklander 
1250*32b31808SJens Wiklander     /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
12517901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
12527901324dSJerome Forissier     /* In general, A * b requires 1 limb more than b. If
12537901324dSJerome Forissier      * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
12547901324dSJerome Forissier      * number of limbs as A and the call to grow() is not required since
12557901324dSJerome Forissier      * copy() will take care of the growth if needed. However, experimentally,
12567901324dSJerome Forissier      * making the call to grow() unconditional causes slightly fewer
12577901324dSJerome Forissier      * calls to calloc() in ECP code, presumably because it reuses the
12587901324dSJerome Forissier      * same mpi for a while and this way the mpi is more likely to directly
1259*32b31808SJens Wiklander      * grow to its final size.
1260*32b31808SJens Wiklander      *
1261*32b31808SJens Wiklander      * Note that calculating A*b as 0 + A*b doesn't work as-is because
1262*32b31808SJens Wiklander      * A,X can be the same. */
12637901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
12647901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1265*32b31808SJens Wiklander     mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
12667901324dSJerome Forissier 
12677901324dSJerome Forissier cleanup:
1268*32b31808SJens Wiklander     return ret;
1269817466cbSJens Wiklander }
1270817466cbSJens Wiklander 
1271817466cbSJens Wiklander /*
1272817466cbSJens Wiklander  * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1273817466cbSJens Wiklander  * mbedtls_mpi_uint divisor, d
1274817466cbSJens Wiklander  */
1275817466cbSJens Wiklander static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1276*32b31808SJens Wiklander                                             mbedtls_mpi_uint u0,
1277*32b31808SJens Wiklander                                             mbedtls_mpi_uint d,
1278*32b31808SJens Wiklander                                             mbedtls_mpi_uint *r)
1279817466cbSJens Wiklander {
1280817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL)
1281817466cbSJens Wiklander     mbedtls_t_udbl dividend, quotient;
1282817466cbSJens Wiklander #else
1283817466cbSJens Wiklander     const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1284817466cbSJens Wiklander     const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
1285817466cbSJens Wiklander     mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1286817466cbSJens Wiklander     mbedtls_mpi_uint u0_msw, u0_lsw;
1287817466cbSJens Wiklander     size_t s;
1288817466cbSJens Wiklander #endif
1289817466cbSJens Wiklander 
1290817466cbSJens Wiklander     /*
1291817466cbSJens Wiklander      * Check for overflow
1292817466cbSJens Wiklander      */
1293*32b31808SJens Wiklander     if (0 == d || u1 >= d) {
1294*32b31808SJens Wiklander         if (r != NULL) {
1295*32b31808SJens Wiklander             *r = ~(mbedtls_mpi_uint) 0u;
1296*32b31808SJens Wiklander         }
1297817466cbSJens Wiklander 
1298*32b31808SJens Wiklander         return ~(mbedtls_mpi_uint) 0u;
1299817466cbSJens Wiklander     }
1300817466cbSJens Wiklander 
1301817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL)
1302817466cbSJens Wiklander     dividend  = (mbedtls_t_udbl) u1 << biL;
1303817466cbSJens Wiklander     dividend |= (mbedtls_t_udbl) u0;
1304817466cbSJens Wiklander     quotient = dividend / d;
1305*32b31808SJens Wiklander     if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1306817466cbSJens Wiklander         quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1307*32b31808SJens Wiklander     }
1308817466cbSJens Wiklander 
1309*32b31808SJens Wiklander     if (r != NULL) {
1310817466cbSJens Wiklander         *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1311*32b31808SJens Wiklander     }
1312817466cbSJens Wiklander 
1313817466cbSJens Wiklander     return (mbedtls_mpi_uint) quotient;
1314817466cbSJens Wiklander #else
1315817466cbSJens Wiklander 
1316817466cbSJens Wiklander     /*
1317817466cbSJens Wiklander      * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1318817466cbSJens Wiklander      *   Vol. 2 - Seminumerical Algorithms, Knuth
1319817466cbSJens Wiklander      */
1320817466cbSJens Wiklander 
1321817466cbSJens Wiklander     /*
1322817466cbSJens Wiklander      * Normalize the divisor, d, and dividend, u0, u1
1323817466cbSJens Wiklander      */
1324*32b31808SJens Wiklander     s = mbedtls_mpi_core_clz(d);
1325817466cbSJens Wiklander     d = d << s;
1326817466cbSJens Wiklander 
1327817466cbSJens Wiklander     u1 = u1 << s;
1328817466cbSJens Wiklander     u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
1329817466cbSJens Wiklander     u0 =  u0 << s;
1330817466cbSJens Wiklander 
1331817466cbSJens Wiklander     d1 = d >> biH;
1332817466cbSJens Wiklander     d0 = d & uint_halfword_mask;
1333817466cbSJens Wiklander 
1334817466cbSJens Wiklander     u0_msw = u0 >> biH;
1335817466cbSJens Wiklander     u0_lsw = u0 & uint_halfword_mask;
1336817466cbSJens Wiklander 
1337817466cbSJens Wiklander     /*
1338817466cbSJens Wiklander      * Find the first quotient and remainder
1339817466cbSJens Wiklander      */
1340817466cbSJens Wiklander     q1 = u1 / d1;
1341817466cbSJens Wiklander     r0 = u1 - d1 * q1;
1342817466cbSJens Wiklander 
1343*32b31808SJens Wiklander     while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
1344817466cbSJens Wiklander         q1 -= 1;
1345817466cbSJens Wiklander         r0 += d1;
1346817466cbSJens Wiklander 
1347*32b31808SJens Wiklander         if (r0 >= radix) {
1348*32b31808SJens Wiklander             break;
1349*32b31808SJens Wiklander         }
1350817466cbSJens Wiklander     }
1351817466cbSJens Wiklander 
1352817466cbSJens Wiklander     rAX = (u1 * radix) + (u0_msw - q1 * d);
1353817466cbSJens Wiklander     q0 = rAX / d1;
1354817466cbSJens Wiklander     r0 = rAX - q0 * d1;
1355817466cbSJens Wiklander 
1356*32b31808SJens Wiklander     while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
1357817466cbSJens Wiklander         q0 -= 1;
1358817466cbSJens Wiklander         r0 += d1;
1359817466cbSJens Wiklander 
1360*32b31808SJens Wiklander         if (r0 >= radix) {
1361*32b31808SJens Wiklander             break;
1362*32b31808SJens Wiklander         }
1363817466cbSJens Wiklander     }
1364817466cbSJens Wiklander 
1365*32b31808SJens Wiklander     if (r != NULL) {
1366817466cbSJens Wiklander         *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1367*32b31808SJens Wiklander     }
1368817466cbSJens Wiklander 
1369817466cbSJens Wiklander     quotient = q1 * radix + q0;
1370817466cbSJens Wiklander 
1371817466cbSJens Wiklander     return quotient;
1372817466cbSJens Wiklander #endif
1373817466cbSJens Wiklander }
1374817466cbSJens Wiklander 
1375817466cbSJens Wiklander /*
1376817466cbSJens Wiklander  * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)
1377817466cbSJens Wiklander  */
13783d3b0591SJens Wiklander int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
13793d3b0591SJens Wiklander                         const mbedtls_mpi *B)
1380817466cbSJens Wiklander {
138111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1382817466cbSJens Wiklander     size_t i, n, t, k;
1383817466cbSJens Wiklander     mbedtls_mpi X, Y, Z, T1, T2;
138411fa71b9SJerome Forissier     mbedtls_mpi_uint TP2[3];
13853d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
13863d3b0591SJens Wiklander     MPI_VALIDATE_RET(B != NULL);
1387817466cbSJens Wiklander 
1388*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1389*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1390*32b31808SJens Wiklander     }
1391817466cbSJens Wiklander 
139298bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&X); mbedtls_mpi_init_mempool(&Y);
139398bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&Z); mbedtls_mpi_init_mempool(&T1);
139411fa71b9SJerome Forissier     /*
139511fa71b9SJerome Forissier      * Avoid dynamic memory allocations for constant-size T2.
139611fa71b9SJerome Forissier      *
139711fa71b9SJerome Forissier      * T2 is used for comparison only and the 3 limbs are assigned explicitly,
139811fa71b9SJerome Forissier      * so nobody increase the size of the MPI and we're safe to use an on-stack
139911fa71b9SJerome Forissier      * buffer.
140011fa71b9SJerome Forissier      */
140111fa71b9SJerome Forissier     T2.s = 1;
140211fa71b9SJerome Forissier     T2.n = sizeof(TP2) / sizeof(*TP2);
140311fa71b9SJerome Forissier     T2.p = TP2;
1404817466cbSJens Wiklander 
1405*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1406*32b31808SJens Wiklander         if (Q != NULL) {
1407*32b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1408*32b31808SJens Wiklander         }
1409*32b31808SJens Wiklander         if (R != NULL) {
1410*32b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1411*32b31808SJens Wiklander         }
1412*32b31808SJens Wiklander         return 0;
1413817466cbSJens Wiklander     }
1414817466cbSJens Wiklander 
1415817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1416817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
1417817466cbSJens Wiklander     X.s = Y.s = 1;
1418817466cbSJens Wiklander 
1419817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1420817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z,  0));
14217901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
1422817466cbSJens Wiklander 
1423817466cbSJens Wiklander     k = mbedtls_mpi_bitlen(&Y) % biL;
1424*32b31808SJens Wiklander     if (k < biL - 1) {
1425817466cbSJens Wiklander         k = biL - 1 - k;
1426817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1427817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1428*32b31808SJens Wiklander     } else {
1429*32b31808SJens Wiklander         k = 0;
1430817466cbSJens Wiklander     }
1431817466cbSJens Wiklander 
1432817466cbSJens Wiklander     n = X.n - 1;
1433817466cbSJens Wiklander     t = Y.n - 1;
1434817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
1435817466cbSJens Wiklander 
1436*32b31808SJens Wiklander     while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
1437817466cbSJens Wiklander         Z.p[n - t]++;
1438817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
1439817466cbSJens Wiklander     }
1440817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
1441817466cbSJens Wiklander 
1442*32b31808SJens Wiklander     for (i = n; i > t; i--) {
1443*32b31808SJens Wiklander         if (X.p[i] >= Y.p[t]) {
1444*32b31808SJens Wiklander             Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1445*32b31808SJens Wiklander         } else {
1446817466cbSJens Wiklander             Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1447817466cbSJens Wiklander                                                  Y.p[t], NULL);
1448817466cbSJens Wiklander         }
1449817466cbSJens Wiklander 
145011fa71b9SJerome Forissier         T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
145111fa71b9SJerome Forissier         T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
145211fa71b9SJerome Forissier         T2.p[2] = X.p[i];
145311fa71b9SJerome Forissier 
1454817466cbSJens Wiklander         Z.p[i - t - 1]++;
1455*32b31808SJens Wiklander         do {
1456817466cbSJens Wiklander             Z.p[i - t - 1]--;
1457817466cbSJens Wiklander 
1458817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1459817466cbSJens Wiklander             T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1460817466cbSJens Wiklander             T1.p[1] = Y.p[t];
1461817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1462*32b31808SJens Wiklander         } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
1463817466cbSJens Wiklander 
1464817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1465817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1,  biL * (i - t - 1)));
1466817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
1467817466cbSJens Wiklander 
1468*32b31808SJens Wiklander         if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1469817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1470817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1471817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
1472817466cbSJens Wiklander             Z.p[i - t - 1]--;
1473817466cbSJens Wiklander         }
1474817466cbSJens Wiklander     }
1475817466cbSJens Wiklander 
1476*32b31808SJens Wiklander     if (Q != NULL) {
1477817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
1478817466cbSJens Wiklander         Q->s = A->s * B->s;
1479817466cbSJens Wiklander     }
1480817466cbSJens Wiklander 
1481*32b31808SJens Wiklander     if (R != NULL) {
1482817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
1483817466cbSJens Wiklander         X.s = A->s;
1484817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
1485817466cbSJens Wiklander 
1486*32b31808SJens Wiklander         if (mbedtls_mpi_cmp_int(R, 0) == 0) {
1487817466cbSJens Wiklander             R->s = 1;
1488817466cbSJens Wiklander         }
1489*32b31808SJens Wiklander     }
1490817466cbSJens Wiklander 
1491817466cbSJens Wiklander cleanup:
1492817466cbSJens Wiklander 
1493817466cbSJens Wiklander     mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
149411fa71b9SJerome Forissier     mbedtls_mpi_free(&T1);
149511fa71b9SJerome Forissier     mbedtls_platform_zeroize(TP2, sizeof(TP2));
1496817466cbSJens Wiklander 
1497*32b31808SJens Wiklander     return ret;
1498817466cbSJens Wiklander }
1499817466cbSJens Wiklander 
1500817466cbSJens Wiklander /*
1501817466cbSJens Wiklander  * Division by int: A = Q * b + R
1502817466cbSJens Wiklander  */
15033d3b0591SJens Wiklander int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
15043d3b0591SJens Wiklander                         const mbedtls_mpi *A,
15053d3b0591SJens Wiklander                         mbedtls_mpi_sint b)
1506817466cbSJens Wiklander {
1507039e02dfSJerome Forissier     mbedtls_mpi B;
1508817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
15093d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
1510817466cbSJens Wiklander 
1511*32b31808SJens Wiklander     p[0] = mpi_sint_abs(b);
1512039e02dfSJerome Forissier     B.s = (b < 0) ? -1 : 1;
1513039e02dfSJerome Forissier     B.n = 1;
1514039e02dfSJerome Forissier     B.p = p;
1515817466cbSJens Wiklander 
1516*32b31808SJens Wiklander     return mbedtls_mpi_div_mpi(Q, R, A, &B);
1517817466cbSJens Wiklander }
1518817466cbSJens Wiklander 
1519817466cbSJens Wiklander /*
1520817466cbSJens Wiklander  * Modulo: R = A mod B
1521817466cbSJens Wiklander  */
1522817466cbSJens Wiklander int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
1523817466cbSJens Wiklander {
152411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
15253d3b0591SJens Wiklander     MPI_VALIDATE_RET(R != NULL);
15263d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
15273d3b0591SJens Wiklander     MPI_VALIDATE_RET(B != NULL);
1528817466cbSJens Wiklander 
1529*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1530*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1531*32b31808SJens Wiklander     }
1532817466cbSJens Wiklander 
1533817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
1534817466cbSJens Wiklander 
1535*32b31808SJens Wiklander     while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1536817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1537*32b31808SJens Wiklander     }
1538817466cbSJens Wiklander 
1539*32b31808SJens Wiklander     while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1540817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1541*32b31808SJens Wiklander     }
1542817466cbSJens Wiklander 
1543817466cbSJens Wiklander cleanup:
1544817466cbSJens Wiklander 
1545*32b31808SJens Wiklander     return ret;
1546817466cbSJens Wiklander }
1547817466cbSJens Wiklander 
1548817466cbSJens Wiklander /*
1549817466cbSJens Wiklander  * Modulo: r = A mod b
1550817466cbSJens Wiklander  */
1551817466cbSJens Wiklander int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
1552817466cbSJens Wiklander {
1553817466cbSJens Wiklander     size_t i;
1554817466cbSJens Wiklander     mbedtls_mpi_uint x, y, z;
15553d3b0591SJens Wiklander     MPI_VALIDATE_RET(r != NULL);
15563d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
1557817466cbSJens Wiklander 
1558*32b31808SJens Wiklander     if (b == 0) {
1559*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1560*32b31808SJens Wiklander     }
1561817466cbSJens Wiklander 
1562*32b31808SJens Wiklander     if (b < 0) {
1563*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1564*32b31808SJens Wiklander     }
1565817466cbSJens Wiklander 
1566817466cbSJens Wiklander     /*
1567817466cbSJens Wiklander      * handle trivial cases
1568817466cbSJens Wiklander      */
1569*32b31808SJens Wiklander     if (b == 1 || A->n == 0) {
1570817466cbSJens Wiklander         *r = 0;
1571*32b31808SJens Wiklander         return 0;
1572817466cbSJens Wiklander     }
1573817466cbSJens Wiklander 
1574*32b31808SJens Wiklander     if (b == 2) {
1575817466cbSJens Wiklander         *r = A->p[0] & 1;
1576*32b31808SJens Wiklander         return 0;
1577817466cbSJens Wiklander     }
1578817466cbSJens Wiklander 
1579817466cbSJens Wiklander     /*
1580817466cbSJens Wiklander      * general case
1581817466cbSJens Wiklander      */
1582*32b31808SJens Wiklander     for (i = A->n, y = 0; i > 0; i--) {
1583817466cbSJens Wiklander         x  = A->p[i - 1];
1584817466cbSJens Wiklander         y  = (y << biH) | (x >> biH);
1585817466cbSJens Wiklander         z  = y / b;
1586817466cbSJens Wiklander         y -= z * b;
1587817466cbSJens Wiklander 
1588817466cbSJens Wiklander         x <<= biH;
1589817466cbSJens Wiklander         y  = (y << biH) | (x >> biH);
1590817466cbSJens Wiklander         z  = y / b;
1591817466cbSJens Wiklander         y -= z * b;
1592817466cbSJens Wiklander     }
1593817466cbSJens Wiklander 
1594817466cbSJens Wiklander     /*
1595817466cbSJens Wiklander      * If A is negative, then the current y represents a negative value.
1596817466cbSJens Wiklander      * Flipping it to the positive side.
1597817466cbSJens Wiklander      */
1598*32b31808SJens Wiklander     if (A->s < 0 && y != 0) {
1599817466cbSJens Wiklander         y = b - y;
1600*32b31808SJens Wiklander     }
1601817466cbSJens Wiklander 
1602817466cbSJens Wiklander     *r = y;
1603817466cbSJens Wiklander 
1604*32b31808SJens Wiklander     return 0;
1605817466cbSJens Wiklander }
1606817466cbSJens Wiklander 
16077901324dSJerome Forissier static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
1608817466cbSJens Wiklander {
1609*32b31808SJens Wiklander     *mm = mbedtls_mpi_core_montmul_init(N->p);
1610817466cbSJens Wiklander }
1611817466cbSJens Wiklander 
16127901324dSJerome Forissier void mbedtls_mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
16137901324dSJerome Forissier {
16147901324dSJerome Forissier 	mpi_montg_init( mm, N );
16157901324dSJerome Forissier }
16167901324dSJerome Forissier 
16177901324dSJerome Forissier /** Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
16187901324dSJerome Forissier  *
16197901324dSJerome Forissier  * \param[in,out]   A   One of the numbers to multiply.
16207901324dSJerome Forissier  *                      It must have at least as many limbs as N
16217901324dSJerome Forissier  *                      (A->n >= N->n), and any limbs beyond n are ignored.
16227901324dSJerome Forissier  *                      On successful completion, A contains the result of
16237901324dSJerome Forissier  *                      the multiplication A * B * R^-1 mod N where
16247901324dSJerome Forissier  *                      R = (2^ciL)^n.
16257901324dSJerome Forissier  * \param[in]       B   One of the numbers to multiply.
16267901324dSJerome Forissier  *                      It must be nonzero and must not have more limbs than N
16277901324dSJerome Forissier  *                      (B->n <= N->n).
1628*32b31808SJens Wiklander  * \param[in]       N   The modulus. \p N must be odd.
16297901324dSJerome Forissier  * \param           mm  The value calculated by `mpi_montg_init(&mm, N)`.
16307901324dSJerome Forissier  *                      This is -N^-1 mod 2^ciL.
16317901324dSJerome Forissier  * \param[in,out]   T   A bignum for temporary storage.
1632*32b31808SJens Wiklander  *                      It must be at least twice the limb size of N plus 1
1633*32b31808SJens Wiklander  *                      (T->n >= 2 * N->n + 1).
16347901324dSJerome Forissier  *                      Its initial content is unused and
16357901324dSJerome Forissier  *                      its final content is indeterminate.
1636*32b31808SJens Wiklander  *                      It does not get reallocated.
1637817466cbSJens Wiklander  */
1638*32b31808SJens Wiklander static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1639*32b31808SJens Wiklander                         const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1640*32b31808SJens Wiklander                         mbedtls_mpi *T)
1641817466cbSJens Wiklander {
1642*32b31808SJens Wiklander     mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
1643817466cbSJens Wiklander }
1644817466cbSJens Wiklander 
1645*32b31808SJens Wiklander void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1646*32b31808SJens Wiklander                          const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1647*32b31808SJens Wiklander                          mbedtls_mpi *T )
16487901324dSJerome Forissier {
16497901324dSJerome Forissier     mpi_montmul( A, B, N, mm, T);
1650817466cbSJens Wiklander }
1651817466cbSJens Wiklander 
1652817466cbSJens Wiklander /*
1653817466cbSJens Wiklander  * Montgomery reduction: A = A * R^-1 mod N
16547901324dSJerome Forissier  *
16557901324dSJerome Forissier  * See mpi_montmul() regarding constraints and guarantees on the parameters.
1656817466cbSJens Wiklander  */
16577901324dSJerome Forissier static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1658*32b31808SJens Wiklander                         mbedtls_mpi_uint mm, mbedtls_mpi *T)
1659817466cbSJens Wiklander {
1660817466cbSJens Wiklander     mbedtls_mpi_uint z = 1;
1661817466cbSJens Wiklander     mbedtls_mpi U;
1662817466cbSJens Wiklander 
1663817466cbSJens Wiklander     U.n = U.s = (int) z;
1664817466cbSJens Wiklander     U.p = &z;
1665817466cbSJens Wiklander 
16667901324dSJerome Forissier     mpi_montmul(A, &U, N, mm, T);
16677901324dSJerome Forissier }
16687901324dSJerome Forissier 
16697901324dSJerome Forissier void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1670*32b31808SJens Wiklander                          mbedtls_mpi_uint mm, mbedtls_mpi *T)
16717901324dSJerome Forissier {
16727901324dSJerome Forissier     mpi_montred(A, N, mm, T);
16737901324dSJerome Forissier }
16747901324dSJerome Forissier 
16757901324dSJerome Forissier /**
16767901324dSJerome Forissier  * Select an MPI from a table without leaking the index.
16777901324dSJerome Forissier  *
16787901324dSJerome Forissier  * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
16797901324dSJerome Forissier  * reads the entire table in order to avoid leaking the value of idx to an
16807901324dSJerome Forissier  * attacker able to observe memory access patterns.
16817901324dSJerome Forissier  *
16827901324dSJerome Forissier  * \param[out] R        Where to write the selected MPI.
16837901324dSJerome Forissier  * \param[in] T         The table to read from.
16847901324dSJerome Forissier  * \param[in] T_size    The number of elements in the table.
16857901324dSJerome Forissier  * \param[in] idx       The index of the element to select;
16867901324dSJerome Forissier  *                      this must satisfy 0 <= idx < T_size.
16877901324dSJerome Forissier  *
16887901324dSJerome Forissier  * \return \c 0 on success, or a negative error code.
16897901324dSJerome Forissier  */
16907901324dSJerome Forissier static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
16917901324dSJerome Forissier {
16927901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
16937901324dSJerome Forissier 
1694*32b31808SJens Wiklander     for (size_t i = 0; i < T_size; i++) {
16957901324dSJerome Forissier         MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
1696*32b31808SJens Wiklander                                                      (unsigned char) mbedtls_ct_size_bool_eq(i,
1697*32b31808SJens Wiklander                                                                                              idx)));
16987901324dSJerome Forissier     }
16997901324dSJerome Forissier 
17007901324dSJerome Forissier cleanup:
1701*32b31808SJens Wiklander     return ret;
1702817466cbSJens Wiklander }
1703817466cbSJens Wiklander 
1704817466cbSJens Wiklander /*
1705817466cbSJens Wiklander  * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
1706817466cbSJens Wiklander  */
17073d3b0591SJens Wiklander int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
17083d3b0591SJens Wiklander                         const mbedtls_mpi *E, const mbedtls_mpi *N,
1709039e02dfSJerome Forissier                         mbedtls_mpi *prec_RR)
1710817466cbSJens Wiklander {
171111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1712*32b31808SJens Wiklander     size_t window_bitsize;
1713817466cbSJens Wiklander     size_t i, j, nblimbs;
1714817466cbSJens Wiklander     size_t bufsize, nbits;
1715*32b31808SJens Wiklander     size_t exponent_bits_in_window = 0;
1716817466cbSJens Wiklander     mbedtls_mpi_uint ei, mm, state;
17177901324dSJerome Forissier     mbedtls_mpi RR, T, WW, Apos;
1718*32b31808SJens Wiklander     mbedtls_mpi *W;
171941e5aa8fSJens Wiklander     const size_t array_size_W = 2 << MBEDTLS_MPI_WINDOW_SIZE;
1720817466cbSJens Wiklander     int neg;
1721817466cbSJens Wiklander 
17223d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
17233d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
17243d3b0591SJens Wiklander     MPI_VALIDATE_RET(E != NULL);
17253d3b0591SJens Wiklander     MPI_VALIDATE_RET(N != NULL);
17263d3b0591SJens Wiklander 
1727*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1728*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1729*32b31808SJens Wiklander     }
1730817466cbSJens Wiklander 
1731*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1732*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1733*32b31808SJens Wiklander     }
1734817466cbSJens Wiklander 
17357901324dSJerome Forissier     if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1736*32b31808SJens Wiklander         mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1737*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1738*32b31808SJens Wiklander     }
17397901324dSJerome Forissier 
1740817466cbSJens Wiklander     /*
1741817466cbSJens Wiklander      * Init temps and window size
1742817466cbSJens Wiklander      */
17437901324dSJerome Forissier     mpi_montg_init(&mm, N);
17447901324dSJerome Forissier     mbedtls_mpi_init_mempool(&RR); mbedtls_mpi_init(&T);
174598bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&Apos);
17467901324dSJerome Forissier     mbedtls_mpi_init_mempool(&WW);
1747817466cbSJens Wiklander 
1748817466cbSJens Wiklander     i = mbedtls_mpi_bitlen(E);
1749817466cbSJens Wiklander 
1750*32b31808SJens Wiklander     window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1751817466cbSJens Wiklander                      (i >  79) ? 4 : (i >  23) ? 3 : 1;
1752817466cbSJens Wiklander 
17535b25c76aSJerome Forissier #if (MBEDTLS_MPI_WINDOW_SIZE < 6)
1754*32b31808SJens Wiklander     if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
1755*32b31808SJens Wiklander         window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
1756*32b31808SJens Wiklander     }
17575b25c76aSJerome Forissier #endif
1758817466cbSJens Wiklander 
1759*32b31808SJens Wiklander     const size_t w_table_used_size = (size_t) 1 << window_bitsize;
1760817466cbSJens Wiklander 
1761ad443200SJens Wiklander     W = mempool_alloc(mbedtls_mpi_mempool,
1762ad443200SJens Wiklander                       sizeof( mbedtls_mpi ) * array_size_W);
1763ad443200SJens Wiklander     if (W == NULL) {
1764ad443200SJens Wiklander         ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
1765ad443200SJens Wiklander         goto cleanup;
1766ad443200SJens Wiklander     }
1767ad443200SJens Wiklander     for (i = 0; i < array_size_W; i++)
1768ad443200SJens Wiklander         mbedtls_mpi_init_mempool(W + i);
1769*32b31808SJens Wiklander     /*
1770*32b31808SJens Wiklander      * This function is not constant-trace: its memory accesses depend on the
1771*32b31808SJens Wiklander      * exponent value. To defend against timing attacks, callers (such as RSA
1772*32b31808SJens Wiklander      * and DHM) should use exponent blinding. However this is not enough if the
1773*32b31808SJens Wiklander      * adversary can find the exponent in a single trace, so this function
1774*32b31808SJens Wiklander      * takes extra precautions against adversaries who can observe memory
1775*32b31808SJens Wiklander      * access patterns.
1776*32b31808SJens Wiklander      *
1777*32b31808SJens Wiklander      * This function performs a series of multiplications by table elements and
1778*32b31808SJens Wiklander      * squarings, and we want the prevent the adversary from finding out which
1779*32b31808SJens Wiklander      * table element was used, and from distinguishing between multiplications
1780*32b31808SJens Wiklander      * and squarings. Firstly, when multiplying by an element of the window
1781*32b31808SJens Wiklander      * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
1782*32b31808SJens Wiklander      * squarings as having a different memory access patterns from other
1783*32b31808SJens Wiklander      * multiplications. So secondly, we put the accumulator X in the table as
1784*32b31808SJens Wiklander      * well, and also do a constant-trace table lookup to multiply by X.
1785*32b31808SJens Wiklander      *
1786*32b31808SJens Wiklander      * This way, all multiplications take the form of a lookup-and-multiply.
1787*32b31808SJens Wiklander      * The number of lookup-and-multiply operations inside each iteration of
1788*32b31808SJens Wiklander      * the main loop still depends on the bits of the exponent, but since the
1789*32b31808SJens Wiklander      * other operations in the loop don't have an easily recognizable memory
1790*32b31808SJens Wiklander      * trace, an adversary is unlikely to be able to observe the exact
1791*32b31808SJens Wiklander      * patterns.
1792*32b31808SJens Wiklander      *
1793*32b31808SJens Wiklander      * An adversary may still be able to recover the exponent if they can
1794*32b31808SJens Wiklander      * observe both memory accesses and branches. However, branch prediction
1795*32b31808SJens Wiklander      * exploitation typically requires many traces of execution over the same
1796*32b31808SJens Wiklander      * data, which is defeated by randomized blinding.
1797*32b31808SJens Wiklander      *
1798*32b31808SJens Wiklander      * To achieve this, we make a copy of X and we use the table entry in each
1799*32b31808SJens Wiklander      * calculation from this point on.
1800*32b31808SJens Wiklander      */
1801*32b31808SJens Wiklander     const size_t x_index = 0;
1802*32b31808SJens Wiklander     mbedtls_mpi_copy(&W[x_index], X);
1803*32b31808SJens Wiklander 
1804*32b31808SJens Wiklander     j = N->n + 1;
1805*32b31808SJens Wiklander     /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
1806*32b31808SJens Wiklander      * and mpi_montred() calls later. Here we ensure that W[1] and X are
1807*32b31808SJens Wiklander      * large enough, and later we'll grow other W[i] to the same length.
1808*32b31808SJens Wiklander      * They must not be shrunk midway through this function!
1809*32b31808SJens Wiklander      */
1810*32b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1811*32b31808SJens Wiklander 
1812*32b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
1813*32b31808SJens Wiklander 
1814*32b31808SJens Wiklander     /*
1815*32b31808SJens Wiklander      * Compensate for negative A (and correct at the end)
1816*32b31808SJens Wiklander      */
1817*32b31808SJens Wiklander     neg = (A->s == -1);
1818*32b31808SJens Wiklander     if (neg) {
1819*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
1820*32b31808SJens Wiklander         Apos.s = 1;
1821*32b31808SJens Wiklander         A = &Apos;
1822*32b31808SJens Wiklander     }
1823*32b31808SJens Wiklander 
1824*32b31808SJens Wiklander     /*
1825*32b31808SJens Wiklander      * If 1st call, pre-compute R^2 mod N
1826*32b31808SJens Wiklander      */
1827*32b31808SJens Wiklander     if (prec_RR == NULL || prec_RR->p == NULL) {
1828*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
1829*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
1830*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
1831*32b31808SJens Wiklander 
1832*32b31808SJens Wiklander         if (prec_RR != NULL) {
1833*32b31808SJens Wiklander             memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
1834*32b31808SJens Wiklander         }
1835*32b31808SJens Wiklander     } else {
1836*32b31808SJens Wiklander         memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
1837*32b31808SJens Wiklander     }
1838*32b31808SJens Wiklander 
1839ad443200SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1],  j));
1840ad443200SJens Wiklander 
1841817466cbSJens Wiklander     /*
1842817466cbSJens Wiklander      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1843817466cbSJens Wiklander      */
1844*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1845817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
18467901324dSJerome Forissier         /* This should be a no-op because W[1] is already that large before
18477901324dSJerome Forissier          * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
18487901324dSJerome Forissier          * in mpi_montmul() below, so let's make sure. */
18497901324dSJerome Forissier         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
1850*32b31808SJens Wiklander     } else {
1851817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
1852*32b31808SJens Wiklander     }
1853817466cbSJens Wiklander 
18547901324dSJerome Forissier     /* Note that this is safe because W[1] always has at least N->n limbs
18557901324dSJerome Forissier      * (it grew above and was preserved by mbedtls_mpi_copy()). */
18567901324dSJerome Forissier     mpi_montmul(&W[1], &RR, N, mm, &T);
1857817466cbSJens Wiklander 
1858817466cbSJens Wiklander     /*
1859*32b31808SJens Wiklander      * W[x_index] = R^2 * R^-1 mod N = R mod N
1860817466cbSJens Wiklander      */
1861*32b31808SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1862*32b31808SJens Wiklander     mpi_montred(&W[x_index], N, mm, &T);
1863817466cbSJens Wiklander 
1864*32b31808SJens Wiklander 
1865*32b31808SJens Wiklander     if (window_bitsize > 1) {
1866817466cbSJens Wiklander         /*
1867*32b31808SJens Wiklander          * W[i] = W[1] ^ i
1868*32b31808SJens Wiklander          *
1869*32b31808SJens Wiklander          * The first bit of the sliding window is always 1 and therefore we
1870*32b31808SJens Wiklander          * only need to store the second half of the table.
1871*32b31808SJens Wiklander          *
1872*32b31808SJens Wiklander          * (There are two special elements in the table: W[0] for the
1873*32b31808SJens Wiklander          * accumulator/result and W[1] for A in Montgomery form. Both of these
1874*32b31808SJens Wiklander          * are already set at this point.)
1875817466cbSJens Wiklander          */
1876*32b31808SJens Wiklander         j = w_table_used_size / 2;
1877817466cbSJens Wiklander 
1878817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1879817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
1880817466cbSJens Wiklander 
1881*32b31808SJens Wiklander         for (i = 0; i < window_bitsize - 1; i++) {
18827901324dSJerome Forissier             mpi_montmul(&W[j], &W[j], N, mm, &T);
1883*32b31808SJens Wiklander         }
1884817466cbSJens Wiklander 
1885817466cbSJens Wiklander         /*
1886817466cbSJens Wiklander          * W[i] = W[i - 1] * W[1]
1887817466cbSJens Wiklander          */
1888*32b31808SJens Wiklander         for (i = j + 1; i < w_table_used_size; i++) {
1889817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1890817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
1891817466cbSJens Wiklander 
18927901324dSJerome Forissier             mpi_montmul(&W[i], &W[1], N, mm, &T);
1893817466cbSJens Wiklander         }
1894817466cbSJens Wiklander     }
1895817466cbSJens Wiklander 
1896817466cbSJens Wiklander     nblimbs = E->n;
1897817466cbSJens Wiklander     bufsize = 0;
1898817466cbSJens Wiklander     nbits   = 0;
1899817466cbSJens Wiklander     state   = 0;
1900817466cbSJens Wiklander 
1901*32b31808SJens Wiklander     while (1) {
1902*32b31808SJens Wiklander         if (bufsize == 0) {
1903*32b31808SJens Wiklander             if (nblimbs == 0) {
1904817466cbSJens Wiklander                 break;
1905*32b31808SJens Wiklander             }
1906817466cbSJens Wiklander 
1907817466cbSJens Wiklander             nblimbs--;
1908817466cbSJens Wiklander 
1909817466cbSJens Wiklander             bufsize = sizeof(mbedtls_mpi_uint) << 3;
1910817466cbSJens Wiklander         }
1911817466cbSJens Wiklander 
1912817466cbSJens Wiklander         bufsize--;
1913817466cbSJens Wiklander 
1914817466cbSJens Wiklander         ei = (E->p[nblimbs] >> bufsize) & 1;
1915817466cbSJens Wiklander 
1916817466cbSJens Wiklander         /*
1917817466cbSJens Wiklander          * skip leading 0s
1918817466cbSJens Wiklander          */
1919*32b31808SJens Wiklander         if (ei == 0 && state == 0) {
1920817466cbSJens Wiklander             continue;
1921*32b31808SJens Wiklander         }
1922817466cbSJens Wiklander 
1923*32b31808SJens Wiklander         if (ei == 0 && state == 1) {
1924817466cbSJens Wiklander             /*
1925*32b31808SJens Wiklander              * out of window, square W[x_index]
1926817466cbSJens Wiklander              */
1927*32b31808SJens Wiklander             MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1928*32b31808SJens Wiklander             mpi_montmul(&W[x_index], &WW, N, mm, &T);
1929817466cbSJens Wiklander             continue;
1930817466cbSJens Wiklander         }
1931817466cbSJens Wiklander 
1932817466cbSJens Wiklander         /*
1933817466cbSJens Wiklander          * add ei to current window
1934817466cbSJens Wiklander          */
1935817466cbSJens Wiklander         state = 2;
1936817466cbSJens Wiklander 
1937817466cbSJens Wiklander         nbits++;
1938*32b31808SJens Wiklander         exponent_bits_in_window |= (ei << (window_bitsize - nbits));
1939817466cbSJens Wiklander 
1940*32b31808SJens Wiklander         if (nbits == window_bitsize) {
1941817466cbSJens Wiklander             /*
1942*32b31808SJens Wiklander              * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
1943817466cbSJens Wiklander              */
1944*32b31808SJens Wiklander             for (i = 0; i < window_bitsize; i++) {
1945*32b31808SJens Wiklander                 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1946*32b31808SJens Wiklander                                            x_index));
1947*32b31808SJens Wiklander                 mpi_montmul(&W[x_index], &WW, N, mm, &T);
1948*32b31808SJens Wiklander             }
1949817466cbSJens Wiklander 
1950817466cbSJens Wiklander             /*
1951*32b31808SJens Wiklander              * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
1952817466cbSJens Wiklander              */
1953*32b31808SJens Wiklander             MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1954*32b31808SJens Wiklander                                        exponent_bits_in_window));
1955*32b31808SJens Wiklander             mpi_montmul(&W[x_index], &WW, N, mm, &T);
1956817466cbSJens Wiklander 
1957817466cbSJens Wiklander             state--;
1958817466cbSJens Wiklander             nbits = 0;
1959*32b31808SJens Wiklander             exponent_bits_in_window = 0;
1960817466cbSJens Wiklander         }
1961817466cbSJens Wiklander     }
1962817466cbSJens Wiklander 
1963817466cbSJens Wiklander     /*
1964817466cbSJens Wiklander      * process the remaining bits
1965817466cbSJens Wiklander      */
1966*32b31808SJens Wiklander     for (i = 0; i < nbits; i++) {
1967*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1968*32b31808SJens Wiklander         mpi_montmul(&W[x_index], &WW, N, mm, &T);
1969817466cbSJens Wiklander 
1970*32b31808SJens Wiklander         exponent_bits_in_window <<= 1;
1971817466cbSJens Wiklander 
1972*32b31808SJens Wiklander         if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
1973*32b31808SJens Wiklander             MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
1974*32b31808SJens Wiklander             mpi_montmul(&W[x_index], &WW, N, mm, &T);
1975*32b31808SJens Wiklander         }
1976817466cbSJens Wiklander     }
1977817466cbSJens Wiklander 
1978817466cbSJens Wiklander     /*
1979*32b31808SJens Wiklander      * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
1980817466cbSJens Wiklander      */
1981*32b31808SJens Wiklander     mpi_montred(&W[x_index], N, mm, &T);
1982817466cbSJens Wiklander 
1983*32b31808SJens Wiklander     if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
1984*32b31808SJens Wiklander         W[x_index].s = -1;
1985*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
1986817466cbSJens Wiklander     }
1987817466cbSJens Wiklander 
1988*32b31808SJens Wiklander     /*
1989*32b31808SJens Wiklander      * Load the result in the output variable.
1990*32b31808SJens Wiklander      */
1991*32b31808SJens Wiklander     mbedtls_mpi_copy(X, &W[x_index]);
1992*32b31808SJens Wiklander 
1993817466cbSJens Wiklander cleanup:
1994817466cbSJens Wiklander 
1995ad443200SJens Wiklander     if (W)
199641e5aa8fSJens Wiklander         for (i = 0; i < array_size_W; i++)
1997b99a4a18SJens Wiklander             mbedtls_mpi_free(W + i);
199841e5aa8fSJens Wiklander     mempool_free(mbedtls_mpi_mempool , W);
1999817466cbSJens Wiklander 
2000*32b31808SJens Wiklander     mbedtls_mpi_free(&T);
2001*32b31808SJens Wiklander     mbedtls_mpi_free(&Apos);
20027901324dSJerome Forissier     mbedtls_mpi_free(&WW);
2003817466cbSJens Wiklander 
2004*32b31808SJens Wiklander     if (prec_RR == NULL || prec_RR->p == NULL) {
2005817466cbSJens Wiklander         mbedtls_mpi_free(&RR);
2006*32b31808SJens Wiklander     }
2007817466cbSJens Wiklander 
2008*32b31808SJens Wiklander     return ret;
2009817466cbSJens Wiklander }
2010817466cbSJens Wiklander 
2011817466cbSJens Wiklander /*
2012817466cbSJens Wiklander  * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
2013817466cbSJens Wiklander  */
2014817466cbSJens Wiklander int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
2015817466cbSJens Wiklander {
201611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2017817466cbSJens Wiklander     size_t lz, lzt;
201811fa71b9SJerome Forissier     mbedtls_mpi TA, TB;
2019817466cbSJens Wiklander 
20203d3b0591SJens Wiklander     MPI_VALIDATE_RET(G != NULL);
20213d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
20223d3b0591SJens Wiklander     MPI_VALIDATE_RET(B != NULL);
20233d3b0591SJens Wiklander 
202411fa71b9SJerome Forissier     mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
2025817466cbSJens Wiklander 
2026817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2027817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
2028817466cbSJens Wiklander 
2029817466cbSJens Wiklander     lz = mbedtls_mpi_lsb(&TA);
2030817466cbSJens Wiklander     lzt = mbedtls_mpi_lsb(&TB);
2031817466cbSJens Wiklander 
20327901324dSJerome Forissier     /* The loop below gives the correct result when A==0 but not when B==0.
20337901324dSJerome Forissier      * So have a special case for B==0. Leverage the fact that we just
20347901324dSJerome Forissier      * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
20357901324dSJerome Forissier      * slightly more efficient than cmp_int(). */
2036*32b31808SJens Wiklander     if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
20377901324dSJerome Forissier         ret = mbedtls_mpi_copy(G, A);
20387901324dSJerome Forissier         goto cleanup;
20397901324dSJerome Forissier     }
20407901324dSJerome Forissier 
2041*32b31808SJens Wiklander     if (lzt < lz) {
2042817466cbSJens Wiklander         lz = lzt;
2043*32b31808SJens Wiklander     }
2044817466cbSJens Wiklander 
2045817466cbSJens Wiklander     TA.s = TB.s = 1;
2046817466cbSJens Wiklander 
20477901324dSJerome Forissier     /* We mostly follow the procedure described in HAC 14.54, but with some
20487901324dSJerome Forissier      * minor differences:
20497901324dSJerome Forissier      * - Sequences of multiplications or divisions by 2 are grouped into a
20507901324dSJerome Forissier      *   single shift operation.
20517901324dSJerome Forissier      * - The procedure in HAC assumes that 0 < TB <= TA.
20527901324dSJerome Forissier      *     - The condition TB <= TA is not actually necessary for correctness.
20537901324dSJerome Forissier      *       TA and TB have symmetric roles except for the loop termination
20547901324dSJerome Forissier      *       condition, and the shifts at the beginning of the loop body
20557901324dSJerome Forissier      *       remove any significance from the ordering of TA vs TB before
20567901324dSJerome Forissier      *       the shifts.
20577901324dSJerome Forissier      *     - If TA = 0, the loop goes through 0 iterations and the result is
20587901324dSJerome Forissier      *       correctly TB.
20597901324dSJerome Forissier      *     - The case TB = 0 was short-circuited above.
20607901324dSJerome Forissier      *
20617901324dSJerome Forissier      * For the correctness proof below, decompose the original values of
20627901324dSJerome Forissier      * A and B as
20637901324dSJerome Forissier      *   A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
20647901324dSJerome Forissier      *   B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
20657901324dSJerome Forissier      * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
20667901324dSJerome Forissier      * and gcd(A',B') is odd or 0.
20677901324dSJerome Forissier      *
20687901324dSJerome Forissier      * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
20697901324dSJerome Forissier      * The code maintains the following invariant:
20707901324dSJerome Forissier      *     gcd(A,B) = 2^k * gcd(TA,TB) for some k   (I)
20717901324dSJerome Forissier      */
20727901324dSJerome Forissier 
20737901324dSJerome Forissier     /* Proof that the loop terminates:
20747901324dSJerome Forissier      * At each iteration, either the right-shift by 1 is made on a nonzero
20757901324dSJerome Forissier      * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
20767901324dSJerome Forissier      * by at least 1, or the right-shift by 1 is made on zero and then
20777901324dSJerome Forissier      * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
20787901324dSJerome Forissier      * since in that case TB is calculated from TB-TA with the condition TB>TA).
20797901324dSJerome Forissier      */
2080*32b31808SJens Wiklander     while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
20817901324dSJerome Forissier         /* Divisions by 2 preserve the invariant (I). */
2082817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2083817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
2084817466cbSJens Wiklander 
20857901324dSJerome Forissier         /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
20867901324dSJerome Forissier          * TA-TB is even so the division by 2 has an integer result.
20877901324dSJerome Forissier          * Invariant (I) is preserved since any odd divisor of both TA and TB
20887901324dSJerome Forissier          * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2089039e02dfSJerome Forissier          * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
20907901324dSJerome Forissier          * divides TA.
20917901324dSJerome Forissier          */
2092*32b31808SJens Wiklander         if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2093817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2094817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2095*32b31808SJens Wiklander         } else {
2096817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2097817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
2098817466cbSJens Wiklander         }
20997901324dSJerome Forissier         /* Note that one of TA or TB is still odd. */
2100817466cbSJens Wiklander     }
2101817466cbSJens Wiklander 
21027901324dSJerome Forissier     /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
21037901324dSJerome Forissier      * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
21047901324dSJerome Forissier      * - If there was at least one loop iteration, then one of TA or TB is odd,
21057901324dSJerome Forissier      *   and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
21067901324dSJerome Forissier      *   lz = min(a,b) so gcd(A,B) = 2^lz * TB.
21077901324dSJerome Forissier      * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
21087901324dSJerome Forissier      *   In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
21097901324dSJerome Forissier      */
21107901324dSJerome Forissier 
2111817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2112817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
2113817466cbSJens Wiklander 
2114817466cbSJens Wiklander cleanup:
2115817466cbSJens Wiklander 
211611fa71b9SJerome Forissier     mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
2117817466cbSJens Wiklander 
2118*32b31808SJens Wiklander     return ret;
21197901324dSJerome Forissier }
21207901324dSJerome Forissier 
2121817466cbSJens Wiklander /*
2122817466cbSJens Wiklander  * Fill X with size bytes of random.
2123*32b31808SJens Wiklander  * The bytes returned from the RNG are used in a specific order which
2124*32b31808SJens Wiklander  * is suitable for deterministic ECDSA (see the specification of
2125*32b31808SJens Wiklander  * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
2126817466cbSJens Wiklander  */
2127817466cbSJens Wiklander int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2128817466cbSJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t),
2129817466cbSJens Wiklander                             void *p_rng)
2130817466cbSJens Wiklander {
213111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2132*32b31808SJens Wiklander     const size_t limbs = CHARS_TO_LIMBS(size);
21335b25c76aSJerome Forissier 
21343d3b0591SJens Wiklander     MPI_VALIDATE_RET(X     != NULL);
21353d3b0591SJens Wiklander     MPI_VALIDATE_RET(f_rng != NULL);
2136817466cbSJens Wiklander 
21375b25c76aSJerome Forissier     /* Ensure that target MPI has exactly the necessary number of limbs */
21387901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2139*32b31808SJens Wiklander     if (size == 0) {
2140*32b31808SJens Wiklander         return 0;
2141*32b31808SJens Wiklander     }
2142817466cbSJens Wiklander 
2143*32b31808SJens Wiklander     ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
2144817466cbSJens Wiklander 
2145817466cbSJens Wiklander cleanup:
2146*32b31808SJens Wiklander     return ret;
2147817466cbSJens Wiklander }
2148817466cbSJens Wiklander 
21497901324dSJerome Forissier int mbedtls_mpi_random(mbedtls_mpi *X,
21507901324dSJerome Forissier                        mbedtls_mpi_sint min,
21517901324dSJerome Forissier                        const mbedtls_mpi *N,
21527901324dSJerome Forissier                        int (*f_rng)(void *, unsigned char *, size_t),
21537901324dSJerome Forissier                        void *p_rng)
21547901324dSJerome Forissier {
2155*32b31808SJens Wiklander     if (min < 0) {
2156*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2157*32b31808SJens Wiklander     }
2158*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2159*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2160*32b31808SJens Wiklander     }
21617901324dSJerome Forissier 
21627901324dSJerome Forissier     /* Ensure that target MPI has exactly the same number of limbs
21637901324dSJerome Forissier      * as the upper bound, even if the upper bound has leading zeros.
2164*32b31808SJens Wiklander      * This is necessary for mbedtls_mpi_core_random. */
2165*32b31808SJens Wiklander     int ret = mbedtls_mpi_resize_clear(X, N->n);
2166*32b31808SJens Wiklander     if (ret != 0) {
2167*32b31808SJens Wiklander         return ret;
21687901324dSJerome Forissier     }
21697901324dSJerome Forissier 
2170*32b31808SJens Wiklander     return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
21717901324dSJerome Forissier }
21727901324dSJerome Forissier 
2173817466cbSJens Wiklander /*
2174817466cbSJens Wiklander  * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
2175817466cbSJens Wiklander  */
2176817466cbSJens Wiklander int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
2177817466cbSJens Wiklander {
217811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2179817466cbSJens Wiklander     mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
21803d3b0591SJens Wiklander     MPI_VALIDATE_RET(X != NULL);
21813d3b0591SJens Wiklander     MPI_VALIDATE_RET(A != NULL);
21823d3b0591SJens Wiklander     MPI_VALIDATE_RET(N != NULL);
2183817466cbSJens Wiklander 
2184*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2185*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2186*32b31808SJens Wiklander     }
2187817466cbSJens Wiklander 
218898bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TU);
218998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&U1); mbedtls_mpi_init_mempool(&U2);
219098bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&G); mbedtls_mpi_init_mempool(&TB);
219198bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&TV); mbedtls_mpi_init_mempool(&V1);
219298bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&V2);
2193817466cbSJens Wiklander 
2194817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
2195817466cbSJens Wiklander 
2196*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
2197817466cbSJens Wiklander         ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2198817466cbSJens Wiklander         goto cleanup;
2199817466cbSJens Wiklander     }
2200817466cbSJens Wiklander 
2201817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2202817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2203817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2204817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
2205817466cbSJens Wiklander 
2206817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2207817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2208817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2209817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
2210817466cbSJens Wiklander 
2211*32b31808SJens Wiklander     do {
2212*32b31808SJens Wiklander         while ((TU.p[0] & 1) == 0) {
2213817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
2214817466cbSJens Wiklander 
2215*32b31808SJens Wiklander             if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2216817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2217817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
2218817466cbSJens Wiklander             }
2219817466cbSJens Wiklander 
2220817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2221817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
2222817466cbSJens Wiklander         }
2223817466cbSJens Wiklander 
2224*32b31808SJens Wiklander         while ((TV.p[0] & 1) == 0) {
2225817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
2226817466cbSJens Wiklander 
2227*32b31808SJens Wiklander             if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2228817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2229817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
2230817466cbSJens Wiklander             }
2231817466cbSJens Wiklander 
2232817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2233817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
2234817466cbSJens Wiklander         }
2235817466cbSJens Wiklander 
2236*32b31808SJens Wiklander         if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2237817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2238817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2239817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2240*32b31808SJens Wiklander         } else {
2241817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2242817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2243817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
2244817466cbSJens Wiklander         }
2245*32b31808SJens Wiklander     } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2246817466cbSJens Wiklander 
2247*32b31808SJens Wiklander     while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2248817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
2249*32b31808SJens Wiklander     }
2250817466cbSJens Wiklander 
2251*32b31808SJens Wiklander     while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2252817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2253*32b31808SJens Wiklander     }
2254817466cbSJens Wiklander 
2255817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
2256817466cbSJens Wiklander 
2257817466cbSJens Wiklander cleanup:
2258817466cbSJens Wiklander 
2259817466cbSJens Wiklander     mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2260817466cbSJens Wiklander     mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2261817466cbSJens Wiklander     mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
2262817466cbSJens Wiklander 
2263*32b31808SJens Wiklander     return ret;
2264817466cbSJens Wiklander }
2265817466cbSJens Wiklander 
2266817466cbSJens Wiklander #if defined(MBEDTLS_GENPRIME)
2267817466cbSJens Wiklander 
2268817466cbSJens Wiklander static const int small_prime[] =
2269817466cbSJens Wiklander {
2270817466cbSJens Wiklander     3,    5,    7,   11,   13,   17,   19,   23,
2271817466cbSJens Wiklander     29,   31,   37,   41,   43,   47,   53,   59,
2272817466cbSJens Wiklander     61,   67,   71,   73,   79,   83,   89,   97,
2273817466cbSJens Wiklander     101,  103,  107,  109,  113,  127,  131,  137,
2274817466cbSJens Wiklander     139,  149,  151,  157,  163,  167,  173,  179,
2275817466cbSJens Wiklander     181,  191,  193,  197,  199,  211,  223,  227,
2276817466cbSJens Wiklander     229,  233,  239,  241,  251,  257,  263,  269,
2277817466cbSJens Wiklander     271,  277,  281,  283,  293,  307,  311,  313,
2278817466cbSJens Wiklander     317,  331,  337,  347,  349,  353,  359,  367,
2279817466cbSJens Wiklander     373,  379,  383,  389,  397,  401,  409,  419,
2280817466cbSJens Wiklander     421,  431,  433,  439,  443,  449,  457,  461,
2281817466cbSJens Wiklander     463,  467,  479,  487,  491,  499,  503,  509,
2282817466cbSJens Wiklander     521,  523,  541,  547,  557,  563,  569,  571,
2283817466cbSJens Wiklander     577,  587,  593,  599,  601,  607,  613,  617,
2284817466cbSJens Wiklander     619,  631,  641,  643,  647,  653,  659,  661,
2285817466cbSJens Wiklander     673,  677,  683,  691,  701,  709,  719,  727,
2286817466cbSJens Wiklander     733,  739,  743,  751,  757,  761,  769,  773,
2287817466cbSJens Wiklander     787,  797,  809,  811,  821,  823,  827,  829,
2288817466cbSJens Wiklander     839,  853,  857,  859,  863,  877,  881,  883,
2289817466cbSJens Wiklander     887,  907,  911,  919,  929,  937,  941,  947,
2290817466cbSJens Wiklander     953,  967,  971,  977,  983,  991,  997, -103
2291817466cbSJens Wiklander };
2292817466cbSJens Wiklander 
2293817466cbSJens Wiklander /*
2294817466cbSJens Wiklander  * Small divisors test (X must be positive)
2295817466cbSJens Wiklander  *
2296817466cbSJens Wiklander  * Return values:
2297817466cbSJens Wiklander  * 0: no small factor (possible prime, more tests needed)
2298817466cbSJens Wiklander  * 1: certain prime
2299817466cbSJens Wiklander  * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2300817466cbSJens Wiklander  * other negative: error
2301817466cbSJens Wiklander  */
2302817466cbSJens Wiklander static int mpi_check_small_factors(const mbedtls_mpi *X)
2303817466cbSJens Wiklander {
2304817466cbSJens Wiklander     int ret = 0;
2305817466cbSJens Wiklander     size_t i;
2306817466cbSJens Wiklander     mbedtls_mpi_uint r;
2307817466cbSJens Wiklander 
2308*32b31808SJens Wiklander     if ((X->p[0] & 1) == 0) {
2309*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2310*32b31808SJens Wiklander     }
2311817466cbSJens Wiklander 
2312*32b31808SJens Wiklander     for (i = 0; small_prime[i] > 0; i++) {
2313*32b31808SJens Wiklander         if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2314*32b31808SJens Wiklander             return 1;
2315*32b31808SJens Wiklander         }
2316817466cbSJens Wiklander 
2317817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
2318817466cbSJens Wiklander 
2319*32b31808SJens Wiklander         if (r == 0) {
2320*32b31808SJens Wiklander             return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2321*32b31808SJens Wiklander         }
2322817466cbSJens Wiklander     }
2323817466cbSJens Wiklander 
2324817466cbSJens Wiklander cleanup:
2325*32b31808SJens Wiklander     return ret;
2326817466cbSJens Wiklander }
2327817466cbSJens Wiklander 
2328817466cbSJens Wiklander /*
2329817466cbSJens Wiklander  * Miller-Rabin pseudo-primality test  (HAC 4.24)
2330817466cbSJens Wiklander  */
23313d3b0591SJens Wiklander static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2332817466cbSJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t),
2333817466cbSJens Wiklander                             void *p_rng)
2334817466cbSJens Wiklander {
2335817466cbSJens Wiklander     int ret, count;
23363d3b0591SJens Wiklander     size_t i, j, k, s;
2337817466cbSJens Wiklander     mbedtls_mpi W, R, T, A, RR;
2338817466cbSJens Wiklander 
23393d3b0591SJens Wiklander     MPI_VALIDATE_RET(X     != NULL);
23403d3b0591SJens Wiklander     MPI_VALIDATE_RET(f_rng != NULL);
23413d3b0591SJens Wiklander 
234298bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&W); mbedtls_mpi_init_mempool(&R);
234398bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A);
234498bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&RR);
2345817466cbSJens Wiklander 
2346817466cbSJens Wiklander     /*
2347817466cbSJens Wiklander      * W = |X| - 1
2348817466cbSJens Wiklander      * R = W >> lsb( W )
2349817466cbSJens Wiklander      */
2350817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2351817466cbSJens Wiklander     s = mbedtls_mpi_lsb(&W);
2352817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2353817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
2354817466cbSJens Wiklander 
2355*32b31808SJens Wiklander     for (i = 0; i < rounds; i++) {
2356817466cbSJens Wiklander         /*
2357817466cbSJens Wiklander          * pick a random A, 1 < A < |X| - 1
2358817466cbSJens Wiklander          */
2359817466cbSJens Wiklander         count = 0;
2360817466cbSJens Wiklander         do {
2361817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
2362817466cbSJens Wiklander 
2363817466cbSJens Wiklander             j = mbedtls_mpi_bitlen(&A);
2364817466cbSJens Wiklander             k = mbedtls_mpi_bitlen(&W);
2365817466cbSJens Wiklander             if (j > k) {
23663d3b0591SJens Wiklander                 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
2367817466cbSJens Wiklander             }
2368817466cbSJens Wiklander 
2369117cce93SJens Wiklander             if (count++ > 300) {
2370336e3299SJens Wiklander                 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2371336e3299SJens Wiklander                 goto cleanup;
2372817466cbSJens Wiklander             }
2373817466cbSJens Wiklander 
2374817466cbSJens Wiklander         } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2375817466cbSJens Wiklander                  mbedtls_mpi_cmp_int(&A, 1)  <= 0);
2376817466cbSJens Wiklander 
2377817466cbSJens Wiklander         /*
2378817466cbSJens Wiklander          * A = A^R mod |X|
2379817466cbSJens Wiklander          */
2380817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
2381817466cbSJens Wiklander 
2382817466cbSJens Wiklander         if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2383*32b31808SJens Wiklander             mbedtls_mpi_cmp_int(&A,  1) == 0) {
2384817466cbSJens Wiklander             continue;
2385*32b31808SJens Wiklander         }
2386817466cbSJens Wiklander 
2387817466cbSJens Wiklander         j = 1;
2388*32b31808SJens Wiklander         while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
2389817466cbSJens Wiklander             /*
2390817466cbSJens Wiklander              * A = A * A mod |X|
2391817466cbSJens Wiklander              */
2392817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2393817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
2394817466cbSJens Wiklander 
2395*32b31808SJens Wiklander             if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
2396817466cbSJens Wiklander                 break;
2397*32b31808SJens Wiklander             }
2398817466cbSJens Wiklander 
2399817466cbSJens Wiklander             j++;
2400817466cbSJens Wiklander         }
2401817466cbSJens Wiklander 
2402817466cbSJens Wiklander         /*
2403817466cbSJens Wiklander          * not prime if A != |X| - 1 or A == 1
2404817466cbSJens Wiklander          */
2405817466cbSJens Wiklander         if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2406*32b31808SJens Wiklander             mbedtls_mpi_cmp_int(&A,  1) == 0) {
2407817466cbSJens Wiklander             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2408817466cbSJens Wiklander             break;
2409817466cbSJens Wiklander         }
2410817466cbSJens Wiklander     }
2411817466cbSJens Wiklander 
2412817466cbSJens Wiklander cleanup:
24133d3b0591SJens Wiklander     mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
24143d3b0591SJens Wiklander     mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2415817466cbSJens Wiklander     mbedtls_mpi_free(&RR);
2416817466cbSJens Wiklander 
2417*32b31808SJens Wiklander     return ret;
2418817466cbSJens Wiklander }
2419817466cbSJens Wiklander 
2420817466cbSJens Wiklander /*
2421817466cbSJens Wiklander  * Pseudo-primality test: small factors, then Miller-Rabin
2422817466cbSJens Wiklander  */
24233d3b0591SJens Wiklander int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2424817466cbSJens Wiklander                              int (*f_rng)(void *, unsigned char *, size_t),
2425817466cbSJens Wiklander                              void *p_rng)
2426817466cbSJens Wiklander {
242711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2428817466cbSJens Wiklander     mbedtls_mpi XX;
24293d3b0591SJens Wiklander     MPI_VALIDATE_RET(X     != NULL);
24303d3b0591SJens Wiklander     MPI_VALIDATE_RET(f_rng != NULL);
2431817466cbSJens Wiklander 
2432817466cbSJens Wiklander     XX.s = 1;
2433817466cbSJens Wiklander     XX.n = X->n;
2434817466cbSJens Wiklander     XX.p = X->p;
2435817466cbSJens Wiklander 
2436817466cbSJens Wiklander     if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2437*32b31808SJens Wiklander         mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2438*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2439817466cbSJens Wiklander     }
2440817466cbSJens Wiklander 
2441*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2442*32b31808SJens Wiklander         return 0;
2443817466cbSJens Wiklander     }
2444817466cbSJens Wiklander 
2445*32b31808SJens Wiklander     if ((ret = mpi_check_small_factors(&XX)) != 0) {
2446*32b31808SJens Wiklander         if (ret == 1) {
2447*32b31808SJens Wiklander             return 0;
24483d3b0591SJens Wiklander         }
2449*32b31808SJens Wiklander 
2450*32b31808SJens Wiklander         return ret;
2451*32b31808SJens Wiklander     }
2452*32b31808SJens Wiklander 
2453*32b31808SJens Wiklander     return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
2454*32b31808SJens Wiklander }
24553d3b0591SJens Wiklander 
24563d3b0591SJens Wiklander /*
24573d3b0591SJens Wiklander  * Prime number generation
24583d3b0591SJens Wiklander  *
24593d3b0591SJens Wiklander  * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
24603d3b0591SJens Wiklander  * be either 1024 bits or 1536 bits long, and flags must contain
24613d3b0591SJens Wiklander  * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
24623d3b0591SJens Wiklander  */
24633d3b0591SJens Wiklander int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
24643d3b0591SJens Wiklander                           int (*f_rng)(void *, unsigned char *, size_t),
24653d3b0591SJens Wiklander                           void *p_rng)
24663d3b0591SJens Wiklander {
24673d3b0591SJens Wiklander #ifdef MBEDTLS_HAVE_INT64
24683d3b0591SJens Wiklander // ceil(2^63.5)
24693d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
24703d3b0591SJens Wiklander #else
24713d3b0591SJens Wiklander // ceil(2^31.5)
24723d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
24733d3b0591SJens Wiklander #endif
24743d3b0591SJens Wiklander     int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2475817466cbSJens Wiklander     size_t k, n;
24763d3b0591SJens Wiklander     int rounds;
2477817466cbSJens Wiklander     mbedtls_mpi_uint r;
2478817466cbSJens Wiklander     mbedtls_mpi Y;
2479817466cbSJens Wiklander 
24803d3b0591SJens Wiklander     MPI_VALIDATE_RET(X     != NULL);
24813d3b0591SJens Wiklander     MPI_VALIDATE_RET(f_rng != NULL);
24823d3b0591SJens Wiklander 
2483*32b31808SJens Wiklander     if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2484*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2485*32b31808SJens Wiklander     }
2486817466cbSJens Wiklander 
248798bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&Y);
2488817466cbSJens Wiklander 
2489817466cbSJens Wiklander     n = BITS_TO_LIMBS(nbits);
2490817466cbSJens Wiklander 
2491*32b31808SJens Wiklander     if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
24923d3b0591SJens Wiklander         /*
24933d3b0591SJens Wiklander          * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
24943d3b0591SJens Wiklander          */
24953d3b0591SJens Wiklander         rounds = ((nbits >= 1300) ?  2 : (nbits >=  850) ?  3 :
24963d3b0591SJens Wiklander                   (nbits >=  650) ?  4 : (nbits >=  350) ?  8 :
24973d3b0591SJens Wiklander                   (nbits >=  250) ? 12 : (nbits >=  150) ? 18 : 27);
2498*32b31808SJens Wiklander     } else {
24993d3b0591SJens Wiklander         /*
25003d3b0591SJens Wiklander          * 2^-100 error probability, number of rounds computed based on HAC,
25013d3b0591SJens Wiklander          * fact 4.48
25023d3b0591SJens Wiklander          */
25033d3b0591SJens Wiklander         rounds = ((nbits >= 1450) ?  4 : (nbits >=  1150) ?  5 :
25043d3b0591SJens Wiklander                   (nbits >= 1000) ?  6 : (nbits >=   850) ?  7 :
25053d3b0591SJens Wiklander                   (nbits >=  750) ?  8 : (nbits >=   500) ? 13 :
25063d3b0591SJens Wiklander                   (nbits >=  250) ? 28 : (nbits >=   150) ? 40 : 51);
25073d3b0591SJens Wiklander     }
25083d3b0591SJens Wiklander 
2509*32b31808SJens Wiklander     while (1) {
2510817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
25113d3b0591SJens Wiklander         /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2512*32b31808SJens Wiklander         if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2513*32b31808SJens Wiklander             continue;
2514*32b31808SJens Wiklander         }
2515817466cbSJens Wiklander 
25163d3b0591SJens Wiklander         k = n * biL;
2517*32b31808SJens Wiklander         if (k > nbits) {
2518*32b31808SJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2519*32b31808SJens Wiklander         }
2520817466cbSJens Wiklander         X->p[0] |= 1;
2521817466cbSJens Wiklander 
2522*32b31808SJens Wiklander         if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
25233d3b0591SJens Wiklander             ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
25243d3b0591SJens Wiklander 
2525*32b31808SJens Wiklander             if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
2526817466cbSJens Wiklander                 goto cleanup;
2527817466cbSJens Wiklander             }
2528*32b31808SJens Wiklander         } else {
2529817466cbSJens Wiklander             /*
2530*32b31808SJens Wiklander              * A necessary condition for Y and X = 2Y + 1 to be prime
2531817466cbSJens Wiklander              * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2532817466cbSJens Wiklander              * Make sure it is satisfied, while keeping X = 3 mod 4
2533817466cbSJens Wiklander              */
2534817466cbSJens Wiklander 
2535817466cbSJens Wiklander             X->p[0] |= 2;
2536817466cbSJens Wiklander 
2537817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2538*32b31808SJens Wiklander             if (r == 0) {
2539817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2540*32b31808SJens Wiklander             } else if (r == 1) {
2541817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2542*32b31808SJens Wiklander             }
2543817466cbSJens Wiklander 
2544817466cbSJens Wiklander             /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2545817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2546817466cbSJens Wiklander             MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
2547817466cbSJens Wiklander 
2548*32b31808SJens Wiklander             while (1) {
2549817466cbSJens Wiklander                 /*
2550817466cbSJens Wiklander                  * First, check small factors for X and Y
2551817466cbSJens Wiklander                  * before doing Miller-Rabin on any of them
2552817466cbSJens Wiklander                  */
2553817466cbSJens Wiklander                 if ((ret = mpi_check_small_factors(X)) == 0 &&
2554817466cbSJens Wiklander                     (ret = mpi_check_small_factors(&Y)) == 0 &&
25553d3b0591SJens Wiklander                     (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
25563d3b0591SJens Wiklander                     == 0 &&
25573d3b0591SJens Wiklander                     (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2558*32b31808SJens Wiklander                     == 0) {
25593d3b0591SJens Wiklander                     goto cleanup;
2560*32b31808SJens Wiklander                 }
2561817466cbSJens Wiklander 
2562*32b31808SJens Wiklander                 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
2563817466cbSJens Wiklander                     goto cleanup;
2564*32b31808SJens Wiklander                 }
2565817466cbSJens Wiklander 
2566817466cbSJens Wiklander                 /*
2567817466cbSJens Wiklander                  * Next candidates. We want to preserve Y = (X-1) / 2 and
2568817466cbSJens Wiklander                  * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2569817466cbSJens Wiklander                  * so up Y by 6 and X by 12.
2570817466cbSJens Wiklander                  */
2571817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X,  X, 12));
2572817466cbSJens Wiklander                 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
2573817466cbSJens Wiklander             }
2574817466cbSJens Wiklander         }
25753d3b0591SJens Wiklander     }
2576817466cbSJens Wiklander 
2577817466cbSJens Wiklander cleanup:
2578817466cbSJens Wiklander 
2579817466cbSJens Wiklander     mbedtls_mpi_free(&Y);
2580817466cbSJens Wiklander 
2581*32b31808SJens Wiklander     return ret;
2582817466cbSJens Wiklander }
2583817466cbSJens Wiklander 
2584817466cbSJens Wiklander #endif /* MBEDTLS_GENPRIME */
2585817466cbSJens Wiklander 
2586817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
2587817466cbSJens Wiklander 
2588817466cbSJens Wiklander #define GCD_PAIR_COUNT  3
2589817466cbSJens Wiklander 
2590817466cbSJens Wiklander static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2591817466cbSJens Wiklander {
2592817466cbSJens Wiklander     { 693, 609, 21 },
2593817466cbSJens Wiklander     { 1764, 868, 28 },
2594817466cbSJens Wiklander     { 768454923, 542167814, 1 }
2595817466cbSJens Wiklander };
2596817466cbSJens Wiklander 
2597817466cbSJens Wiklander /*
2598817466cbSJens Wiklander  * Checkup routine
2599817466cbSJens Wiklander  */
2600817466cbSJens Wiklander int mbedtls_mpi_self_test(int verbose)
2601817466cbSJens Wiklander {
2602817466cbSJens Wiklander     int ret, i;
2603817466cbSJens Wiklander     mbedtls_mpi A, E, N, X, Y, U, V;
2604817466cbSJens Wiklander 
260598bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&A); mbedtls_mpi_init_mempool(&E);
260698bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&N); mbedtls_mpi_init_mempool(&X);
260798bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&Y); mbedtls_mpi_init_mempool(&U);
260898bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool(&V);
2609817466cbSJens Wiklander 
2610817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2611817466cbSJens Wiklander                                             "EFE021C2645FD1DC586E69184AF4A31E" \
2612817466cbSJens Wiklander                                             "D5F53E93B5F123FA41680867BA110131" \
2613817466cbSJens Wiklander                                             "944FE7952E2517337780CB0DB80E61AA" \
2614817466cbSJens Wiklander                                             "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
2615817466cbSJens Wiklander 
2616817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2617817466cbSJens Wiklander                                             "B2E7EFD37075B9F03FF989C7C5051C20" \
2618817466cbSJens Wiklander                                             "34D2A323810251127E7BF8625A4F49A5" \
2619817466cbSJens Wiklander                                             "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2620817466cbSJens Wiklander                                             "5B5C25763222FEFCCFC38B832366C29E"));
2621817466cbSJens Wiklander 
2622817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2623817466cbSJens Wiklander                                             "0066A198186C18C10B2F5ED9B522752A" \
2624817466cbSJens Wiklander                                             "9830B69916E535C8F047518A889A43A5" \
2625817466cbSJens Wiklander                                             "94B6BED27A168D31D4A52F88925AA8F5"));
2626817466cbSJens Wiklander 
2627817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
2628817466cbSJens Wiklander 
2629817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2630817466cbSJens Wiklander                                             "602AB7ECA597A3D6B56FF9829A5E8B85" \
2631817466cbSJens Wiklander                                             "9E857EA95A03512E2BAE7391688D264A" \
2632817466cbSJens Wiklander                                             "A5663B0341DB9CCFD2C4C5F421FEC814" \
2633817466cbSJens Wiklander                                             "8001B72E848A38CAE1C65F78E56ABDEF" \
2634817466cbSJens Wiklander                                             "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2635817466cbSJens Wiklander                                             "ECF677152EF804370C1A305CAF3B5BF1" \
2636817466cbSJens Wiklander                                             "30879B56C61DE584A0F53A2447A51E"));
2637817466cbSJens Wiklander 
2638*32b31808SJens Wiklander     if (verbose != 0) {
2639817466cbSJens Wiklander         mbedtls_printf("  MPI test #1 (mul_mpi): ");
2640*32b31808SJens Wiklander     }
2641817466cbSJens Wiklander 
2642*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2643*32b31808SJens Wiklander         if (verbose != 0) {
2644817466cbSJens Wiklander             mbedtls_printf("failed\n");
2645*32b31808SJens Wiklander         }
2646817466cbSJens Wiklander 
2647817466cbSJens Wiklander         ret = 1;
2648817466cbSJens Wiklander         goto cleanup;
2649817466cbSJens Wiklander     }
2650817466cbSJens Wiklander 
2651*32b31808SJens Wiklander     if (verbose != 0) {
2652817466cbSJens Wiklander         mbedtls_printf("passed\n");
2653*32b31808SJens Wiklander     }
2654817466cbSJens Wiklander 
2655817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
2656817466cbSJens Wiklander 
2657817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2658817466cbSJens Wiklander                                             "256567336059E52CAE22925474705F39A94"));
2659817466cbSJens Wiklander 
2660817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2661817466cbSJens Wiklander                                             "6613F26162223DF488E9CD48CC132C7A" \
2662817466cbSJens Wiklander                                             "0AC93C701B001B092E4E5B9F73BCD27B" \
2663817466cbSJens Wiklander                                             "9EE50D0657C77F374E903CDFA4C642"));
2664817466cbSJens Wiklander 
2665*32b31808SJens Wiklander     if (verbose != 0) {
2666817466cbSJens Wiklander         mbedtls_printf("  MPI test #2 (div_mpi): ");
2667*32b31808SJens Wiklander     }
2668817466cbSJens Wiklander 
2669817466cbSJens Wiklander     if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2670*32b31808SJens Wiklander         mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2671*32b31808SJens Wiklander         if (verbose != 0) {
2672817466cbSJens Wiklander             mbedtls_printf("failed\n");
2673*32b31808SJens Wiklander         }
2674817466cbSJens Wiklander 
2675817466cbSJens Wiklander         ret = 1;
2676817466cbSJens Wiklander         goto cleanup;
2677817466cbSJens Wiklander     }
2678817466cbSJens Wiklander 
2679*32b31808SJens Wiklander     if (verbose != 0) {
2680817466cbSJens Wiklander         mbedtls_printf("passed\n");
2681*32b31808SJens Wiklander     }
2682817466cbSJens Wiklander 
2683817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
2684817466cbSJens Wiklander 
2685817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2686817466cbSJens Wiklander                                             "36E139AEA55215609D2816998ED020BB" \
2687817466cbSJens Wiklander                                             "BD96C37890F65171D948E9BC7CBAA4D9" \
2688817466cbSJens Wiklander                                             "325D24D6A3C12710F10A09FA08AB87"));
2689817466cbSJens Wiklander 
2690*32b31808SJens Wiklander     if (verbose != 0) {
2691817466cbSJens Wiklander         mbedtls_printf("  MPI test #3 (exp_mod): ");
2692*32b31808SJens Wiklander     }
2693817466cbSJens Wiklander 
2694*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2695*32b31808SJens Wiklander         if (verbose != 0) {
2696817466cbSJens Wiklander             mbedtls_printf("failed\n");
2697*32b31808SJens Wiklander         }
2698817466cbSJens Wiklander 
2699817466cbSJens Wiklander         ret = 1;
2700817466cbSJens Wiklander         goto cleanup;
2701817466cbSJens Wiklander     }
2702817466cbSJens Wiklander 
2703*32b31808SJens Wiklander     if (verbose != 0) {
2704817466cbSJens Wiklander         mbedtls_printf("passed\n");
2705*32b31808SJens Wiklander     }
2706817466cbSJens Wiklander 
2707817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
2708817466cbSJens Wiklander 
2709817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2710817466cbSJens Wiklander                                             "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2711817466cbSJens Wiklander                                             "C3DBA76456363A10869622EAC2DD84EC" \
2712817466cbSJens Wiklander                                             "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
2713817466cbSJens Wiklander 
2714*32b31808SJens Wiklander     if (verbose != 0) {
2715817466cbSJens Wiklander         mbedtls_printf("  MPI test #4 (inv_mod): ");
2716*32b31808SJens Wiklander     }
2717817466cbSJens Wiklander 
2718*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2719*32b31808SJens Wiklander         if (verbose != 0) {
2720817466cbSJens Wiklander             mbedtls_printf("failed\n");
2721*32b31808SJens Wiklander         }
2722817466cbSJens Wiklander 
2723817466cbSJens Wiklander         ret = 1;
2724817466cbSJens Wiklander         goto cleanup;
2725817466cbSJens Wiklander     }
2726817466cbSJens Wiklander 
2727*32b31808SJens Wiklander     if (verbose != 0) {
2728817466cbSJens Wiklander         mbedtls_printf("passed\n");
2729*32b31808SJens Wiklander     }
2730817466cbSJens Wiklander 
2731*32b31808SJens Wiklander     if (verbose != 0) {
2732817466cbSJens Wiklander         mbedtls_printf("  MPI test #5 (simple gcd): ");
2733*32b31808SJens Wiklander     }
2734817466cbSJens Wiklander 
2735*32b31808SJens Wiklander     for (i = 0; i < GCD_PAIR_COUNT; i++) {
2736817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2737817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
2738817466cbSJens Wiklander 
2739817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
2740817466cbSJens Wiklander 
2741*32b31808SJens Wiklander         if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2742*32b31808SJens Wiklander             if (verbose != 0) {
2743817466cbSJens Wiklander                 mbedtls_printf("failed at %d\n", i);
2744*32b31808SJens Wiklander             }
2745817466cbSJens Wiklander 
2746817466cbSJens Wiklander             ret = 1;
2747817466cbSJens Wiklander             goto cleanup;
2748817466cbSJens Wiklander         }
2749817466cbSJens Wiklander     }
2750817466cbSJens Wiklander 
2751*32b31808SJens Wiklander     if (verbose != 0) {
2752817466cbSJens Wiklander         mbedtls_printf("passed\n");
2753*32b31808SJens Wiklander     }
2754817466cbSJens Wiklander 
2755817466cbSJens Wiklander cleanup:
2756817466cbSJens Wiklander 
2757*32b31808SJens Wiklander     if (ret != 0 && verbose != 0) {
27587901324dSJerome Forissier         mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2759*32b31808SJens Wiklander     }
2760817466cbSJens Wiklander 
2761817466cbSJens Wiklander     mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2762817466cbSJens Wiklander     mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
2763817466cbSJens Wiklander 
2764*32b31808SJens Wiklander     if (verbose != 0) {
2765817466cbSJens Wiklander         mbedtls_printf("\n");
2766*32b31808SJens Wiklander     }
2767817466cbSJens Wiklander 
2768*32b31808SJens Wiklander     return ret;
2769817466cbSJens Wiklander }
2770817466cbSJens Wiklander 
2771817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
2772817466cbSJens Wiklander 
2773817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */
2774