blob: 47f46a6e80964f79f7501fa943dff1a79b468741 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * Multi-precision integer library
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
Tom Van Eyckc1633172024-04-09 18:44:13 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7
8/*
9 * The following sources were referenced in the design of this Multi-precision
10 * Integer library:
11 *
12 * [1] Handbook of Applied Cryptography - 1997
13 * Menezes, van Oorschot and Vanstone
14 *
15 * [2] Multi-Precision Math
16 * Tom St Denis
17 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
18 *
19 * [3] GNU Multi-Precision Arithmetic Library
20 * https://gmplib.org/manual/index.html
21 *
22 */
23
Jerome Forissier79013242021-07-28 10:24:04 +020024#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020025
26#if defined(MBEDTLS_BIGNUM_C)
27
28#include "mbedtls/bignum.h"
Jens Wiklander32b31802023-10-06 16:59:46 +020029#include "bignum_core.h"
30#include "bn_mul.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010031#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020032#include "mbedtls/error.h"
Jerome Forissier039e02d2022-08-09 17:10:15 +020033#include "constant_time_internal.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020034
Jerome Forissier039e02d2022-08-09 17:10:15 +020035#include <limits.h>
Jens Wiklander817466c2018-05-22 13:49:31 +020036#include <string.h>
37
Jens Wiklander817466c2018-05-22 13:49:31 +020038#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020039
Jens Wiklander8eaf6922018-11-08 11:18:22 +010040#include <mempool.h>
41
42void *mbedtls_mpi_mempool;
Jens Wiklander98bd5fe2018-11-08 11:18:22 +010043
Jens Wiklander817466c2018-05-22 13:49:31 +020044
Tom Van Eyckc1633172024-04-09 18:44:13 +020045/*
46 * Conditionally select an MPI sign in constant time.
47 * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid
48 * values.)
49 */
50static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,
51 signed short sign1, signed short sign2)
52{
53 return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;
54}
Jens Wiklander817466c2018-05-22 13:49:31 +020055
Tom Van Eyckc1633172024-04-09 18:44:13 +020056/*
57 * Compare signed values in constant time
58 */
59int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
60 const mbedtls_mpi *Y,
61 unsigned *ret)
62{
63 mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
64
65 if (X->n != Y->n) {
66 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
67 }
68
69 /*
70 * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.
71 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
72 */
73 X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
74 Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
75
76 /*
77 * If the signs are different, then the positive operand is the bigger.
78 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
79 * is false if X is positive (X_is_negative == 0).
80 */
81 different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
82 result = mbedtls_ct_bool_and(different_sign, X_is_negative);
83
84 /*
85 * Assuming signs are the same, compare X and Y. We switch the comparison
86 * order if they are negative so that we get the right result, regardles of
87 * sign.
88 */
89
90 /* This array is used to conditionally swap the pointers in const time */
91 void * const p[2] = { X->p, Y->p };
92 size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
93 mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
94
95 /*
96 * Store in result iff the signs are the same (i.e., iff different_sign == false). If
97 * the signs differ, result has already been set, so we don't change it.
98 */
99 result = mbedtls_ct_bool_or(result,
100 mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
101
102 *ret = mbedtls_ct_uint_if_else_0(result, 1);
103
104 return 0;
105}
106
107/*
108 * Conditionally assign X = Y, without leaking information
109 * about whether the assignment was made or not.
110 * (Leaking information about the respective sizes of X and Y is ok however.)
111 */
112#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
113 (_MSC_FULL_VER < 193131103)
114/*
115 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
116 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
117 */
118__declspec(noinline)
119#endif
120int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
121 const mbedtls_mpi *Y,
122 unsigned char assign)
123{
124 int ret = 0;
125
126 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
127
128 {
129 mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
130
131 X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);
132
133 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
134
135 mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
136 for (size_t i = Y->n; i < X->n; i++) {
137 X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
138 }
139 }
140
141cleanup:
142 return ret;
143}
144
145/*
146 * Conditionally swap X and Y, without leaking information
147 * about whether the swap was made or not.
148 * Here it is not ok to simply swap the pointers, which would lead to
149 * different memory access patterns when X and Y are used afterwards.
150 */
151int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
152 mbedtls_mpi *Y,
153 unsigned char swap)
154{
155 int ret = 0;
156 int s;
157
158 if (X == Y) {
159 return 0;
160 }
161
162 mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
163
164 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
165 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
166
167 s = X->s;
168 X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);
169 Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);
170
171 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
172
173cleanup:
174 return ret;
175}
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100176
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100177/* Implementation that should never be optimized out by the compiler */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200178#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100179
Jens Wiklander817466c2018-05-22 13:49:31 +0200180/*
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100181 * Implementation that should never be optimized out by the compiler.
182 * Reintroduced to allow use of mempool.
183 */
184#define mbedtls_mpi_zeroize(v, n) mbedtls_platform_zeroize(v, ciL * (n))
185
186/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200187 * Initialize one MPI
188 */
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100189static void mpi_init(mbedtls_mpi *X, short use_mempool)
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100190{
Tom Van Eyckc1633172024-04-09 18:44:13 +0200191 X->s = 1;
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100192 X->use_mempool = use_mempool;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200193 X->n = 0;
194 X->p = NULL;
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100195}
196
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100197void mbedtls_mpi_init(mbedtls_mpi *X)
198{
199 mpi_init(X, 0 /*use_mempool*/);
200}
201
202void mbedtls_mpi_init_mempool(mbedtls_mpi *X)
203{
204 mpi_init(X, !!mbedtls_mpi_mempool /*use_mempool*/);
205}
206
Jens Wiklander817466c2018-05-22 13:49:31 +0200207/*
208 * Unallocate one MPI
209 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200210void mbedtls_mpi_free(mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200211{
Jens Wiklander32b31802023-10-06 16:59:46 +0200212 if (X == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200213 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200214 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200215
Jens Wiklander32b31802023-10-06 16:59:46 +0200216 if (X->p != NULL) {
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100217 if(X->use_mempool) {
218 mbedtls_mpi_zeroize(X->p, X->n);
219 mempool_free(mbedtls_mpi_mempool, X->p);
220 } else {
221 mbedtls_mpi_zeroize_and_free(X->p, X->n);
222 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200223 }
224
225 X->s = 1;
226 X->n = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100227 X->p = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200228}
229
230/*
231 * Enlarge to the specified number of limbs
232 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200233int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Jens Wiklander817466c2018-05-22 13:49:31 +0200234{
235 mbedtls_mpi_uint *p;
236
Jens Wiklander32b31802023-10-06 16:59:46 +0200237 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
238 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
239 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200240
Jens Wiklander32b31802023-10-06 16:59:46 +0200241 if (X->n < nblimbs) {
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100242 if(X->use_mempool) {
243 p = mempool_alloc(mbedtls_mpi_mempool, nblimbs * ciL);
244 if(p == NULL)
245 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
246 memset(p, 0, nblimbs * ciL);
247 } else {
248 p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL);
249 if (p == NULL)
250 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100251 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200252
Jens Wiklander32b31802023-10-06 16:59:46 +0200253 if (X->p != NULL) {
254 memcpy(p, X->p, X->n * ciL);
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100255
256 if (X->use_mempool) {
257 mbedtls_mpi_zeroize(X->p, X->n);
258 mempool_free(mbedtls_mpi_mempool, X->p);
259 } else {
260 mbedtls_mpi_zeroize_and_free(X->p, X->n);
261 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100262 }
263
Tom Van Eyckc1633172024-04-09 18:44:13 +0200264 /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
265 * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
266 X->n = (unsigned short) nblimbs;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100267 X->p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +0200268 }
269
Jens Wiklander32b31802023-10-06 16:59:46 +0200270 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200271}
272
273/*
274 * Resize down as much as possible,
275 * while keeping at least the specified number of limbs
276 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200277int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Jens Wiklander817466c2018-05-22 13:49:31 +0200278{
279 mbedtls_mpi_uint *p;
280 size_t i;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100281
Jens Wiklander32b31802023-10-06 16:59:46 +0200282 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
283 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
284 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200285
Jerome Forissier5b25c762020-04-07 11:18:49 +0200286 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200287 if (X->n <= nblimbs) {
288 return mbedtls_mpi_grow(X, nblimbs);
289 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200290 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Jens Wiklander817466c2018-05-22 13:49:31 +0200291
Jens Wiklander32b31802023-10-06 16:59:46 +0200292 for (i = X->n - 1; i > 0; i--) {
293 if (X->p[i] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200294 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200295 }
296 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200297 i++;
298
Jens Wiklander32b31802023-10-06 16:59:46 +0200299 if (i < nblimbs) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200300 i = nblimbs;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100301 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200302
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100303 if (X->use_mempool) {
304 p = mempool_alloc(mbedtls_mpi_mempool, i * ciL);
305 if (p == NULL)
306 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
307 memset(p, 0, i * ciL);
308 } else {
309 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL)
310 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200311 }
312
313 if (X->p != NULL) {
314 memcpy(p, X->p, i * ciL);
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100315
316 if (X->use_mempool) {
317 mbedtls_mpi_zeroize(X->p, X->n);
318 mempool_free(mbedtls_mpi_mempool, X->p);
319 }
320 else {
321 mbedtls_mpi_zeroize_and_free(X->p, X->n);
322 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200323 }
324
Tom Van Eyckc1633172024-04-09 18:44:13 +0200325 /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
326 * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
327 X->n = (unsigned short) i;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100328 X->p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +0200329
Jens Wiklander32b31802023-10-06 16:59:46 +0200330 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200331}
332
Jerome Forissier79013242021-07-28 10:24:04 +0200333/* Resize X to have exactly n limbs and set it to 0. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200334static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Jerome Forissier79013242021-07-28 10:24:04 +0200335{
Jens Wiklander32b31802023-10-06 16:59:46 +0200336 if (limbs == 0) {
337 mbedtls_mpi_free(X);
338 return 0;
339 } else if (X->n == limbs) {
340 memset(X->p, 0, limbs * ciL);
Jerome Forissier79013242021-07-28 10:24:04 +0200341 X->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200342 return 0;
343 } else {
344 mbedtls_mpi_free(X);
345 return mbedtls_mpi_grow(X, limbs);
Jerome Forissier79013242021-07-28 10:24:04 +0200346 }
347}
348
Jens Wiklander817466c2018-05-22 13:49:31 +0200349/*
Jerome Forissier79013242021-07-28 10:24:04 +0200350 * Copy the contents of Y into X.
351 *
352 * This function is not constant-time. Leading zeros in Y may be removed.
353 *
354 * Ensure that X does not shrink. This is not guaranteed by the public API,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200355 * but some code in the bignum module might still rely on this property.
Jens Wiklander817466c2018-05-22 13:49:31 +0200356 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200357int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200358{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100359 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200360 size_t i;
361
Jens Wiklander32b31802023-10-06 16:59:46 +0200362 if (X == Y) {
363 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200364 }
365
Jens Wiklander32b31802023-10-06 16:59:46 +0200366 if (Y->n == 0) {
367 if (X->n != 0) {
368 X->s = 1;
369 memset(X->p, 0, X->n * ciL);
370 }
371 return 0;
372 }
373
374 for (i = Y->n - 1; i > 0; i--) {
375 if (Y->p[i] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200376 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200377 }
378 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200379 i++;
380
381 X->s = Y->s;
382
Jens Wiklander32b31802023-10-06 16:59:46 +0200383 if (X->n < i) {
384 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
385 } else {
386 memset(X->p + i, 0, (X->n - i) * ciL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100387 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200388
Jens Wiklander32b31802023-10-06 16:59:46 +0200389 memcpy(X->p, Y->p, i * ciL);
Jens Wiklander817466c2018-05-22 13:49:31 +0200390
391cleanup:
392
Jens Wiklander32b31802023-10-06 16:59:46 +0200393 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200394}
395
396/*
397 * Swap the contents of X and Y
398 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200399void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200400{
401 mbedtls_mpi T;
402
Jens Wiklander32b31802023-10-06 16:59:46 +0200403 memcpy(&T, X, sizeof(mbedtls_mpi));
404 memcpy(X, Y, sizeof(mbedtls_mpi));
405 memcpy(Y, &T, sizeof(mbedtls_mpi));
406}
407
408static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
409{
410 if (z >= 0) {
411 return z;
412 }
413 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
414 * A naive -z would have undefined behavior.
415 * Write this in a way that makes popular compilers happy (GCC, Clang,
416 * MSVC). */
417 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Jens Wiklander817466c2018-05-22 13:49:31 +0200418}
419
Tom Van Eyckc1633172024-04-09 18:44:13 +0200420/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
421 * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
422#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
423
Jens Wiklander817466c2018-05-22 13:49:31 +0200424/*
425 * Set value from integer
426 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200427int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Jens Wiklander817466c2018-05-22 13:49:31 +0200428{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200429 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200430
Jens Wiklander32b31802023-10-06 16:59:46 +0200431 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
432 memset(X->p, 0, X->n * ciL);
Jens Wiklander817466c2018-05-22 13:49:31 +0200433
Jens Wiklander32b31802023-10-06 16:59:46 +0200434 X->p[0] = mpi_sint_abs(z);
Tom Van Eyckc1633172024-04-09 18:44:13 +0200435 X->s = TO_SIGN(z);
Jens Wiklander817466c2018-05-22 13:49:31 +0200436
437cleanup:
438
Jens Wiklander32b31802023-10-06 16:59:46 +0200439 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200440}
441
442/*
443 * Get a specific bit
444 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200445int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Jens Wiklander817466c2018-05-22 13:49:31 +0200446{
Jens Wiklander32b31802023-10-06 16:59:46 +0200447 if (X->n * biL <= pos) {
448 return 0;
449 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200450
Jens Wiklander32b31802023-10-06 16:59:46 +0200451 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Jens Wiklander817466c2018-05-22 13:49:31 +0200452}
453
454/*
455 * Set a bit to a specific value of 0 or 1
456 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200457int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Jens Wiklander817466c2018-05-22 13:49:31 +0200458{
459 int ret = 0;
460 size_t off = pos / biL;
461 size_t idx = pos % biL;
462
Jens Wiklander32b31802023-10-06 16:59:46 +0200463 if (val != 0 && val != 1) {
464 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200465 }
466
Jens Wiklander32b31802023-10-06 16:59:46 +0200467 if (X->n * biL <= pos) {
468 if (val == 0) {
469 return 0;
470 }
471
472 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
473 }
474
475 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200476 X->p[off] |= (mbedtls_mpi_uint) val << idx;
477
478cleanup:
479
Jens Wiklander32b31802023-10-06 16:59:46 +0200480 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200481}
482
483/*
484 * Return the number of less significant zero-bits
485 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200486size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200487{
Tom Van Eyckc1633172024-04-09 18:44:13 +0200488 size_t i;
Jens Wiklander817466c2018-05-22 13:49:31 +0200489
Tom Van Eyckc1633172024-04-09 18:44:13 +0200490#if defined(__has_builtin)
491#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
492 #define mbedtls_mpi_uint_ctz __builtin_ctz
493#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
494 #define mbedtls_mpi_uint_ctz __builtin_ctzl
495#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
496 #define mbedtls_mpi_uint_ctz __builtin_ctzll
497#endif
498#endif
499
500#if defined(mbedtls_mpi_uint_ctz)
Jens Wiklander32b31802023-10-06 16:59:46 +0200501 for (i = 0; i < X->n; i++) {
Tom Van Eyckc1633172024-04-09 18:44:13 +0200502 if (X->p[i] != 0) {
503 return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
504 }
505 }
506#else
507 size_t count = 0;
508 for (i = 0; i < X->n; i++) {
509 for (size_t j = 0; j < biL; j++, count++) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200510 if (((X->p[i] >> j) & 1) != 0) {
511 return count;
512 }
513 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200514 }
Tom Van Eyckc1633172024-04-09 18:44:13 +0200515#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200516
Jens Wiklander32b31802023-10-06 16:59:46 +0200517 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200518}
519
520/*
521 * Return the number of bits
522 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200523size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200524{
Jens Wiklander32b31802023-10-06 16:59:46 +0200525 return mbedtls_mpi_core_bitlen(X->p, X->n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200526}
527
528/*
529 * Return the total size in bytes
530 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200531size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200532{
Jens Wiklander32b31802023-10-06 16:59:46 +0200533 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Jens Wiklander817466c2018-05-22 13:49:31 +0200534}
535
536/*
537 * Convert an ASCII character to digit value
538 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200539static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Jens Wiklander817466c2018-05-22 13:49:31 +0200540{
541 *d = 255;
542
Jens Wiklander32b31802023-10-06 16:59:46 +0200543 if (c >= 0x30 && c <= 0x39) {
544 *d = c - 0x30;
545 }
546 if (c >= 0x41 && c <= 0x46) {
547 *d = c - 0x37;
548 }
549 if (c >= 0x61 && c <= 0x66) {
550 *d = c - 0x57;
551 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200552
Jens Wiklander32b31802023-10-06 16:59:46 +0200553 if (*d >= (mbedtls_mpi_uint) radix) {
554 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
555 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200556
Jens Wiklander32b31802023-10-06 16:59:46 +0200557 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200558}
559
560/*
561 * Import from an ASCII string
562 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200563int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Jens Wiklander817466c2018-05-22 13:49:31 +0200564{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200565 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200566 size_t i, j, slen, n;
Jerome Forissier79013242021-07-28 10:24:04 +0200567 int sign = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +0200568 mbedtls_mpi_uint d;
569 mbedtls_mpi T;
570
Jens Wiklander32b31802023-10-06 16:59:46 +0200571 if (radix < 2 || radix > 16) {
572 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jerome Forissier79013242021-07-28 10:24:04 +0200573 }
574
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100575 mbedtls_mpi_init_mempool(&T);
Jens Wiklander32b31802023-10-06 16:59:46 +0200576
577 if (s[0] == 0) {
578 mbedtls_mpi_free(X);
579 return 0;
580 }
581
582 if (s[0] == '-') {
Jerome Forissier79013242021-07-28 10:24:04 +0200583 ++s;
584 sign = -1;
585 }
586
Jens Wiklander32b31802023-10-06 16:59:46 +0200587 slen = strlen(s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200588
Jens Wiklander32b31802023-10-06 16:59:46 +0200589 if (radix == 16) {
Tom Van Eyckc1633172024-04-09 18:44:13 +0200590 if (slen > SIZE_MAX >> 2) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200591 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200592 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200593
Jens Wiklander32b31802023-10-06 16:59:46 +0200594 n = BITS_TO_LIMBS(slen << 2);
595
596 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
597 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
598
599 for (i = slen, j = 0; i > 0; i--, j++) {
600 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
601 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
602 }
603 } else {
604 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
605
606 for (i = 0; i < slen; i++) {
607 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
608 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
609 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Jens Wiklander817466c2018-05-22 13:49:31 +0200610 }
611 }
612
Jens Wiklander32b31802023-10-06 16:59:46 +0200613 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200614 X->s = -1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200615 }
Jerome Forissier79013242021-07-28 10:24:04 +0200616
Jens Wiklander817466c2018-05-22 13:49:31 +0200617cleanup:
618
Jens Wiklander32b31802023-10-06 16:59:46 +0200619 mbedtls_mpi_free(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200620
Jens Wiklander32b31802023-10-06 16:59:46 +0200621 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200622}
623
624/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200625 * Helper to write the digits high-order first.
Jens Wiklander817466c2018-05-22 13:49:31 +0200626 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200627static int mpi_write_hlp(mbedtls_mpi *X, int radix,
628 char **p, const size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200629{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200630 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200631 mbedtls_mpi_uint r;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200632 size_t length = 0;
633 char *p_end = *p + buflen;
Jens Wiklander817466c2018-05-22 13:49:31 +0200634
Jens Wiklander32b31802023-10-06 16:59:46 +0200635 do {
636 if (length >= buflen) {
637 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200638 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200639
Jens Wiklander32b31802023-10-06 16:59:46 +0200640 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
641 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Jerome Forissier5b25c762020-04-07 11:18:49 +0200642 /*
643 * Write the residue in the current position, as an ASCII character.
644 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200645 if (r < 0xA) {
646 *(--p_end) = (char) ('0' + r);
647 } else {
648 *(--p_end) = (char) ('A' + (r - 0xA));
649 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200650
Jerome Forissier5b25c762020-04-07 11:18:49 +0200651 length++;
Jens Wiklander32b31802023-10-06 16:59:46 +0200652 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200653
Jens Wiklander32b31802023-10-06 16:59:46 +0200654 memmove(*p, p_end, length);
Jerome Forissier5b25c762020-04-07 11:18:49 +0200655 *p += length;
Jens Wiklander817466c2018-05-22 13:49:31 +0200656
657cleanup:
658
Jens Wiklander32b31802023-10-06 16:59:46 +0200659 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200660}
661
662/*
663 * Export into an ASCII string
664 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200665int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
666 char *buf, size_t buflen, size_t *olen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200667{
668 int ret = 0;
669 size_t n;
670 char *p;
671 mbedtls_mpi T;
672
Jens Wiklander32b31802023-10-06 16:59:46 +0200673 if (radix < 2 || radix > 16) {
674 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
675 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200676
Jens Wiklander32b31802023-10-06 16:59:46 +0200677 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
678 if (radix >= 4) {
679 n >>= 1; /* Number of 4-adic digits necessary to present
Jerome Forissier5b25c762020-04-07 11:18:49 +0200680 * `n`. If radix > 4, this might be a strict
681 * overapproximation of the number of
682 * radix-adic digits needed to present `n`. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200683 }
684 if (radix >= 16) {
685 n >>= 1; /* Number of hexadecimal digits necessary to
Jerome Forissier5b25c762020-04-07 11:18:49 +0200686 * present `n`. */
687
Jens Wiklander32b31802023-10-06 16:59:46 +0200688 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200689 n += 1; /* Terminating null byte */
690 n += 1; /* Compensate for the divisions above, which round down `n`
691 * in case it's not even. */
692 n += 1; /* Potential '-'-sign. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200693 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200694 * which always uses an even number of hex-digits. */
Jens Wiklander817466c2018-05-22 13:49:31 +0200695
Jens Wiklander32b31802023-10-06 16:59:46 +0200696 if (buflen < n) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200697 *olen = n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200698 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200699 }
700
701 p = buf;
Jens Wiklander8eaf6922018-11-08 11:18:22 +0100702 mbedtls_mpi_init_mempool(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200703
Jens Wiklander32b31802023-10-06 16:59:46 +0200704 if (X->s == -1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200705 *p++ = '-';
Jerome Forissier5b25c762020-04-07 11:18:49 +0200706 buflen--;
707 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200708
Jens Wiklander32b31802023-10-06 16:59:46 +0200709 if (radix == 16) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200710 int c;
711 size_t i, j, k;
712
Jens Wiklander32b31802023-10-06 16:59:46 +0200713 for (i = X->n, k = 0; i > 0; i--) {
714 for (j = ciL; j > 0; j--) {
715 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Jens Wiklander817466c2018-05-22 13:49:31 +0200716
Jens Wiklander32b31802023-10-06 16:59:46 +0200717 if (c == 0 && k == 0 && (i + j) != 2) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200718 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +0200719 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200720
721 *(p++) = "0123456789ABCDEF" [c / 16];
722 *(p++) = "0123456789ABCDEF" [c % 16];
723 k = 1;
724 }
725 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200726 } else {
727 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +0200728
Jens Wiklander32b31802023-10-06 16:59:46 +0200729 if (T.s == -1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200730 T.s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200731 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200732
Jens Wiklander32b31802023-10-06 16:59:46 +0200733 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200734 }
735
736 *p++ = '\0';
Tom Van Eyckc1633172024-04-09 18:44:13 +0200737 *olen = (size_t) (p - buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200738
739cleanup:
740
Jens Wiklander32b31802023-10-06 16:59:46 +0200741 mbedtls_mpi_free(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200742
Jens Wiklander32b31802023-10-06 16:59:46 +0200743 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200744}
745
746#if defined(MBEDTLS_FS_IO)
747/*
748 * Read X from an opened file
749 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200750int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Jens Wiklander817466c2018-05-22 13:49:31 +0200751{
752 mbedtls_mpi_uint d;
753 size_t slen;
754 char *p;
755 /*
756 * Buffer should have space for (short) label and decimal formatted MPI,
757 * newline characters and '\0'
758 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200759 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200760
Jens Wiklander32b31802023-10-06 16:59:46 +0200761 if (radix < 2 || radix > 16) {
762 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
763 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100764
Jens Wiklander32b31802023-10-06 16:59:46 +0200765 memset(s, 0, sizeof(s));
766 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
767 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
768 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200769
Jens Wiklander32b31802023-10-06 16:59:46 +0200770 slen = strlen(s);
771 if (slen == sizeof(s) - 2) {
772 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
773 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200774
Jens Wiklander32b31802023-10-06 16:59:46 +0200775 if (slen > 0 && s[slen - 1] == '\n') {
776 slen--; s[slen] = '\0';
777 }
778 if (slen > 0 && s[slen - 1] == '\r') {
779 slen--; s[slen] = '\0';
780 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200781
782 p = s + slen;
Jens Wiklander32b31802023-10-06 16:59:46 +0200783 while (p-- > s) {
784 if (mpi_get_digit(&d, radix, *p) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200785 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200786 }
787 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200788
Jens Wiklander32b31802023-10-06 16:59:46 +0200789 return mbedtls_mpi_read_string(X, radix, p + 1);
Jens Wiklander817466c2018-05-22 13:49:31 +0200790}
791
792/*
793 * Write X into an opened file (or stdout if fout == NULL)
794 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200795int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Jens Wiklander817466c2018-05-22 13:49:31 +0200796{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200797 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200798 size_t n, slen, plen;
799 /*
800 * Buffer should have space for (short) label and decimal formatted MPI,
801 * newline characters and '\0'
802 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200803 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100804
Jens Wiklander32b31802023-10-06 16:59:46 +0200805 if (radix < 2 || radix > 16) {
806 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
807 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200808
Jens Wiklander32b31802023-10-06 16:59:46 +0200809 memset(s, 0, sizeof(s));
Jens Wiklander817466c2018-05-22 13:49:31 +0200810
Jens Wiklander32b31802023-10-06 16:59:46 +0200811 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Jens Wiklander817466c2018-05-22 13:49:31 +0200812
Jens Wiklander32b31802023-10-06 16:59:46 +0200813 if (p == NULL) {
814 p = "";
815 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200816
Jens Wiklander32b31802023-10-06 16:59:46 +0200817 plen = strlen(p);
818 slen = strlen(s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200819 s[slen++] = '\r';
820 s[slen++] = '\n';
821
Jens Wiklander32b31802023-10-06 16:59:46 +0200822 if (fout != NULL) {
823 if (fwrite(p, 1, plen, fout) != plen ||
824 fwrite(s, 1, slen, fout) != slen) {
825 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
826 }
827 } else {
828 mbedtls_printf("%s%s", p, s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200829 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200830
831cleanup:
832
Jens Wiklander32b31802023-10-06 16:59:46 +0200833 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200834}
835#endif /* MBEDTLS_FS_IO */
836
837/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200838 * Import X from unsigned binary data, little endian
Jens Wiklander32b31802023-10-06 16:59:46 +0200839 *
840 * This function is guaranteed to return an MPI with exactly the necessary
841 * number of limbs (in particular, it does not skip 0s in the input).
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200842 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200843int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
844 const unsigned char *buf, size_t buflen)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200845{
846 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200847 const size_t limbs = CHARS_TO_LIMBS(buflen);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200848
849 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +0200850 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200851
Jens Wiklander32b31802023-10-06 16:59:46 +0200852 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200853
854cleanup:
855
856 /*
857 * This function is also used to import keys. However, wiping the buffers
858 * upon failure is not necessary because failure only can happen before any
859 * input is copied.
860 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200861 return ret;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200862}
863
864/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200865 * Import X from unsigned binary data, big endian
Jens Wiklander32b31802023-10-06 16:59:46 +0200866 *
867 * This function is guaranteed to return an MPI with exactly the necessary
868 * number of limbs (in particular, it does not skip 0s in the input).
Jens Wiklander817466c2018-05-22 13:49:31 +0200869 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200870int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200871{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200872 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200873 const size_t limbs = CHARS_TO_LIMBS(buflen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200874
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100875 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +0200876 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Jens Wiklander29762732019-04-17 12:28:43 +0200877
Jens Wiklander32b31802023-10-06 16:59:46 +0200878 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200879
880cleanup:
881
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200882 /*
883 * This function is also used to import keys. However, wiping the buffers
884 * upon failure is not necessary because failure only can happen before any
885 * input is copied.
886 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200887 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200888}
889
890/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200891 * Export X into unsigned binary data, little endian
892 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200893int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
894 unsigned char *buf, size_t buflen)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200895{
Jens Wiklander32b31802023-10-06 16:59:46 +0200896 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200897}
898
899/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200900 * Export X into unsigned binary data, big endian
901 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200902int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
903 unsigned char *buf, size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200904{
Jens Wiklander32b31802023-10-06 16:59:46 +0200905 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200906}
907
908/*
909 * Left-shift: X <<= count
910 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200911int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Jens Wiklander817466c2018-05-22 13:49:31 +0200912{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200913 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200914 size_t i;
Jens Wiklander817466c2018-05-22 13:49:31 +0200915
Jens Wiklander32b31802023-10-06 16:59:46 +0200916 i = mbedtls_mpi_bitlen(X) + count;
Jens Wiklander817466c2018-05-22 13:49:31 +0200917
Jens Wiklander32b31802023-10-06 16:59:46 +0200918 if (X->n * biL < i) {
919 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
920 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200921
922 ret = 0;
923
Tom Van Eyckc1633172024-04-09 18:44:13 +0200924 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Jens Wiklander817466c2018-05-22 13:49:31 +0200925cleanup:
926
Jens Wiklander32b31802023-10-06 16:59:46 +0200927 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200928}
929
930/*
931 * Right-shift: X >>= count
932 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200933int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Jens Wiklander817466c2018-05-22 13:49:31 +0200934{
Jens Wiklander32b31802023-10-06 16:59:46 +0200935 if (X->n != 0) {
936 mbedtls_mpi_core_shift_r(X->p, X->n, count);
Jens Wiklander817466c2018-05-22 13:49:31 +0200937 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200938 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200939}
940
941/*
942 * Compare unsigned values
943 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200944int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200945{
946 size_t i, j;
947
Jens Wiklander32b31802023-10-06 16:59:46 +0200948 for (i = X->n; i > 0; i--) {
949 if (X->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200950 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200951 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200952 }
953
Jens Wiklander32b31802023-10-06 16:59:46 +0200954 for (j = Y->n; j > 0; j--) {
955 if (Y->p[j - 1] != 0) {
956 break;
957 }
958 }
959
Tom Van Eyckc1633172024-04-09 18:44:13 +0200960 /* If i == j == 0, i.e. abs(X) == abs(Y),
961 * we end up returning 0 at the end of the function. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200962
963 if (i > j) {
964 return 1;
965 }
966 if (j > i) {
967 return -1;
968 }
969
970 for (; i > 0; i--) {
971 if (X->p[i - 1] > Y->p[i - 1]) {
972 return 1;
973 }
974 if (X->p[i - 1] < Y->p[i - 1]) {
975 return -1;
976 }
977 }
978
979 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200980}
981
982/*
983 * Compare signed values
984 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200985int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200986{
987 size_t i, j;
988
Jens Wiklander32b31802023-10-06 16:59:46 +0200989 for (i = X->n; i > 0; i--) {
990 if (X->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200991 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200992 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200993 }
994
Jens Wiklander32b31802023-10-06 16:59:46 +0200995 for (j = Y->n; j > 0; j--) {
996 if (Y->p[j - 1] != 0) {
997 break;
998 }
999 }
1000
1001 if (i == 0 && j == 0) {
1002 return 0;
1003 }
1004
1005 if (i > j) {
1006 return X->s;
1007 }
1008 if (j > i) {
1009 return -Y->s;
1010 }
1011
1012 if (X->s > 0 && Y->s < 0) {
1013 return 1;
1014 }
1015 if (Y->s > 0 && X->s < 0) {
1016 return -1;
1017 }
1018
1019 for (; i > 0; i--) {
1020 if (X->p[i - 1] > Y->p[i - 1]) {
1021 return X->s;
1022 }
1023 if (X->p[i - 1] < Y->p[i - 1]) {
1024 return -X->s;
1025 }
1026 }
1027
1028 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001029}
1030
1031/*
1032 * Compare signed values
1033 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001034int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Jens Wiklander817466c2018-05-22 13:49:31 +02001035{
1036 mbedtls_mpi Y;
1037 mbedtls_mpi_uint p[1];
1038
Jens Wiklander32b31802023-10-06 16:59:46 +02001039 *p = mpi_sint_abs(z);
Tom Van Eyckc1633172024-04-09 18:44:13 +02001040 Y.s = TO_SIGN(z);
Jens Wiklander817466c2018-05-22 13:49:31 +02001041 Y.n = 1;
1042 Y.p = p;
1043
Jens Wiklander32b31802023-10-06 16:59:46 +02001044 return mbedtls_mpi_cmp_mpi(X, &Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02001045}
1046
1047/*
1048 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1049 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001050int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001051{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001052 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001053 size_t j;
Tom Van Eyckc1633172024-04-09 18:44:13 +02001054 mbedtls_mpi_uint *p;
1055 mbedtls_mpi_uint c;
Jens Wiklander817466c2018-05-22 13:49:31 +02001056
Jens Wiklander32b31802023-10-06 16:59:46 +02001057 if (X == B) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001058 const mbedtls_mpi *T = A; A = X; B = T;
1059 }
1060
Jens Wiklander32b31802023-10-06 16:59:46 +02001061 if (X != A) {
1062 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1063 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001064
1065 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02001066 * X must always be positive as a result of unsigned additions.
Jens Wiklander817466c2018-05-22 13:49:31 +02001067 */
1068 X->s = 1;
1069
Jens Wiklander32b31802023-10-06 16:59:46 +02001070 for (j = B->n; j > 0; j--) {
1071 if (B->p[j - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001072 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001073 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001074 }
1075
Jens Wiklander32b31802023-10-06 16:59:46 +02001076 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1077 * and B is 0 (of any size). */
1078 if (j == 0) {
1079 return 0;
1080 }
1081
1082 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
1083
1084 /* j is the number of non-zero limbs of B. Add those to X. */
1085
Tom Van Eyckc1633172024-04-09 18:44:13 +02001086 p = X->p;
Jens Wiklander32b31802023-10-06 16:59:46 +02001087
Tom Van Eyckc1633172024-04-09 18:44:13 +02001088 c = mbedtls_mpi_core_add(p, p, B->p, j);
Jens Wiklander32b31802023-10-06 16:59:46 +02001089
1090 p += j;
1091
1092 /* Now propagate any carry */
1093
1094 while (c != 0) {
1095 if (j >= X->n) {
1096 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
1097 p = X->p + j;
Jens Wiklander817466c2018-05-22 13:49:31 +02001098 }
1099
Jens Wiklander32b31802023-10-06 16:59:46 +02001100 *p += c; c = (*p < c); j++; p++;
Jens Wiklander817466c2018-05-22 13:49:31 +02001101 }
1102
1103cleanup:
1104
Jens Wiklander32b31802023-10-06 16:59:46 +02001105 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001106}
1107
1108/*
Jerome Forissier79013242021-07-28 10:24:04 +02001109 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Jens Wiklander817466c2018-05-22 13:49:31 +02001110 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001111int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001112{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001113 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001114 size_t n;
Jerome Forissier79013242021-07-28 10:24:04 +02001115 mbedtls_mpi_uint carry;
Jens Wiklander817466c2018-05-22 13:49:31 +02001116
Jens Wiklander32b31802023-10-06 16:59:46 +02001117 for (n = B->n; n > 0; n--) {
1118 if (B->p[n - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001119 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001120 }
1121 }
1122 if (n > A->n) {
Jerome Forissier79013242021-07-28 10:24:04 +02001123 /* B >= (2^ciL)^n > A */
1124 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1125 goto cleanup;
1126 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001127
Jens Wiklander32b31802023-10-06 16:59:46 +02001128 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Jerome Forissier79013242021-07-28 10:24:04 +02001129
1130 /* Set the high limbs of X to match A. Don't touch the lower limbs
1131 * because X might be aliased to B, and we must not overwrite the
1132 * significant digits of B. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001133 if (A->n > n && A != X) {
1134 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1135 }
1136 if (X->n > A->n) {
1137 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1138 }
Jerome Forissier79013242021-07-28 10:24:04 +02001139
Jens Wiklander32b31802023-10-06 16:59:46 +02001140 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1141 if (carry != 0) {
1142 /* Propagate the carry through the rest of X. */
1143 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
1144
1145 /* If we have further carry/borrow, the result is negative. */
1146 if (carry != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001147 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1148 goto cleanup;
1149 }
Jerome Forissier79013242021-07-28 10:24:04 +02001150 }
1151
1152 /* X should always be positive as a result of unsigned subtractions. */
1153 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001154
1155cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001156 return ret;
1157}
1158
1159/* Common function for signed addition and subtraction.
1160 * Calculate A + B * flip_B where flip_B is 1 or -1.
1161 */
1162static int add_sub_mpi(mbedtls_mpi *X,
1163 const mbedtls_mpi *A, const mbedtls_mpi *B,
1164 int flip_B)
1165{
1166 int ret, s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001167
1168 s = A->s;
1169 if (A->s * B->s * flip_B < 0) {
1170 int cmp = mbedtls_mpi_cmp_abs(A, B);
1171 if (cmp >= 0) {
1172 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
1173 /* If |A| = |B|, the result is 0 and we must set the sign bit
1174 * to +1 regardless of which of A or B was negative. Otherwise,
1175 * since |A| > |B|, the sign is the sign of A. */
1176 X->s = cmp == 0 ? 1 : s;
1177 } else {
1178 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
1179 /* Since |A| < |B|, the sign is the opposite of A. */
1180 X->s = -s;
1181 }
1182 } else {
1183 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
1184 X->s = s;
1185 }
1186
1187cleanup:
1188
1189 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001190}
1191
1192/*
1193 * Signed addition: X = A + B
1194 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001195int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001196{
Jens Wiklander32b31802023-10-06 16:59:46 +02001197 return add_sub_mpi(X, A, B, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001198}
1199
1200/*
1201 * Signed subtraction: X = A - B
1202 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001203int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001204{
Jens Wiklander32b31802023-10-06 16:59:46 +02001205 return add_sub_mpi(X, A, B, -1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001206}
1207
1208/*
1209 * Signed addition: X = A + b
1210 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001211int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001212{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001213 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001214 mbedtls_mpi_uint p[1];
1215
Jens Wiklander32b31802023-10-06 16:59:46 +02001216 p[0] = mpi_sint_abs(b);
Tom Van Eyckc1633172024-04-09 18:44:13 +02001217 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001218 B.n = 1;
1219 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001220
Jens Wiklander32b31802023-10-06 16:59:46 +02001221 return mbedtls_mpi_add_mpi(X, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001222}
1223
1224/*
1225 * Signed subtraction: X = A - b
1226 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001227int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001228{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001229 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001230 mbedtls_mpi_uint p[1];
1231
Jens Wiklander32b31802023-10-06 16:59:46 +02001232 p[0] = mpi_sint_abs(b);
Tom Van Eyckc1633172024-04-09 18:44:13 +02001233 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001234 B.n = 1;
1235 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001236
Jens Wiklander32b31802023-10-06 16:59:46 +02001237 return mbedtls_mpi_sub_mpi(X, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001238}
1239
1240/*
1241 * Baseline multiplication: X = A * B (HAC 14.12)
1242 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001243int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001244{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001245 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001246 size_t i, j;
1247 mbedtls_mpi TA, TB;
Jerome Forissier79013242021-07-28 10:24:04 +02001248 int result_is_zero = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001249
Jens Wiklander8eaf6922018-11-08 11:18:22 +01001250 mbedtls_mpi_init_mempool(&TA);
1251 mbedtls_mpi_init_mempool(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001252
Jens Wiklander32b31802023-10-06 16:59:46 +02001253 if (X == A) {
1254 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1255 }
1256 if (X == B) {
1257 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1258 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001259
Jens Wiklander32b31802023-10-06 16:59:46 +02001260 for (i = A->n; i > 0; i--) {
1261 if (A->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001262 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001263 }
1264 }
1265 if (i == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001266 result_is_zero = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001267 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001268
Jens Wiklander32b31802023-10-06 16:59:46 +02001269 for (j = B->n; j > 0; j--) {
1270 if (B->p[j - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001271 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001272 }
1273 }
1274 if (j == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001275 result_is_zero = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001276 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001277
Jens Wiklander32b31802023-10-06 16:59:46 +02001278 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1279 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Jens Wiklander817466c2018-05-22 13:49:31 +02001280
Tom Van Eyckc1633172024-04-09 18:44:13 +02001281 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Jens Wiklander817466c2018-05-22 13:49:31 +02001282
Jerome Forissier79013242021-07-28 10:24:04 +02001283 /* If the result is 0, we don't shortcut the operation, which reduces
1284 * but does not eliminate side channels leaking the zero-ness. We do
1285 * need to take care to set the sign bit properly since the library does
1286 * not fully support an MPI object with a value of 0 and s == -1. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001287 if (result_is_zero) {
Jerome Forissier79013242021-07-28 10:24:04 +02001288 X->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001289 } else {
Jerome Forissier79013242021-07-28 10:24:04 +02001290 X->s = A->s * B->s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001291 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001292
1293cleanup:
1294
Jens Wiklander32b31802023-10-06 16:59:46 +02001295 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Jens Wiklander817466c2018-05-22 13:49:31 +02001296
Jens Wiklander32b31802023-10-06 16:59:46 +02001297 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001298}
1299
1300/*
1301 * Baseline multiplication: X = A * b
1302 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001303int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001304{
Jerome Forissier79013242021-07-28 10:24:04 +02001305 size_t n = A->n;
Jens Wiklander32b31802023-10-06 16:59:46 +02001306 while (n > 0 && A->p[n - 1] == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001307 --n;
Jerome Forissier79013242021-07-28 10:24:04 +02001308 }
1309
Jens Wiklander32b31802023-10-06 16:59:46 +02001310 /* The general method below doesn't work if b==0. */
1311 if (b == 0 || n == 0) {
1312 return mbedtls_mpi_lset(X, 0);
1313 }
1314
1315 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Jerome Forissier79013242021-07-28 10:24:04 +02001316 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1317 /* In general, A * b requires 1 limb more than b. If
1318 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1319 * number of limbs as A and the call to grow() is not required since
1320 * copy() will take care of the growth if needed. However, experimentally,
1321 * making the call to grow() unconditional causes slightly fewer
1322 * calls to calloc() in ECP code, presumably because it reuses the
1323 * same mpi for a while and this way the mpi is more likely to directly
Jens Wiklander32b31802023-10-06 16:59:46 +02001324 * grow to its final size.
1325 *
1326 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1327 * A,X can be the same. */
1328 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1329 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1330 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Jerome Forissier79013242021-07-28 10:24:04 +02001331
1332cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001333 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001334}
1335
1336/*
1337 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1338 * mbedtls_mpi_uint divisor, d
1339 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001340static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1341 mbedtls_mpi_uint u0,
1342 mbedtls_mpi_uint d,
1343 mbedtls_mpi_uint *r)
Jens Wiklander817466c2018-05-22 13:49:31 +02001344{
1345#if defined(MBEDTLS_HAVE_UDBL)
1346 mbedtls_t_udbl dividend, quotient;
1347#else
1348 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Jens Wiklander32b31802023-10-06 16:59:46 +02001349 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001350 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1351 mbedtls_mpi_uint u0_msw, u0_lsw;
1352 size_t s;
1353#endif
1354
1355 /*
1356 * Check for overflow
1357 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001358 if (0 == d || u1 >= d) {
1359 if (r != NULL) {
1360 *r = ~(mbedtls_mpi_uint) 0u;
1361 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001362
Jens Wiklander32b31802023-10-06 16:59:46 +02001363 return ~(mbedtls_mpi_uint) 0u;
Jens Wiklander817466c2018-05-22 13:49:31 +02001364 }
1365
1366#if defined(MBEDTLS_HAVE_UDBL)
1367 dividend = (mbedtls_t_udbl) u1 << biL;
1368 dividend |= (mbedtls_t_udbl) u0;
1369 quotient = dividend / d;
Jens Wiklander32b31802023-10-06 16:59:46 +02001370 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1371 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1372 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001373
Jens Wiklander32b31802023-10-06 16:59:46 +02001374 if (r != NULL) {
1375 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1376 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001377
1378 return (mbedtls_mpi_uint) quotient;
1379#else
1380
1381 /*
1382 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1383 * Vol. 2 - Seminumerical Algorithms, Knuth
1384 */
1385
1386 /*
1387 * Normalize the divisor, d, and dividend, u0, u1
1388 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001389 s = mbedtls_mpi_core_clz(d);
Jens Wiklander817466c2018-05-22 13:49:31 +02001390 d = d << s;
1391
1392 u1 = u1 << s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001393 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001394 u0 = u0 << s;
1395
1396 d1 = d >> biH;
1397 d0 = d & uint_halfword_mask;
1398
1399 u0_msw = u0 >> biH;
1400 u0_lsw = u0 & uint_halfword_mask;
1401
1402 /*
1403 * Find the first quotient and remainder
1404 */
1405 q1 = u1 / d1;
1406 r0 = u1 - d1 * q1;
1407
Jens Wiklander32b31802023-10-06 16:59:46 +02001408 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001409 q1 -= 1;
1410 r0 += d1;
1411
Jens Wiklander32b31802023-10-06 16:59:46 +02001412 if (r0 >= radix) {
1413 break;
1414 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001415 }
1416
Jens Wiklander32b31802023-10-06 16:59:46 +02001417 rAX = (u1 * radix) + (u0_msw - q1 * d);
Jens Wiklander817466c2018-05-22 13:49:31 +02001418 q0 = rAX / d1;
1419 r0 = rAX - q0 * d1;
1420
Jens Wiklander32b31802023-10-06 16:59:46 +02001421 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001422 q0 -= 1;
1423 r0 += d1;
1424
Jens Wiklander32b31802023-10-06 16:59:46 +02001425 if (r0 >= radix) {
1426 break;
1427 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001428 }
1429
Jens Wiklander32b31802023-10-06 16:59:46 +02001430 if (r != NULL) {
1431 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1432 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001433
1434 quotient = q1 * radix + q0;
1435
1436 return quotient;
1437#endif
1438}
1439
1440/*
1441 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
1442 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001443int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1444 const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001445{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001446 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001447 size_t i, n, t, k;
1448 mbedtls_mpi X, Y, Z, T1, T2;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001449 mbedtls_mpi_uint TP2[3];
Jens Wiklander817466c2018-05-22 13:49:31 +02001450
Jens Wiklander32b31802023-10-06 16:59:46 +02001451 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1452 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1453 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001454
Jens Wiklander8eaf6922018-11-08 11:18:22 +01001455 mbedtls_mpi_init_mempool(&X); mbedtls_mpi_init_mempool(&Y);
1456 mbedtls_mpi_init_mempool(&Z); mbedtls_mpi_init_mempool(&T1);
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001457 /*
1458 * Avoid dynamic memory allocations for constant-size T2.
1459 *
1460 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1461 * so nobody increase the size of the MPI and we're safe to use an on-stack
1462 * buffer.
1463 */
1464 T2.s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001465 T2.n = sizeof(TP2) / sizeof(*TP2);
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001466 T2.p = TP2;
Jens Wiklander817466c2018-05-22 13:49:31 +02001467
Jens Wiklander32b31802023-10-06 16:59:46 +02001468 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1469 if (Q != NULL) {
1470 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1471 }
1472 if (R != NULL) {
1473 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1474 }
1475 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001476 }
1477
Jens Wiklander32b31802023-10-06 16:59:46 +02001478 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1479 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001480 X.s = Y.s = 1;
1481
Jens Wiklander32b31802023-10-06 16:59:46 +02001482 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1483 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1484 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Jens Wiklander817466c2018-05-22 13:49:31 +02001485
Jens Wiklander32b31802023-10-06 16:59:46 +02001486 k = mbedtls_mpi_bitlen(&Y) % biL;
1487 if (k < biL - 1) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001488 k = biL - 1 - k;
Jens Wiklander32b31802023-10-06 16:59:46 +02001489 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1490 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1491 } else {
1492 k = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001493 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001494
1495 n = X.n - 1;
1496 t = Y.n - 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001497 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001498
Jens Wiklander32b31802023-10-06 16:59:46 +02001499 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001500 Z.p[n - t]++;
Jens Wiklander32b31802023-10-06 16:59:46 +02001501 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02001502 }
Jens Wiklander32b31802023-10-06 16:59:46 +02001503 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001504
Jens Wiklander32b31802023-10-06 16:59:46 +02001505 for (i = n; i > t; i--) {
1506 if (X.p[i] >= Y.p[t]) {
1507 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1508 } else {
1509 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1510 Y.p[t], NULL);
Jens Wiklander817466c2018-05-22 13:49:31 +02001511 }
1512
Jens Wiklander32b31802023-10-06 16:59:46 +02001513 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1514 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001515 T2.p[2] = X.p[i];
1516
Jens Wiklander817466c2018-05-22 13:49:31 +02001517 Z.p[i - t - 1]++;
Jens Wiklander32b31802023-10-06 16:59:46 +02001518 do {
Jens Wiklander817466c2018-05-22 13:49:31 +02001519 Z.p[i - t - 1]--;
1520
Jens Wiklander32b31802023-10-06 16:59:46 +02001521 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1522 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Jens Wiklander817466c2018-05-22 13:49:31 +02001523 T1.p[1] = Y.p[t];
Jens Wiklander32b31802023-10-06 16:59:46 +02001524 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1525 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001526
Jens Wiklander32b31802023-10-06 16:59:46 +02001527 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1528 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1529 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001530
Jens Wiklander32b31802023-10-06 16:59:46 +02001531 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1532 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1533 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1534 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001535 Z.p[i - t - 1]--;
1536 }
1537 }
1538
Jens Wiklander32b31802023-10-06 16:59:46 +02001539 if (Q != NULL) {
1540 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Jens Wiklander817466c2018-05-22 13:49:31 +02001541 Q->s = A->s * B->s;
1542 }
1543
Jens Wiklander32b31802023-10-06 16:59:46 +02001544 if (R != NULL) {
1545 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Jens Wiklander817466c2018-05-22 13:49:31 +02001546 X.s = A->s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001547 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001548
Jens Wiklander32b31802023-10-06 16:59:46 +02001549 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001550 R->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001551 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001552 }
1553
1554cleanup:
1555
Jens Wiklander32b31802023-10-06 16:59:46 +02001556 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1557 mbedtls_mpi_free(&T1);
1558 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Jens Wiklander817466c2018-05-22 13:49:31 +02001559
Jens Wiklander32b31802023-10-06 16:59:46 +02001560 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001561}
1562
1563/*
1564 * Division by int: A = Q * b + R
1565 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001566int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1567 const mbedtls_mpi *A,
1568 mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001569{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001570 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001571 mbedtls_mpi_uint p[1];
1572
Jens Wiklander32b31802023-10-06 16:59:46 +02001573 p[0] = mpi_sint_abs(b);
Tom Van Eyckc1633172024-04-09 18:44:13 +02001574 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001575 B.n = 1;
1576 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001577
Jens Wiklander32b31802023-10-06 16:59:46 +02001578 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001579}
1580
1581/*
1582 * Modulo: R = A mod B
1583 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001584int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001585{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001586 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001587
Jens Wiklander32b31802023-10-06 16:59:46 +02001588 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1589 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1590 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001591
Jens Wiklander32b31802023-10-06 16:59:46 +02001592 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001593
Jens Wiklander32b31802023-10-06 16:59:46 +02001594 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1595 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1596 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001597
Jens Wiklander32b31802023-10-06 16:59:46 +02001598 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1599 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1600 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001601
1602cleanup:
1603
Jens Wiklander32b31802023-10-06 16:59:46 +02001604 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001605}
1606
1607/*
1608 * Modulo: r = A mod b
1609 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001610int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001611{
1612 size_t i;
1613 mbedtls_mpi_uint x, y, z;
1614
Jens Wiklander32b31802023-10-06 16:59:46 +02001615 if (b == 0) {
1616 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1617 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001618
Jens Wiklander32b31802023-10-06 16:59:46 +02001619 if (b < 0) {
1620 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1621 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001622
1623 /*
1624 * handle trivial cases
1625 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001626 if (b == 1 || A->n == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001627 *r = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +02001628 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001629 }
1630
Jens Wiklander32b31802023-10-06 16:59:46 +02001631 if (b == 2) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001632 *r = A->p[0] & 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001633 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001634 }
1635
1636 /*
1637 * general case
1638 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001639 for (i = A->n, y = 0; i > 0; i--) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001640 x = A->p[i - 1];
Jens Wiklander32b31802023-10-06 16:59:46 +02001641 y = (y << biH) | (x >> biH);
Jens Wiklander817466c2018-05-22 13:49:31 +02001642 z = y / b;
1643 y -= z * b;
1644
1645 x <<= biH;
Jens Wiklander32b31802023-10-06 16:59:46 +02001646 y = (y << biH) | (x >> biH);
Jens Wiklander817466c2018-05-22 13:49:31 +02001647 z = y / b;
1648 y -= z * b;
1649 }
1650
1651 /*
1652 * If A is negative, then the current y represents a negative value.
1653 * Flipping it to the positive side.
1654 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001655 if (A->s < 0 && y != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001656 y = b - y;
Jens Wiklander32b31802023-10-06 16:59:46 +02001657 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001658
1659 *r = y;
1660
Jens Wiklander32b31802023-10-06 16:59:46 +02001661 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001662}
1663
Jens Wiklander12e83fc2018-11-07 08:11:29 +01001664/**
1665 * \remark Replaced by our own because the original has been removed since
1666 * mbedtls v3.6.0.
1667*/
1668void mbedtls_mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
1669{
1670 *mm = mbedtls_mpi_core_montmul_init(N->p);
1671}
1672
1673/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1674 *
1675 * \param[in,out] A One of the numbers to multiply.
1676 * It must have at least as many limbs as N
1677 * (A->n >= N->n), and any limbs beyond n are ignored.
1678 * On successful completion, A contains the result of
1679 * the multiplication A * B * R^-1 mod N where
1680 * R = (2^ciL)^n.
1681 * \param[in] B One of the numbers to multiply.
1682 * It must be nonzero and must not have more limbs than N
1683 * (B->n <= N->n).
1684 * \param[in] N The modulus. \p N must be odd.
1685 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1686 * This is -N^-1 mod 2^ciL.
1687 * \param[in,out] T A bignum for temporary storage.
1688 * It must be at least twice the limb size of N plus 1
1689 * (T->n >= 2 * N->n + 1).
1690 * Its initial content is unused and
1691 * its final content is indeterminate.
1692 * It does not get reallocated.
1693 * \remark Replaced by our own because the original has been removed since
1694 * mbedtls v3.6.0.
1695 */
1696void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1697 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1698 mbedtls_mpi *T)
1699{
1700 mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
1701}
1702
1703/**
1704 * Montgomery reduction: A = A * R^-1 mod N
1705 *
1706 * See mbedtls_mpi_montmul() regarding constraints and guarantees on the parameters.
1707 *
1708 * \remark Replaced by our own because the original has been removed since
1709 * mbedtls v3.6.0.
1710 */
1711void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1712 mbedtls_mpi_uint mm, mbedtls_mpi *T)
1713{
1714 mbedtls_mpi_uint z = 1;
1715 mbedtls_mpi U;
1716
1717 U.n = U.s = (int) z;
1718 U.p = &z;
1719
1720 mbedtls_mpi_montmul(A, &U, N, mm, T);
1721}
1722
1723/*
1724 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1725 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001726int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1727 const mbedtls_mpi *E, const mbedtls_mpi *N,
1728 mbedtls_mpi *prec_RR)
Jens Wiklander817466c2018-05-22 13:49:31 +02001729{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001730 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001731
Jens Wiklander32b31802023-10-06 16:59:46 +02001732 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1733 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1734 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001735
Jens Wiklander32b31802023-10-06 16:59:46 +02001736 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1737 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1738 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001739
Jens Wiklander32b31802023-10-06 16:59:46 +02001740 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1741 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1742 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1743 }
Jerome Forissier79013242021-07-28 10:24:04 +02001744
Jens Wiklander817466c2018-05-22 13:49:31 +02001745 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001746 * Ensure that the exponent that we are passing to the core is not NULL.
Jens Wiklander817466c2018-05-22 13:49:31 +02001747 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001748 if (E->n == 0) {
1749 ret = mbedtls_mpi_lset(X, 1);
1750 return ret;
Jens Wiklander32b31802023-10-06 16:59:46 +02001751 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001752
1753 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001754 * Allocate working memory for mbedtls_mpi_core_exp_mod()
Jens Wiklander817466c2018-05-22 13:49:31 +02001755 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001756 size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);
1757 mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint));
1758 if (T == NULL) {
1759 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001760 }
1761
Tom Van Eyckc1633172024-04-09 18:44:13 +02001762 mbedtls_mpi RR;
Jens Wiklander8eaf6922018-11-08 11:18:22 +01001763 mbedtls_mpi_init_mempool(&RR);
Tom Van Eyckc1633172024-04-09 18:44:13 +02001764
Jens Wiklander817466c2018-05-22 13:49:31 +02001765 /*
1766 * If 1st call, pre-compute R^2 mod N
1767 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001768 if (prec_RR == NULL || prec_RR->p == NULL) {
Tom Van Eyckc1633172024-04-09 18:44:13 +02001769 MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001770
Jens Wiklander32b31802023-10-06 16:59:46 +02001771 if (prec_RR != NULL) {
Tom Van Eyckc1633172024-04-09 18:44:13 +02001772 *prec_RR = RR;
Jens Wiklander32b31802023-10-06 16:59:46 +02001773 }
1774 } else {
Tom Van Eyckc1633172024-04-09 18:44:13 +02001775 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
1776 RR = *prec_RR;
Jens Wiklander817466c2018-05-22 13:49:31 +02001777 }
1778
1779 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001780 * To preserve constness we need to make a copy of A. Using X for this to
1781 * save memory.
Jens Wiklander817466c2018-05-22 13:49:31 +02001782 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001783 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
Jens Wiklander817466c2018-05-22 13:49:31 +02001784
Tom Van Eyckc1633172024-04-09 18:44:13 +02001785 /*
1786 * Compensate for negative A (and correct at the end).
1787 */
1788 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001789
Tom Van Eyckc1633172024-04-09 18:44:13 +02001790 /*
1791 * Make sure that X is in a form that is safe for consumption by
1792 * the core functions.
1793 *
1794 * - The core functions will not touch the limbs of X above N->n. The
1795 * result will be correct if those limbs are 0, which the mod call
1796 * ensures.
1797 * - Also, X must have at least as many limbs as N for the calls to the
1798 * core functions.
1799 */
1800 if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
1801 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
1802 }
1803 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
1804
1805 /*
1806 * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
1807 */
1808 {
1809 mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
1810 mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
1811 mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
1812 mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
Jens Wiklander817466c2018-05-22 13:49:31 +02001813 }
1814
1815 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001816 * Correct for negative A.
Jens Wiklander817466c2018-05-22 13:49:31 +02001817 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001818 if (A->s == -1 && (E->p[0] & 1) != 0) {
1819 mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
1820 X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001821
Tom Van Eyckc1633172024-04-09 18:44:13 +02001822 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001823 }
1824
1825cleanup:
1826
Tom Van Eyckc1633172024-04-09 18:44:13 +02001827 mbedtls_mpi_zeroize_and_free(T, T_limbs);
Jens Wiklander817466c2018-05-22 13:49:31 +02001828
Jens Wiklander32b31802023-10-06 16:59:46 +02001829 if (prec_RR == NULL || prec_RR->p == NULL) {
1830 mbedtls_mpi_free(&RR);
1831 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001832
Jens Wiklander32b31802023-10-06 16:59:46 +02001833 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001834}
1835
1836/*
1837 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1838 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001839int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001840{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001841 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001842 size_t lz, lzt;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001843 mbedtls_mpi TA, TB;
Jens Wiklander817466c2018-05-22 13:49:31 +02001844
Jens Wiklander8eaf6922018-11-08 11:18:22 +01001845 mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001846
Jens Wiklander32b31802023-10-06 16:59:46 +02001847 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1848 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001849
Jens Wiklander32b31802023-10-06 16:59:46 +02001850 lz = mbedtls_mpi_lsb(&TA);
1851 lzt = mbedtls_mpi_lsb(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001852
Jerome Forissier79013242021-07-28 10:24:04 +02001853 /* The loop below gives the correct result when A==0 but not when B==0.
1854 * So have a special case for B==0. Leverage the fact that we just
1855 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1856 * slightly more efficient than cmp_int(). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001857 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1858 ret = mbedtls_mpi_copy(G, A);
Jerome Forissier79013242021-07-28 10:24:04 +02001859 goto cleanup;
1860 }
1861
Jens Wiklander32b31802023-10-06 16:59:46 +02001862 if (lzt < lz) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001863 lz = lzt;
Jens Wiklander32b31802023-10-06 16:59:46 +02001864 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001865
Jens Wiklander817466c2018-05-22 13:49:31 +02001866 TA.s = TB.s = 1;
1867
Jerome Forissier79013242021-07-28 10:24:04 +02001868 /* We mostly follow the procedure described in HAC 14.54, but with some
1869 * minor differences:
1870 * - Sequences of multiplications or divisions by 2 are grouped into a
1871 * single shift operation.
1872 * - The procedure in HAC assumes that 0 < TB <= TA.
1873 * - The condition TB <= TA is not actually necessary for correctness.
1874 * TA and TB have symmetric roles except for the loop termination
1875 * condition, and the shifts at the beginning of the loop body
1876 * remove any significance from the ordering of TA vs TB before
1877 * the shifts.
1878 * - If TA = 0, the loop goes through 0 iterations and the result is
1879 * correctly TB.
1880 * - The case TB = 0 was short-circuited above.
1881 *
1882 * For the correctness proof below, decompose the original values of
1883 * A and B as
1884 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1885 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1886 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1887 * and gcd(A',B') is odd or 0.
1888 *
1889 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1890 * The code maintains the following invariant:
1891 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
1892 */
1893
1894 /* Proof that the loop terminates:
1895 * At each iteration, either the right-shift by 1 is made on a nonzero
1896 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
1897 * by at least 1, or the right-shift by 1 is made on zero and then
1898 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
1899 * since in that case TB is calculated from TB-TA with the condition TB>TA).
1900 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001901 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001902 /* Divisions by 2 preserve the invariant (I). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001903 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
1904 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001905
Jerome Forissier79013242021-07-28 10:24:04 +02001906 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
1907 * TA-TB is even so the division by 2 has an integer result.
1908 * Invariant (I) is preserved since any odd divisor of both TA and TB
1909 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Jerome Forissier039e02d2022-08-09 17:10:15 +02001910 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Jerome Forissier79013242021-07-28 10:24:04 +02001911 * divides TA.
1912 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001913 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
1914 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
1915 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
1916 } else {
1917 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
1918 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001919 }
Jerome Forissier79013242021-07-28 10:24:04 +02001920 /* Note that one of TA or TB is still odd. */
Jens Wiklander817466c2018-05-22 13:49:31 +02001921 }
1922
Jerome Forissier79013242021-07-28 10:24:04 +02001923 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
1924 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
1925 * - If there was at least one loop iteration, then one of TA or TB is odd,
1926 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
1927 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
1928 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
1929 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
1930 */
1931
Jens Wiklander32b31802023-10-06 16:59:46 +02001932 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
1933 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Jens Wiklander817466c2018-05-22 13:49:31 +02001934
1935cleanup:
1936
Jens Wiklander32b31802023-10-06 16:59:46 +02001937 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001938
Jens Wiklander32b31802023-10-06 16:59:46 +02001939 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001940}
1941
Jens Wiklander817466c2018-05-22 13:49:31 +02001942/*
1943 * Fill X with size bytes of random.
Jens Wiklander32b31802023-10-06 16:59:46 +02001944 * The bytes returned from the RNG are used in a specific order which
1945 * is suitable for deterministic ECDSA (see the specification of
1946 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Jens Wiklander817466c2018-05-22 13:49:31 +02001947 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001948int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
1949 int (*f_rng)(void *, unsigned char *, size_t),
1950 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02001951{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001952 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001953 const size_t limbs = CHARS_TO_LIMBS(size);
Jerome Forissier5b25c762020-04-07 11:18:49 +02001954
Jerome Forissier5b25c762020-04-07 11:18:49 +02001955 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +02001956 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
1957 if (size == 0) {
1958 return 0;
1959 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001960
Jens Wiklander32b31802023-10-06 16:59:46 +02001961 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02001962
1963cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001964 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001965}
1966
Jens Wiklander32b31802023-10-06 16:59:46 +02001967int mbedtls_mpi_random(mbedtls_mpi *X,
1968 mbedtls_mpi_sint min,
1969 const mbedtls_mpi *N,
1970 int (*f_rng)(void *, unsigned char *, size_t),
1971 void *p_rng)
Jerome Forissier79013242021-07-28 10:24:04 +02001972{
Jens Wiklander32b31802023-10-06 16:59:46 +02001973 if (min < 0) {
1974 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1975 }
1976 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
1977 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1978 }
Jerome Forissier79013242021-07-28 10:24:04 +02001979
1980 /* Ensure that target MPI has exactly the same number of limbs
1981 * as the upper bound, even if the upper bound has leading zeros.
Jens Wiklander32b31802023-10-06 16:59:46 +02001982 * This is necessary for mbedtls_mpi_core_random. */
1983 int ret = mbedtls_mpi_resize_clear(X, N->n);
1984 if (ret != 0) {
1985 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001986 }
Jerome Forissier79013242021-07-28 10:24:04 +02001987
Jens Wiklander32b31802023-10-06 16:59:46 +02001988 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Jerome Forissier79013242021-07-28 10:24:04 +02001989}
1990
Jens Wiklander817466c2018-05-22 13:49:31 +02001991/*
1992 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1993 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001994int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Jens Wiklander817466c2018-05-22 13:49:31 +02001995{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001996 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001997 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1998
Jens Wiklander32b31802023-10-06 16:59:46 +02001999 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2000 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2001 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002002
Jens Wiklander8eaf6922018-11-08 11:18:22 +01002003 mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TU);
2004 mbedtls_mpi_init_mempool(&U1); mbedtls_mpi_init_mempool(&U2);
2005 mbedtls_mpi_init_mempool(&G); mbedtls_mpi_init_mempool(&TB);
2006 mbedtls_mpi_init_mempool(&TV); mbedtls_mpi_init_mempool(&V1);
2007 mbedtls_mpi_init_mempool(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02002008
Jens Wiklander32b31802023-10-06 16:59:46 +02002009 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002010
Jens Wiklander32b31802023-10-06 16:59:46 +02002011 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002012 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2013 goto cleanup;
2014 }
2015
Jens Wiklander32b31802023-10-06 16:59:46 +02002016 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2017 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2018 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2019 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002020
Jens Wiklander32b31802023-10-06 16:59:46 +02002021 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2022 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2023 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2024 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002025
Jens Wiklander32b31802023-10-06 16:59:46 +02002026 do {
2027 while ((TU.p[0] & 1) == 0) {
2028 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002029
Jens Wiklander32b31802023-10-06 16:59:46 +02002030 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2031 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2032 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02002033 }
2034
Jens Wiklander32b31802023-10-06 16:59:46 +02002035 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2036 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002037 }
2038
Jens Wiklander32b31802023-10-06 16:59:46 +02002039 while ((TV.p[0] & 1) == 0) {
2040 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002041
Jens Wiklander32b31802023-10-06 16:59:46 +02002042 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2043 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2044 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02002045 }
2046
Jens Wiklander32b31802023-10-06 16:59:46 +02002047 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2048 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002049 }
2050
Jens Wiklander32b31802023-10-06 16:59:46 +02002051 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2052 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2053 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2054 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2055 } else {
2056 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2057 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2058 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Jens Wiklander817466c2018-05-22 13:49:31 +02002059 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002060 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2061
2062 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2063 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002064 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002065
Jens Wiklander32b31802023-10-06 16:59:46 +02002066 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2067 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2068 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002069
Jens Wiklander32b31802023-10-06 16:59:46 +02002070 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002071
2072cleanup:
2073
Jens Wiklander32b31802023-10-06 16:59:46 +02002074 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2075 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2076 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02002077
Jens Wiklander32b31802023-10-06 16:59:46 +02002078 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002079}
2080
2081#if defined(MBEDTLS_GENPRIME)
2082
Tom Van Eyckc1633172024-04-09 18:44:13 +02002083/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
2084static const unsigned char small_prime_gaps[] = {
2085 2, 2, 4, 2, 4, 2, 4, 6,
2086 2, 6, 4, 2, 4, 6, 6, 2,
2087 6, 4, 2, 6, 4, 6, 8, 4,
2088 2, 4, 2, 4, 14, 4, 6, 2,
2089 10, 2, 6, 6, 4, 6, 6, 2,
2090 10, 2, 4, 2, 12, 12, 4, 2,
2091 4, 6, 2, 10, 6, 6, 6, 2,
2092 6, 4, 2, 10, 14, 4, 2, 4,
2093 14, 6, 10, 2, 4, 6, 8, 6,
2094 6, 4, 6, 8, 4, 8, 10, 2,
2095 10, 2, 6, 4, 6, 8, 4, 2,
2096 4, 12, 8, 4, 8, 4, 6, 12,
2097 2, 18, 6, 10, 6, 6, 2, 6,
2098 10, 6, 6, 2, 6, 6, 4, 2,
2099 12, 10, 2, 4, 6, 6, 2, 12,
2100 4, 6, 8, 10, 8, 10, 8, 6,
2101 6, 4, 8, 6, 4, 8, 4, 14,
2102 10, 12, 2, 10, 2, 4, 2, 10,
2103 14, 4, 2, 4, 14, 4, 2, 4,
2104 20, 4, 8, 10, 8, 4, 6, 6,
2105 14, 4, 6, 6, 8, 6, /*reaches 997*/
2106 0 /* the last entry is effectively unused */
Jens Wiklander817466c2018-05-22 13:49:31 +02002107};
2108
2109/*
2110 * Small divisors test (X must be positive)
2111 *
2112 * Return values:
2113 * 0: no small factor (possible prime, more tests needed)
2114 * 1: certain prime
2115 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2116 * other negative: error
2117 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002118static int mpi_check_small_factors(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +02002119{
2120 int ret = 0;
2121 size_t i;
2122 mbedtls_mpi_uint r;
Tom Van Eyckc1633172024-04-09 18:44:13 +02002123 unsigned p = 3; /* The first odd prime */
Jens Wiklander817466c2018-05-22 13:49:31 +02002124
Jens Wiklander32b31802023-10-06 16:59:46 +02002125 if ((X->p[0] & 1) == 0) {
2126 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2127 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002128
Tom Van Eyckc1633172024-04-09 18:44:13 +02002129 for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2130 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
Jens Wiklander32b31802023-10-06 16:59:46 +02002131 if (r == 0) {
Tom Van Eyckc1633172024-04-09 18:44:13 +02002132 if (mbedtls_mpi_cmp_int(X, p) == 0) {
2133 return 1;
2134 } else {
2135 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2136 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002137 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002138 }
2139
2140cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002141 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002142}
2143
2144/*
2145 * Miller-Rabin pseudo-primality test (HAC 4.24)
2146 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002147static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2148 int (*f_rng)(void *, unsigned char *, size_t),
2149 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002150{
2151 int ret, count;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002152 size_t i, j, k, s;
Jens Wiklander817466c2018-05-22 13:49:31 +02002153 mbedtls_mpi W, R, T, A, RR;
2154
Jens Wiklander8eaf6922018-11-08 11:18:22 +01002155 mbedtls_mpi_init_mempool(&W); mbedtls_mpi_init_mempool(&R);
2156 mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A);
2157 mbedtls_mpi_init_mempool(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002158
2159 /*
2160 * W = |X| - 1
2161 * R = W >> lsb( W )
2162 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002163 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2164 s = mbedtls_mpi_lsb(&W);
2165 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2166 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Jens Wiklander817466c2018-05-22 13:49:31 +02002167
Jens Wiklander32b31802023-10-06 16:59:46 +02002168 for (i = 0; i < rounds; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002169 /*
2170 * pick a random A, 1 < A < |X| - 1
2171 */
Jens Wiklander817466c2018-05-22 13:49:31 +02002172 count = 0;
2173 do {
Jens Wiklander32b31802023-10-06 16:59:46 +02002174 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +02002175
Jens Wiklander32b31802023-10-06 16:59:46 +02002176 j = mbedtls_mpi_bitlen(&A);
2177 k = mbedtls_mpi_bitlen(&W);
Jens Wiklander817466c2018-05-22 13:49:31 +02002178 if (j > k) {
Jens Wiklander32b31802023-10-06 16:59:46 +02002179 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002180 }
2181
Jens Wiklander7925a6f2018-11-27 12:21:24 +01002182 if (count++ > 300) {
Jens Wiklander336e3292019-01-17 11:14:38 +01002183 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2184 goto cleanup;
Jens Wiklander817466c2018-05-22 13:49:31 +02002185 }
2186
Jens Wiklander32b31802023-10-06 16:59:46 +02002187 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2188 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02002189
2190 /*
2191 * A = A^R mod |X|
2192 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002193 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Jens Wiklander817466c2018-05-22 13:49:31 +02002194
Jens Wiklander32b31802023-10-06 16:59:46 +02002195 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2196 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002197 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +02002198 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002199
2200 j = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02002201 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002202 /*
2203 * A = A * A mod |X|
2204 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002205 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2206 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02002207
Jens Wiklander32b31802023-10-06 16:59:46 +02002208 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002209 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02002210 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002211
2212 j++;
2213 }
2214
2215 /*
2216 * not prime if A != |X| - 1 or A == 1
2217 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002218 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2219 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002220 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2221 break;
2222 }
2223 }
2224
2225cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002226 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2227 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2228 mbedtls_mpi_free(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002229
Jens Wiklander32b31802023-10-06 16:59:46 +02002230 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002231}
2232
2233/*
2234 * Pseudo-primality test: small factors, then Miller-Rabin
2235 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002236int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2237 int (*f_rng)(void *, unsigned char *, size_t),
2238 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002239{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02002240 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02002241 mbedtls_mpi XX;
2242
2243 XX.s = 1;
2244 XX.n = X->n;
2245 XX.p = X->p;
2246
Jens Wiklander32b31802023-10-06 16:59:46 +02002247 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2248 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2249 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002250 }
2251
Jens Wiklander32b31802023-10-06 16:59:46 +02002252 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2253 return 0;
2254 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002255
Jens Wiklander32b31802023-10-06 16:59:46 +02002256 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2257 if (ret == 1) {
2258 return 0;
2259 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002260
Jens Wiklander32b31802023-10-06 16:59:46 +02002261 return ret;
2262 }
2263
2264 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002265}
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002266
Jens Wiklander817466c2018-05-22 13:49:31 +02002267/*
2268 * Prime number generation
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002269 *
2270 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2271 * be either 1024 bits or 1536 bits long, and flags must contain
2272 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Jens Wiklander817466c2018-05-22 13:49:31 +02002273 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002274int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2275 int (*f_rng)(void *, unsigned char *, size_t),
2276 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002277{
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002278#ifdef MBEDTLS_HAVE_INT64
2279// ceil(2^63.5)
2280#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2281#else
2282// ceil(2^31.5)
2283#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2284#endif
2285 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002286 size_t k, n;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002287 int rounds;
Jens Wiklander817466c2018-05-22 13:49:31 +02002288 mbedtls_mpi_uint r;
2289 mbedtls_mpi Y;
2290
Jens Wiklander32b31802023-10-06 16:59:46 +02002291 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2292 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2293 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002294
Jens Wiklander8eaf6922018-11-08 11:18:22 +01002295 mbedtls_mpi_init_mempool(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002296
Jens Wiklander32b31802023-10-06 16:59:46 +02002297 n = BITS_TO_LIMBS(nbits);
Jens Wiklander817466c2018-05-22 13:49:31 +02002298
Jens Wiklander32b31802023-10-06 16:59:46 +02002299 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002300 /*
2301 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2302 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002303 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2304 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2305 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2306 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002307 /*
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002308 * 2^-100 error probability, number of rounds computed based on HAC,
2309 * fact 4.48
Jens Wiklander817466c2018-05-22 13:49:31 +02002310 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002311 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2312 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2313 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2314 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002315 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002316
Jens Wiklander32b31802023-10-06 16:59:46 +02002317 while (1) {
2318 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002319 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
Jens Wiklander32b31802023-10-06 16:59:46 +02002320 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2321 continue;
2322 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002323
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002324 k = n * biL;
Jens Wiklander32b31802023-10-06 16:59:46 +02002325 if (k > nbits) {
2326 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2327 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002328 X->p[0] |= 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002329
Jens Wiklander32b31802023-10-06 16:59:46 +02002330 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2331 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02002332
Jens Wiklander32b31802023-10-06 16:59:46 +02002333 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002334 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002335 }
2336 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002337 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02002338 * A necessary condition for Y and X = 2Y + 1 to be prime
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002339 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2340 * Make sure it is satisfied, while keeping X = 3 mod 4
Jens Wiklander817466c2018-05-22 13:49:31 +02002341 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002342
2343 X->p[0] |= 2;
2344
Jens Wiklander32b31802023-10-06 16:59:46 +02002345 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2346 if (r == 0) {
2347 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2348 } else if (r == 1) {
2349 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2350 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002351
2352 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Jens Wiklander32b31802023-10-06 16:59:46 +02002353 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2354 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002355
Jens Wiklander32b31802023-10-06 16:59:46 +02002356 while (1) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002357 /*
2358 * First, check small factors for X and Y
2359 * before doing Miller-Rabin on any of them
2360 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002361 if ((ret = mpi_check_small_factors(X)) == 0 &&
2362 (ret = mpi_check_small_factors(&Y)) == 0 &&
2363 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2364 == 0 &&
2365 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2366 == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002367 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002368 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002369
Jens Wiklander32b31802023-10-06 16:59:46 +02002370 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002371 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002372 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002373
2374 /*
2375 * Next candidates. We want to preserve Y = (X-1) / 2 and
2376 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2377 * so up Y by 6 and X by 12.
2378 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002379 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2380 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002381 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002382 }
2383 }
2384
2385cleanup:
2386
Jens Wiklander32b31802023-10-06 16:59:46 +02002387 mbedtls_mpi_free(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002388
Jens Wiklander32b31802023-10-06 16:59:46 +02002389 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002390}
2391
2392#endif /* MBEDTLS_GENPRIME */
2393
2394#if defined(MBEDTLS_SELF_TEST)
2395
2396#define GCD_PAIR_COUNT 3
2397
2398static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2399{
2400 { 693, 609, 21 },
2401 { 1764, 868, 28 },
2402 { 768454923, 542167814, 1 }
2403};
2404
2405/*
2406 * Checkup routine
2407 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002408int mbedtls_mpi_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +02002409{
2410 int ret, i;
2411 mbedtls_mpi A, E, N, X, Y, U, V;
2412
Jens Wiklander8eaf6922018-11-08 11:18:22 +01002413 mbedtls_mpi_init_mempool(&A); mbedtls_mpi_init_mempool(&E);
2414 mbedtls_mpi_init_mempool(&N); mbedtls_mpi_init_mempool(&X);
2415 mbedtls_mpi_init_mempool(&Y); mbedtls_mpi_init_mempool(&U);
2416 mbedtls_mpi_init_mempool(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002417
Jens Wiklander32b31802023-10-06 16:59:46 +02002418 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2419 "EFE021C2645FD1DC586E69184AF4A31E" \
2420 "D5F53E93B5F123FA41680867BA110131" \
2421 "944FE7952E2517337780CB0DB80E61AA" \
2422 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002423
Jens Wiklander32b31802023-10-06 16:59:46 +02002424 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2425 "B2E7EFD37075B9F03FF989C7C5051C20" \
2426 "34D2A323810251127E7BF8625A4F49A5" \
2427 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2428 "5B5C25763222FEFCCFC38B832366C29E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002429
Jens Wiklander32b31802023-10-06 16:59:46 +02002430 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2431 "0066A198186C18C10B2F5ED9B522752A" \
2432 "9830B69916E535C8F047518A889A43A5" \
2433 "94B6BED27A168D31D4A52F88925AA8F5"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002434
Jens Wiklander32b31802023-10-06 16:59:46 +02002435 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002436
Jens Wiklander32b31802023-10-06 16:59:46 +02002437 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2438 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2439 "9E857EA95A03512E2BAE7391688D264A" \
2440 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2441 "8001B72E848A38CAE1C65F78E56ABDEF" \
2442 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2443 "ECF677152EF804370C1A305CAF3B5BF1" \
2444 "30879B56C61DE584A0F53A2447A51E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002445
Jens Wiklander32b31802023-10-06 16:59:46 +02002446 if (verbose != 0) {
2447 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2448 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002449
Jens Wiklander32b31802023-10-06 16:59:46 +02002450 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2451 if (verbose != 0) {
2452 mbedtls_printf("failed\n");
2453 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002454
2455 ret = 1;
2456 goto cleanup;
2457 }
2458
Jens Wiklander32b31802023-10-06 16:59:46 +02002459 if (verbose != 0) {
2460 mbedtls_printf("passed\n");
2461 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002462
Jens Wiklander32b31802023-10-06 16:59:46 +02002463 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002464
Jens Wiklander32b31802023-10-06 16:59:46 +02002465 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2466 "256567336059E52CAE22925474705F39A94"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002467
Jens Wiklander32b31802023-10-06 16:59:46 +02002468 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2469 "6613F26162223DF488E9CD48CC132C7A" \
2470 "0AC93C701B001B092E4E5B9F73BCD27B" \
2471 "9EE50D0657C77F374E903CDFA4C642"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002472
Jens Wiklander32b31802023-10-06 16:59:46 +02002473 if (verbose != 0) {
2474 mbedtls_printf(" MPI test #2 (div_mpi): ");
2475 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002476
Jens Wiklander32b31802023-10-06 16:59:46 +02002477 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2478 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2479 if (verbose != 0) {
2480 mbedtls_printf("failed\n");
2481 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002482
2483 ret = 1;
2484 goto cleanup;
2485 }
2486
Jens Wiklander32b31802023-10-06 16:59:46 +02002487 if (verbose != 0) {
2488 mbedtls_printf("passed\n");
2489 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002490
Jens Wiklander32b31802023-10-06 16:59:46 +02002491 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Jens Wiklander817466c2018-05-22 13:49:31 +02002492
Jens Wiklander32b31802023-10-06 16:59:46 +02002493 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2494 "36E139AEA55215609D2816998ED020BB" \
2495 "BD96C37890F65171D948E9BC7CBAA4D9" \
2496 "325D24D6A3C12710F10A09FA08AB87"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002497
Jens Wiklander32b31802023-10-06 16:59:46 +02002498 if (verbose != 0) {
2499 mbedtls_printf(" MPI test #3 (exp_mod): ");
2500 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002501
Jens Wiklander32b31802023-10-06 16:59:46 +02002502 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2503 if (verbose != 0) {
2504 mbedtls_printf("failed\n");
2505 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002506
2507 ret = 1;
2508 goto cleanup;
2509 }
2510
Jens Wiklander32b31802023-10-06 16:59:46 +02002511 if (verbose != 0) {
2512 mbedtls_printf("passed\n");
2513 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002514
Jens Wiklander32b31802023-10-06 16:59:46 +02002515 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002516
Jens Wiklander32b31802023-10-06 16:59:46 +02002517 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2518 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2519 "C3DBA76456363A10869622EAC2DD84EC" \
2520 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002521
Jens Wiklander32b31802023-10-06 16:59:46 +02002522 if (verbose != 0) {
2523 mbedtls_printf(" MPI test #4 (inv_mod): ");
2524 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002525
Jens Wiklander32b31802023-10-06 16:59:46 +02002526 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2527 if (verbose != 0) {
2528 mbedtls_printf("failed\n");
2529 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002530
2531 ret = 1;
2532 goto cleanup;
2533 }
2534
Jens Wiklander32b31802023-10-06 16:59:46 +02002535 if (verbose != 0) {
2536 mbedtls_printf("passed\n");
2537 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002538
Jens Wiklander32b31802023-10-06 16:59:46 +02002539 if (verbose != 0) {
2540 mbedtls_printf(" MPI test #5 (simple gcd): ");
2541 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002542
Jens Wiklander32b31802023-10-06 16:59:46 +02002543 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2544 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2545 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Jens Wiklander817466c2018-05-22 13:49:31 +02002546
Jens Wiklander32b31802023-10-06 16:59:46 +02002547 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02002548
Jens Wiklander32b31802023-10-06 16:59:46 +02002549 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2550 if (verbose != 0) {
2551 mbedtls_printf("failed at %d\n", i);
2552 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002553
2554 ret = 1;
2555 goto cleanup;
2556 }
2557 }
2558
Jens Wiklander32b31802023-10-06 16:59:46 +02002559 if (verbose != 0) {
2560 mbedtls_printf("passed\n");
2561 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002562
2563cleanup:
2564
Jens Wiklander32b31802023-10-06 16:59:46 +02002565 if (ret != 0 && verbose != 0) {
2566 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2567 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002568
Jens Wiklander32b31802023-10-06 16:59:46 +02002569 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2570 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002571
Jens Wiklander32b31802023-10-06 16:59:46 +02002572 if (verbose != 0) {
2573 mbedtls_printf("\n");
2574 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002575
Jens Wiklander32b31802023-10-06 16:59:46 +02002576 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002577}
2578
2579#endif /* MBEDTLS_SELF_TEST */
2580
2581#endif /* MBEDTLS_BIGNUM_C */