blob: ce7fe1a1d1369f3b2b59e6c5e577db430c6038c9 [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 Eyckb0563632024-06-13 16:20:14 +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"
Sungbae Yoo4d211f32024-11-19 02:47:55 +000030#include "bignum_internal.h"
Jens Wiklander32b31802023-10-06 16:59:46 +020031#include "bn_mul.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010032#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020033#include "mbedtls/error.h"
Jerome Forissier039e02d2022-08-09 17:10:15 +020034#include "constant_time_internal.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020035
Jerome Forissier039e02d2022-08-09 17:10:15 +020036#include <limits.h>
Jens Wiklander817466c2018-05-22 13:49:31 +020037#include <string.h>
38
Jens Wiklander817466c2018-05-22 13:49:31 +020039#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020040
Jens Wiklander5e0191a2018-11-08 11:18:22 +010041#include <mempool.h>
42
43void *mbedtls_mpi_mempool;
Jens Wiklander98bd5fe2018-11-08 11:18:22 +010044
Tom Van Eyckb0563632024-06-13 16:20:14 +020045
46/*
47 * Conditionally select an MPI sign in constant time.
48 * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid
49 * values.)
50 */
51static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,
52 signed short sign1, signed short sign2)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010053{
Tom Van Eyckb0563632024-06-13 16:20:14 +020054 return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;
Jens Wiklander3d3b0592019-03-20 15:30:29 +010055}
56
Jens Wiklander817466c2018-05-22 13:49:31 +020057/*
Tom Van Eyckb0563632024-06-13 16:20:14 +020058 * Compare signed values in constant time
59 */
60int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
61 const mbedtls_mpi *Y,
62 unsigned *ret)
63{
64 mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
65
66 if (X->n != Y->n) {
67 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
68 }
69
70 /*
71 * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.
72 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
73 */
74 X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
75 Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
76
77 /*
78 * If the signs are different, then the positive operand is the bigger.
79 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
80 * is false if X is positive (X_is_negative == 0).
81 */
82 different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
83 result = mbedtls_ct_bool_and(different_sign, X_is_negative);
84
85 /*
86 * Assuming signs are the same, compare X and Y. We switch the comparison
87 * order if they are negative so that we get the right result, regardles of
88 * sign.
89 */
90
91 /* This array is used to conditionally swap the pointers in const time */
92 void * const p[2] = { X->p, Y->p };
93 size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
94 mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
95
96 /*
97 * Store in result iff the signs are the same (i.e., iff different_sign == false). If
98 * the signs differ, result has already been set, so we don't change it.
99 */
100 result = mbedtls_ct_bool_or(result,
101 mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
102
103 *ret = mbedtls_ct_uint_if_else_0(result, 1);
104
105 return 0;
106}
107
108/*
109 * Conditionally assign X = Y, without leaking information
110 * about whether the assignment was made or not.
111 * (Leaking information about the respective sizes of X and Y is ok however.)
112 */
113#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
114 (_MSC_FULL_VER < 193131103)
115/*
116 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
117 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
118 */
119__declspec(noinline)
120#endif
121int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
122 const mbedtls_mpi *Y,
123 unsigned char assign)
124{
125 int ret = 0;
126
127 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
128
129 {
130 mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
131
132 X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);
133
134 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
135
136 mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
137 for (size_t i = Y->n; i < X->n; i++) {
138 X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
139 }
140 }
141
142cleanup:
143 return ret;
144}
145
146/*
147 * Conditionally swap X and Y, without leaking information
148 * about whether the swap was made or not.
149 * Here it is not ok to simply swap the pointers, which would lead to
150 * different memory access patterns when X and Y are used afterwards.
151 */
152int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
153 mbedtls_mpi *Y,
154 unsigned char swap)
155{
156 int ret = 0;
157 int s;
158
159 if (X == Y) {
160 return 0;
161 }
162
163 mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
164
165 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
166 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
167
168 s = X->s;
169 X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);
170 Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);
171
172 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
173
174cleanup:
175 return ret;
176}
177
178/* Implementation that should never be optimized out by the compiler */
179#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
180
181/*
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100182 * Implementation that should never be optimized out by the compiler.
183 * Reintroduced to allow use of mempool.
184 */
185#define mbedtls_mpi_zeroize(v, n) mbedtls_platform_zeroize(v, ciL * (n))
186
187/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200188 * Initialize one MPI
189 */
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100190static void mpi_init(mbedtls_mpi *X, short use_mempool)
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100191{
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000192 X->s = 1;
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100193 X->use_mempool = use_mempool;
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000194 X->n = 0;
195 X->p = NULL;
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100196}
197
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100198void mbedtls_mpi_init(mbedtls_mpi *X)
199{
200 mpi_init(X, 0 /*use_mempool*/);
201}
202
203void mbedtls_mpi_init_mempool(mbedtls_mpi *X)
204{
205 mpi_init(X, !!mbedtls_mpi_mempool /*use_mempool*/);
206}
207
Jens Wiklander817466c2018-05-22 13:49:31 +0200208/*
209 * Unallocate one MPI
210 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200211void mbedtls_mpi_free(mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200212{
Jens Wiklander32b31802023-10-06 16:59:46 +0200213 if (X == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200214 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200215 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200216
Jens Wiklander32b31802023-10-06 16:59:46 +0200217 if (X->p != NULL) {
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100218 if(X->use_mempool) {
219 mbedtls_mpi_zeroize(X->p, X->n);
220 mempool_free(mbedtls_mpi_mempool, X->p);
221 } else {
222 mbedtls_mpi_zeroize_and_free(X->p, X->n);
223 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200224 }
225
226 X->s = 1;
227 X->n = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100228 X->p = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200229}
230
231/*
232 * Enlarge to the specified number of limbs
233 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200234int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Jens Wiklander817466c2018-05-22 13:49:31 +0200235{
236 mbedtls_mpi_uint *p;
237
Jens Wiklander32b31802023-10-06 16:59:46 +0200238 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
239 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
240 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200241
Jens Wiklander32b31802023-10-06 16:59:46 +0200242 if (X->n < nblimbs) {
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100243 if(X->use_mempool) {
244 p = mempool_alloc(mbedtls_mpi_mempool, nblimbs * ciL);
245 if(p == NULL)
246 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
247 memset(p, 0, nblimbs * ciL);
248 } else {
249 p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL);
250 if (p == NULL)
251 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100252 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200253
Jens Wiklander32b31802023-10-06 16:59:46 +0200254 if (X->p != NULL) {
255 memcpy(p, X->p, X->n * ciL);
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100256
257 if (X->use_mempool) {
258 mbedtls_mpi_zeroize(X->p, X->n);
259 mempool_free(mbedtls_mpi_mempool, X->p);
260 } else {
261 mbedtls_mpi_zeroize_and_free(X->p, X->n);
262 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100263 }
264
Tom Van Eyckb0563632024-06-13 16:20:14 +0200265 /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
266 * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
267 X->n = (unsigned short) nblimbs;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100268 X->p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +0200269 }
270
Jens Wiklander32b31802023-10-06 16:59:46 +0200271 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200272}
273
274/*
275 * Resize down as much as possible,
276 * while keeping at least the specified number of limbs
277 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200278int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Jens Wiklander817466c2018-05-22 13:49:31 +0200279{
280 mbedtls_mpi_uint *p;
281 size_t i;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100282
Jens Wiklander32b31802023-10-06 16:59:46 +0200283 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
284 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
285 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200286
Jerome Forissier5b25c762020-04-07 11:18:49 +0200287 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200288 if (X->n <= nblimbs) {
289 return mbedtls_mpi_grow(X, nblimbs);
290 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200291 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Jens Wiklander817466c2018-05-22 13:49:31 +0200292
Jens Wiklander32b31802023-10-06 16:59:46 +0200293 for (i = X->n - 1; i > 0; i--) {
294 if (X->p[i] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200295 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200296 }
297 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200298 i++;
299
Jens Wiklander32b31802023-10-06 16:59:46 +0200300 if (i < nblimbs) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200301 i = nblimbs;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100302 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200303
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100304 if (X->use_mempool) {
305 p = mempool_alloc(mbedtls_mpi_mempool, i * ciL);
306 if (p == NULL)
307 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
308 memset(p, 0, i * ciL);
309 } else {
310 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL)
311 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200312 }
313
314 if (X->p != NULL) {
315 memcpy(p, X->p, i * ciL);
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100316
317 if (X->use_mempool) {
318 mbedtls_mpi_zeroize(X->p, X->n);
319 mempool_free(mbedtls_mpi_mempool, X->p);
320 }
321 else {
322 mbedtls_mpi_zeroize_and_free(X->p, X->n);
323 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200324 }
325
Tom Van Eyckb0563632024-06-13 16:20:14 +0200326 /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
327 * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
328 X->n = (unsigned short) i;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100329 X->p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +0200330
Jens Wiklander32b31802023-10-06 16:59:46 +0200331 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200332}
333
Jerome Forissier79013242021-07-28 10:24:04 +0200334/* Resize X to have exactly n limbs and set it to 0. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200335static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Jerome Forissier79013242021-07-28 10:24:04 +0200336{
Jens Wiklander32b31802023-10-06 16:59:46 +0200337 if (limbs == 0) {
338 mbedtls_mpi_free(X);
339 return 0;
340 } else if (X->n == limbs) {
341 memset(X->p, 0, limbs * ciL);
Jerome Forissier79013242021-07-28 10:24:04 +0200342 X->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200343 return 0;
344 } else {
345 mbedtls_mpi_free(X);
346 return mbedtls_mpi_grow(X, limbs);
Jerome Forissier79013242021-07-28 10:24:04 +0200347 }
348}
349
Jens Wiklander817466c2018-05-22 13:49:31 +0200350/*
Jerome Forissier79013242021-07-28 10:24:04 +0200351 * Copy the contents of Y into X.
352 *
353 * This function is not constant-time. Leading zeros in Y may be removed.
354 *
355 * Ensure that X does not shrink. This is not guaranteed by the public API,
Tom Van Eyckb0563632024-06-13 16:20:14 +0200356 * but some code in the bignum module might still rely on this property.
Jens Wiklander817466c2018-05-22 13:49:31 +0200357 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200358int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200359{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100360 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200361 size_t i;
362
Jens Wiklander32b31802023-10-06 16:59:46 +0200363 if (X == Y) {
364 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200365 }
366
Jens Wiklander32b31802023-10-06 16:59:46 +0200367 if (Y->n == 0) {
368 if (X->n != 0) {
369 X->s = 1;
370 memset(X->p, 0, X->n * ciL);
371 }
372 return 0;
373 }
374
375 for (i = Y->n - 1; i > 0; i--) {
376 if (Y->p[i] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200377 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200378 }
379 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200380 i++;
381
382 X->s = Y->s;
383
Jens Wiklander32b31802023-10-06 16:59:46 +0200384 if (X->n < i) {
385 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
386 } else {
387 memset(X->p + i, 0, (X->n - i) * ciL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100388 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200389
Jens Wiklander32b31802023-10-06 16:59:46 +0200390 memcpy(X->p, Y->p, i * ciL);
Jens Wiklander817466c2018-05-22 13:49:31 +0200391
392cleanup:
393
Jens Wiklander32b31802023-10-06 16:59:46 +0200394 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200395}
396
397/*
398 * Swap the contents of X and Y
399 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200400void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200401{
402 mbedtls_mpi T;
403
Jens Wiklander32b31802023-10-06 16:59:46 +0200404 memcpy(&T, X, sizeof(mbedtls_mpi));
405 memcpy(X, Y, sizeof(mbedtls_mpi));
406 memcpy(Y, &T, sizeof(mbedtls_mpi));
407}
408
409static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
410{
411 if (z >= 0) {
412 return z;
413 }
414 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
415 * A naive -z would have undefined behavior.
416 * Write this in a way that makes popular compilers happy (GCC, Clang,
417 * MSVC). */
418 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Jens Wiklander817466c2018-05-22 13:49:31 +0200419}
420
Tom Van Eyckb0563632024-06-13 16:20:14 +0200421/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
422 * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
423#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
424
Jens Wiklander817466c2018-05-22 13:49:31 +0200425/*
426 * Set value from integer
427 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200428int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Jens Wiklander817466c2018-05-22 13:49:31 +0200429{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200430 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200431
Jens Wiklander32b31802023-10-06 16:59:46 +0200432 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
433 memset(X->p, 0, X->n * ciL);
Jens Wiklander817466c2018-05-22 13:49:31 +0200434
Jens Wiklander32b31802023-10-06 16:59:46 +0200435 X->p[0] = mpi_sint_abs(z);
Tom Van Eyckb0563632024-06-13 16:20:14 +0200436 X->s = TO_SIGN(z);
Jens Wiklander817466c2018-05-22 13:49:31 +0200437
438cleanup:
439
Jens Wiklander32b31802023-10-06 16:59:46 +0200440 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200441}
442
443/*
444 * Get a specific bit
445 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200446int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Jens Wiklander817466c2018-05-22 13:49:31 +0200447{
Jens Wiklander32b31802023-10-06 16:59:46 +0200448 if (X->n * biL <= pos) {
449 return 0;
450 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200451
Jens Wiklander32b31802023-10-06 16:59:46 +0200452 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Jens Wiklander817466c2018-05-22 13:49:31 +0200453}
454
455/*
456 * Set a bit to a specific value of 0 or 1
457 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200458int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Jens Wiklander817466c2018-05-22 13:49:31 +0200459{
460 int ret = 0;
461 size_t off = pos / biL;
462 size_t idx = pos % biL;
463
Jens Wiklander32b31802023-10-06 16:59:46 +0200464 if (val != 0 && val != 1) {
465 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200466 }
467
Jens Wiklander32b31802023-10-06 16:59:46 +0200468 if (X->n * biL <= pos) {
469 if (val == 0) {
470 return 0;
471 }
472
473 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
474 }
475
476 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200477 X->p[off] |= (mbedtls_mpi_uint) val << idx;
478
479cleanup:
480
Jens Wiklander32b31802023-10-06 16:59:46 +0200481 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200482}
483
484/*
485 * Return the number of less significant zero-bits
486 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200487size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200488{
Tom Van Eyckb0563632024-06-13 16:20:14 +0200489 size_t i;
Jens Wiklander817466c2018-05-22 13:49:31 +0200490
Tom Van Eyckb0563632024-06-13 16:20:14 +0200491#if defined(__has_builtin)
492#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
493 #define mbedtls_mpi_uint_ctz __builtin_ctz
494#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
495 #define mbedtls_mpi_uint_ctz __builtin_ctzl
496#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
497 #define mbedtls_mpi_uint_ctz __builtin_ctzll
498#endif
499#endif
500
501#if defined(mbedtls_mpi_uint_ctz)
Jens Wiklander32b31802023-10-06 16:59:46 +0200502 for (i = 0; i < X->n; i++) {
Tom Van Eyckb0563632024-06-13 16:20:14 +0200503 if (X->p[i] != 0) {
504 return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
505 }
506 }
507#else
508 size_t count = 0;
509 for (i = 0; i < X->n; i++) {
510 for (size_t j = 0; j < biL; j++, count++) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200511 if (((X->p[i] >> j) & 1) != 0) {
512 return count;
513 }
514 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200515 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200516#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200517
Jens Wiklander32b31802023-10-06 16:59:46 +0200518 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200519}
520
521/*
522 * Return the number of bits
523 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200524size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200525{
Jens Wiklander32b31802023-10-06 16:59:46 +0200526 return mbedtls_mpi_core_bitlen(X->p, X->n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200527}
528
529/*
530 * Return the total size in bytes
531 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200532size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200533{
Jens Wiklander32b31802023-10-06 16:59:46 +0200534 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Jens Wiklander817466c2018-05-22 13:49:31 +0200535}
536
537/*
538 * Convert an ASCII character to digit value
539 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200540static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Jens Wiklander817466c2018-05-22 13:49:31 +0200541{
542 *d = 255;
543
Jens Wiklander32b31802023-10-06 16:59:46 +0200544 if (c >= 0x30 && c <= 0x39) {
545 *d = c - 0x30;
546 }
547 if (c >= 0x41 && c <= 0x46) {
548 *d = c - 0x37;
549 }
550 if (c >= 0x61 && c <= 0x66) {
551 *d = c - 0x57;
552 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200553
Jens Wiklander32b31802023-10-06 16:59:46 +0200554 if (*d >= (mbedtls_mpi_uint) radix) {
555 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
556 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200557
Jens Wiklander32b31802023-10-06 16:59:46 +0200558 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200559}
560
561/*
562 * Import from an ASCII string
563 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200564int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Jens Wiklander817466c2018-05-22 13:49:31 +0200565{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200566 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200567 size_t i, j, slen, n;
Jerome Forissier79013242021-07-28 10:24:04 +0200568 int sign = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +0200569 mbedtls_mpi_uint d;
570 mbedtls_mpi T;
571
Jens Wiklander32b31802023-10-06 16:59:46 +0200572 if (radix < 2 || radix > 16) {
573 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jerome Forissier79013242021-07-28 10:24:04 +0200574 }
575
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100576 mbedtls_mpi_init_mempool(&T);
Jens Wiklander32b31802023-10-06 16:59:46 +0200577
578 if (s[0] == 0) {
579 mbedtls_mpi_free(X);
580 return 0;
581 }
582
583 if (s[0] == '-') {
Jerome Forissier79013242021-07-28 10:24:04 +0200584 ++s;
585 sign = -1;
586 }
587
Jens Wiklander32b31802023-10-06 16:59:46 +0200588 slen = strlen(s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200589
Jens Wiklander32b31802023-10-06 16:59:46 +0200590 if (radix == 16) {
Tom Van Eyckb0563632024-06-13 16:20:14 +0200591 if (slen > SIZE_MAX >> 2) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200592 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200593 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200594
Jens Wiklander32b31802023-10-06 16:59:46 +0200595 n = BITS_TO_LIMBS(slen << 2);
596
597 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
598 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
599
600 for (i = slen, j = 0; i > 0; i--, j++) {
601 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
602 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
603 }
604 } else {
605 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
606
607 for (i = 0; i < slen; i++) {
608 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
609 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
610 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Jens Wiklander817466c2018-05-22 13:49:31 +0200611 }
612 }
613
Jens Wiklander32b31802023-10-06 16:59:46 +0200614 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200615 X->s = -1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200616 }
Jerome Forissier79013242021-07-28 10:24:04 +0200617
Jens Wiklander817466c2018-05-22 13:49:31 +0200618cleanup:
619
Jens Wiklander32b31802023-10-06 16:59:46 +0200620 mbedtls_mpi_free(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200621
Jens Wiklander32b31802023-10-06 16:59:46 +0200622 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200623}
624
625/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200626 * Helper to write the digits high-order first.
Jens Wiklander817466c2018-05-22 13:49:31 +0200627 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200628static int mpi_write_hlp(mbedtls_mpi *X, int radix,
629 char **p, const size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200630{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200631 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200632 mbedtls_mpi_uint r;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200633 size_t length = 0;
634 char *p_end = *p + buflen;
Jens Wiklander817466c2018-05-22 13:49:31 +0200635
Jens Wiklander32b31802023-10-06 16:59:46 +0200636 do {
637 if (length >= buflen) {
638 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200639 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200640
Jens Wiklander32b31802023-10-06 16:59:46 +0200641 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
642 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Jerome Forissier5b25c762020-04-07 11:18:49 +0200643 /*
644 * Write the residue in the current position, as an ASCII character.
645 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200646 if (r < 0xA) {
647 *(--p_end) = (char) ('0' + r);
648 } else {
649 *(--p_end) = (char) ('A' + (r - 0xA));
650 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200651
Jerome Forissier5b25c762020-04-07 11:18:49 +0200652 length++;
Jens Wiklander32b31802023-10-06 16:59:46 +0200653 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200654
Jens Wiklander32b31802023-10-06 16:59:46 +0200655 memmove(*p, p_end, length);
Jerome Forissier5b25c762020-04-07 11:18:49 +0200656 *p += length;
Jens Wiklander817466c2018-05-22 13:49:31 +0200657
658cleanup:
659
Jens Wiklander32b31802023-10-06 16:59:46 +0200660 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200661}
662
663/*
664 * Export into an ASCII string
665 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200666int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
667 char *buf, size_t buflen, size_t *olen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200668{
669 int ret = 0;
670 size_t n;
671 char *p;
672 mbedtls_mpi T;
673
Jens Wiklander32b31802023-10-06 16:59:46 +0200674 if (radix < 2 || radix > 16) {
675 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
676 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200677
Jens Wiklander32b31802023-10-06 16:59:46 +0200678 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
679 if (radix >= 4) {
680 n >>= 1; /* Number of 4-adic digits necessary to present
Jerome Forissier5b25c762020-04-07 11:18:49 +0200681 * `n`. If radix > 4, this might be a strict
682 * overapproximation of the number of
683 * radix-adic digits needed to present `n`. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200684 }
685 if (radix >= 16) {
686 n >>= 1; /* Number of hexadecimal digits necessary to
Jerome Forissier5b25c762020-04-07 11:18:49 +0200687 * present `n`. */
688
Jens Wiklander32b31802023-10-06 16:59:46 +0200689 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200690 n += 1; /* Terminating null byte */
691 n += 1; /* Compensate for the divisions above, which round down `n`
692 * in case it's not even. */
693 n += 1; /* Potential '-'-sign. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200694 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200695 * which always uses an even number of hex-digits. */
Jens Wiklander817466c2018-05-22 13:49:31 +0200696
Jens Wiklander32b31802023-10-06 16:59:46 +0200697 if (buflen < n) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200698 *olen = n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200699 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200700 }
701
702 p = buf;
Jens Wiklander5e0191a2018-11-08 11:18:22 +0100703 mbedtls_mpi_init_mempool(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200704
Jens Wiklander32b31802023-10-06 16:59:46 +0200705 if (X->s == -1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200706 *p++ = '-';
Jerome Forissier5b25c762020-04-07 11:18:49 +0200707 buflen--;
708 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200709
Jens Wiklander32b31802023-10-06 16:59:46 +0200710 if (radix == 16) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200711 int c;
712 size_t i, j, k;
713
Jens Wiklander32b31802023-10-06 16:59:46 +0200714 for (i = X->n, k = 0; i > 0; i--) {
715 for (j = ciL; j > 0; j--) {
716 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Jens Wiklander817466c2018-05-22 13:49:31 +0200717
Jens Wiklander32b31802023-10-06 16:59:46 +0200718 if (c == 0 && k == 0 && (i + j) != 2) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200719 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +0200720 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200721
722 *(p++) = "0123456789ABCDEF" [c / 16];
723 *(p++) = "0123456789ABCDEF" [c % 16];
724 k = 1;
725 }
726 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200727 } else {
728 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +0200729
Jens Wiklander32b31802023-10-06 16:59:46 +0200730 if (T.s == -1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200731 T.s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200732 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200733
Jens Wiklander32b31802023-10-06 16:59:46 +0200734 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200735 }
736
737 *p++ = '\0';
Tom Van Eyckb0563632024-06-13 16:20:14 +0200738 *olen = (size_t) (p - buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200739
740cleanup:
741
Jens Wiklander32b31802023-10-06 16:59:46 +0200742 mbedtls_mpi_free(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200743
Jens Wiklander32b31802023-10-06 16:59:46 +0200744 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200745}
746
747#if defined(MBEDTLS_FS_IO)
748/*
749 * Read X from an opened file
750 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200751int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Jens Wiklander817466c2018-05-22 13:49:31 +0200752{
753 mbedtls_mpi_uint d;
754 size_t slen;
755 char *p;
756 /*
757 * Buffer should have space for (short) label and decimal formatted MPI,
758 * newline characters and '\0'
759 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200760 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200761
Jens Wiklander32b31802023-10-06 16:59:46 +0200762 if (radix < 2 || radix > 16) {
763 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
764 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100765
Jens Wiklander32b31802023-10-06 16:59:46 +0200766 memset(s, 0, sizeof(s));
767 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
768 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
769 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200770
Jens Wiklander32b31802023-10-06 16:59:46 +0200771 slen = strlen(s);
772 if (slen == sizeof(s) - 2) {
773 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
774 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200775
Jens Wiklander32b31802023-10-06 16:59:46 +0200776 if (slen > 0 && s[slen - 1] == '\n') {
777 slen--; s[slen] = '\0';
778 }
779 if (slen > 0 && s[slen - 1] == '\r') {
780 slen--; s[slen] = '\0';
781 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200782
783 p = s + slen;
Jens Wiklander32b31802023-10-06 16:59:46 +0200784 while (p-- > s) {
785 if (mpi_get_digit(&d, radix, *p) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200786 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200787 }
788 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200789
Jens Wiklander32b31802023-10-06 16:59:46 +0200790 return mbedtls_mpi_read_string(X, radix, p + 1);
Jens Wiklander817466c2018-05-22 13:49:31 +0200791}
792
793/*
794 * Write X into an opened file (or stdout if fout == NULL)
795 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200796int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Jens Wiklander817466c2018-05-22 13:49:31 +0200797{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200798 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200799 size_t n, slen, plen;
800 /*
801 * Buffer should have space for (short) label and decimal formatted MPI,
802 * newline characters and '\0'
803 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200804 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100805
Jens Wiklander32b31802023-10-06 16:59:46 +0200806 if (radix < 2 || radix > 16) {
807 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
808 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200809
Jens Wiklander32b31802023-10-06 16:59:46 +0200810 memset(s, 0, sizeof(s));
Jens Wiklander817466c2018-05-22 13:49:31 +0200811
Jens Wiklander32b31802023-10-06 16:59:46 +0200812 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Jens Wiklander817466c2018-05-22 13:49:31 +0200813
Jens Wiklander32b31802023-10-06 16:59:46 +0200814 if (p == NULL) {
815 p = "";
816 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200817
Jens Wiklander32b31802023-10-06 16:59:46 +0200818 plen = strlen(p);
819 slen = strlen(s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200820 s[slen++] = '\r';
821 s[slen++] = '\n';
822
Jens Wiklander32b31802023-10-06 16:59:46 +0200823 if (fout != NULL) {
824 if (fwrite(p, 1, plen, fout) != plen ||
825 fwrite(s, 1, slen, fout) != slen) {
826 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
827 }
828 } else {
829 mbedtls_printf("%s%s", p, s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200830 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200831
832cleanup:
833
Jens Wiklander32b31802023-10-06 16:59:46 +0200834 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200835}
836#endif /* MBEDTLS_FS_IO */
837
838/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200839 * Import X from unsigned binary data, little endian
Jens Wiklander32b31802023-10-06 16:59:46 +0200840 *
841 * This function is guaranteed to return an MPI with exactly the necessary
842 * number of limbs (in particular, it does not skip 0s in the input).
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200843 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200844int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
845 const unsigned char *buf, size_t buflen)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200846{
847 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200848 const size_t limbs = CHARS_TO_LIMBS(buflen);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200849
850 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +0200851 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200852
Jens Wiklander32b31802023-10-06 16:59:46 +0200853 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200854
855cleanup:
856
857 /*
858 * This function is also used to import keys. However, wiping the buffers
859 * upon failure is not necessary because failure only can happen before any
860 * input is copied.
861 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200862 return ret;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200863}
864
865/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200866 * Import X from unsigned binary data, big endian
Jens Wiklander32b31802023-10-06 16:59:46 +0200867 *
868 * This function is guaranteed to return an MPI with exactly the necessary
869 * number of limbs (in particular, it does not skip 0s in the input).
Jens Wiklander817466c2018-05-22 13:49:31 +0200870 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200871int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200872{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200873 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200874 const size_t limbs = CHARS_TO_LIMBS(buflen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200875
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100876 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +0200877 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Jens Wiklander29762732019-04-17 12:28:43 +0200878
Jens Wiklander32b31802023-10-06 16:59:46 +0200879 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200880
881cleanup:
882
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200883 /*
884 * This function is also used to import keys. However, wiping the buffers
885 * upon failure is not necessary because failure only can happen before any
886 * input is copied.
887 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200888 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200889}
890
891/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200892 * Export X into unsigned binary data, little endian
893 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200894int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
895 unsigned char *buf, size_t buflen)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200896{
Jens Wiklander32b31802023-10-06 16:59:46 +0200897 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200898}
899
900/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200901 * Export X into unsigned binary data, big endian
902 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200903int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
904 unsigned char *buf, size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200905{
Jens Wiklander32b31802023-10-06 16:59:46 +0200906 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200907}
908
909/*
910 * Left-shift: X <<= count
911 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200912int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Jens Wiklander817466c2018-05-22 13:49:31 +0200913{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200914 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Van Eyckb0563632024-06-13 16:20:14 +0200915 size_t i;
Jens Wiklander817466c2018-05-22 13:49:31 +0200916
Jens Wiklander32b31802023-10-06 16:59:46 +0200917 i = mbedtls_mpi_bitlen(X) + count;
Jens Wiklander817466c2018-05-22 13:49:31 +0200918
Jens Wiklander32b31802023-10-06 16:59:46 +0200919 if (X->n * biL < i) {
920 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
921 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200922
923 ret = 0;
924
Tom Van Eyckb0563632024-06-13 16:20:14 +0200925 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Jens Wiklander817466c2018-05-22 13:49:31 +0200926cleanup:
927
Jens Wiklander32b31802023-10-06 16:59:46 +0200928 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200929}
930
931/*
932 * Right-shift: X >>= count
933 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200934int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Jens Wiklander817466c2018-05-22 13:49:31 +0200935{
Jens Wiklander32b31802023-10-06 16:59:46 +0200936 if (X->n != 0) {
937 mbedtls_mpi_core_shift_r(X->p, X->n, count);
Jens Wiklander817466c2018-05-22 13:49:31 +0200938 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200939 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200940}
941
942/*
943 * Compare unsigned values
944 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200945int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200946{
947 size_t i, j;
948
Jens Wiklander32b31802023-10-06 16:59:46 +0200949 for (i = X->n; i > 0; i--) {
950 if (X->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200951 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200952 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200953 }
954
Jens Wiklander32b31802023-10-06 16:59:46 +0200955 for (j = Y->n; j > 0; j--) {
956 if (Y->p[j - 1] != 0) {
957 break;
958 }
959 }
960
Tom Van Eyckb0563632024-06-13 16:20:14 +0200961 /* If i == j == 0, i.e. abs(X) == abs(Y),
962 * we end up returning 0 at the end of the function. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200963
964 if (i > j) {
965 return 1;
966 }
967 if (j > i) {
968 return -1;
969 }
970
971 for (; i > 0; i--) {
972 if (X->p[i - 1] > Y->p[i - 1]) {
973 return 1;
974 }
975 if (X->p[i - 1] < Y->p[i - 1]) {
976 return -1;
977 }
978 }
979
980 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200981}
982
983/*
984 * Compare signed values
985 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200986int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200987{
988 size_t i, j;
989
Jens Wiklander32b31802023-10-06 16:59:46 +0200990 for (i = X->n; i > 0; i--) {
991 if (X->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200992 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200993 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200994 }
995
Jens Wiklander32b31802023-10-06 16:59:46 +0200996 for (j = Y->n; j > 0; j--) {
997 if (Y->p[j - 1] != 0) {
998 break;
999 }
1000 }
1001
1002 if (i == 0 && j == 0) {
1003 return 0;
1004 }
1005
1006 if (i > j) {
1007 return X->s;
1008 }
1009 if (j > i) {
1010 return -Y->s;
1011 }
1012
1013 if (X->s > 0 && Y->s < 0) {
1014 return 1;
1015 }
1016 if (Y->s > 0 && X->s < 0) {
1017 return -1;
1018 }
1019
1020 for (; i > 0; i--) {
1021 if (X->p[i - 1] > Y->p[i - 1]) {
1022 return X->s;
1023 }
1024 if (X->p[i - 1] < Y->p[i - 1]) {
1025 return -X->s;
1026 }
1027 }
1028
1029 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001030}
1031
1032/*
1033 * Compare signed values
1034 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001035int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Jens Wiklander817466c2018-05-22 13:49:31 +02001036{
1037 mbedtls_mpi Y;
1038 mbedtls_mpi_uint p[1];
1039
Jens Wiklander32b31802023-10-06 16:59:46 +02001040 *p = mpi_sint_abs(z);
Tom Van Eyckb0563632024-06-13 16:20:14 +02001041 Y.s = TO_SIGN(z);
Jens Wiklander817466c2018-05-22 13:49:31 +02001042 Y.n = 1;
1043 Y.p = p;
1044
Jens Wiklander32b31802023-10-06 16:59:46 +02001045 return mbedtls_mpi_cmp_mpi(X, &Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02001046}
1047
1048/*
1049 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1050 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001051int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001052{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001053 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001054 size_t j;
Tom Van Eyckb0563632024-06-13 16:20:14 +02001055 mbedtls_mpi_uint *p;
1056 mbedtls_mpi_uint c;
Jens Wiklander817466c2018-05-22 13:49:31 +02001057
Jens Wiklander32b31802023-10-06 16:59:46 +02001058 if (X == B) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001059 const mbedtls_mpi *T = A; A = X; B = T;
1060 }
1061
Jens Wiklander32b31802023-10-06 16:59:46 +02001062 if (X != A) {
1063 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1064 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001065
1066 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02001067 * X must always be positive as a result of unsigned additions.
Jens Wiklander817466c2018-05-22 13:49:31 +02001068 */
1069 X->s = 1;
1070
Jens Wiklander32b31802023-10-06 16:59:46 +02001071 for (j = B->n; j > 0; j--) {
1072 if (B->p[j - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001073 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001074 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001075 }
1076
Jens Wiklander32b31802023-10-06 16:59:46 +02001077 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1078 * and B is 0 (of any size). */
1079 if (j == 0) {
1080 return 0;
1081 }
1082
1083 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
1084
1085 /* j is the number of non-zero limbs of B. Add those to X. */
1086
Tom Van Eyckb0563632024-06-13 16:20:14 +02001087 p = X->p;
Jens Wiklander32b31802023-10-06 16:59:46 +02001088
Tom Van Eyckb0563632024-06-13 16:20:14 +02001089 c = mbedtls_mpi_core_add(p, p, B->p, j);
Jens Wiklander32b31802023-10-06 16:59:46 +02001090
1091 p += j;
1092
1093 /* Now propagate any carry */
1094
1095 while (c != 0) {
1096 if (j >= X->n) {
1097 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
1098 p = X->p + j;
Jens Wiklander817466c2018-05-22 13:49:31 +02001099 }
1100
Jens Wiklander32b31802023-10-06 16:59:46 +02001101 *p += c; c = (*p < c); j++; p++;
Jens Wiklander817466c2018-05-22 13:49:31 +02001102 }
1103
1104cleanup:
1105
Jens Wiklander32b31802023-10-06 16:59:46 +02001106 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001107}
1108
1109/*
Jerome Forissier79013242021-07-28 10:24:04 +02001110 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Jens Wiklander817466c2018-05-22 13:49:31 +02001111 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001112int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001113{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001114 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001115 size_t n;
Jerome Forissier79013242021-07-28 10:24:04 +02001116 mbedtls_mpi_uint carry;
Jens Wiklander817466c2018-05-22 13:49:31 +02001117
Jens Wiklander32b31802023-10-06 16:59:46 +02001118 for (n = B->n; n > 0; n--) {
1119 if (B->p[n - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001120 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001121 }
1122 }
1123 if (n > A->n) {
Jerome Forissier79013242021-07-28 10:24:04 +02001124 /* B >= (2^ciL)^n > A */
1125 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1126 goto cleanup;
1127 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001128
Jens Wiklander32b31802023-10-06 16:59:46 +02001129 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Jerome Forissier79013242021-07-28 10:24:04 +02001130
1131 /* Set the high limbs of X to match A. Don't touch the lower limbs
1132 * because X might be aliased to B, and we must not overwrite the
1133 * significant digits of B. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001134 if (A->n > n && A != X) {
1135 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1136 }
1137 if (X->n > A->n) {
1138 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1139 }
Jerome Forissier79013242021-07-28 10:24:04 +02001140
Jens Wiklander32b31802023-10-06 16:59:46 +02001141 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1142 if (carry != 0) {
1143 /* Propagate the carry through the rest of X. */
1144 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
1145
1146 /* If we have further carry/borrow, the result is negative. */
1147 if (carry != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001148 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1149 goto cleanup;
1150 }
Jerome Forissier79013242021-07-28 10:24:04 +02001151 }
1152
1153 /* X should always be positive as a result of unsigned subtractions. */
1154 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001155
1156cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001157 return ret;
1158}
1159
1160/* Common function for signed addition and subtraction.
1161 * Calculate A + B * flip_B where flip_B is 1 or -1.
1162 */
1163static int add_sub_mpi(mbedtls_mpi *X,
1164 const mbedtls_mpi *A, const mbedtls_mpi *B,
1165 int flip_B)
1166{
1167 int ret, s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001168
1169 s = A->s;
1170 if (A->s * B->s * flip_B < 0) {
1171 int cmp = mbedtls_mpi_cmp_abs(A, B);
1172 if (cmp >= 0) {
1173 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
1174 /* If |A| = |B|, the result is 0 and we must set the sign bit
1175 * to +1 regardless of which of A or B was negative. Otherwise,
1176 * since |A| > |B|, the sign is the sign of A. */
1177 X->s = cmp == 0 ? 1 : s;
1178 } else {
1179 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
1180 /* Since |A| < |B|, the sign is the opposite of A. */
1181 X->s = -s;
1182 }
1183 } else {
1184 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
1185 X->s = s;
1186 }
1187
1188cleanup:
1189
1190 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001191}
1192
1193/*
1194 * Signed addition: X = A + B
1195 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001196int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001197{
Jens Wiklander32b31802023-10-06 16:59:46 +02001198 return add_sub_mpi(X, A, B, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001199}
1200
1201/*
1202 * Signed subtraction: X = A - B
1203 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001204int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001205{
Jens Wiklander32b31802023-10-06 16:59:46 +02001206 return add_sub_mpi(X, A, B, -1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001207}
1208
1209/*
1210 * Signed addition: X = A + b
1211 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001212int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001213{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001214 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001215 mbedtls_mpi_uint p[1];
1216
Jens Wiklander32b31802023-10-06 16:59:46 +02001217 p[0] = mpi_sint_abs(b);
Tom Van Eyckb0563632024-06-13 16:20:14 +02001218 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001219 B.n = 1;
1220 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001221
Jens Wiklander32b31802023-10-06 16:59:46 +02001222 return mbedtls_mpi_add_mpi(X, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001223}
1224
1225/*
1226 * Signed subtraction: X = A - b
1227 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001228int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001229{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001230 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001231 mbedtls_mpi_uint p[1];
1232
Jens Wiklander32b31802023-10-06 16:59:46 +02001233 p[0] = mpi_sint_abs(b);
Tom Van Eyckb0563632024-06-13 16:20:14 +02001234 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001235 B.n = 1;
1236 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001237
Jens Wiklander32b31802023-10-06 16:59:46 +02001238 return mbedtls_mpi_sub_mpi(X, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001239}
1240
1241/*
1242 * Baseline multiplication: X = A * B (HAC 14.12)
1243 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001244int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001245{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001246 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001247 size_t i, j;
1248 mbedtls_mpi TA, TB;
Jerome Forissier79013242021-07-28 10:24:04 +02001249 int result_is_zero = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001250
Jens Wiklander5e0191a2018-11-08 11:18:22 +01001251 mbedtls_mpi_init_mempool(&TA);
1252 mbedtls_mpi_init_mempool(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001253
Jens Wiklander32b31802023-10-06 16:59:46 +02001254 if (X == A) {
1255 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1256 }
1257 if (X == B) {
1258 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1259 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001260
Jens Wiklander32b31802023-10-06 16:59:46 +02001261 for (i = A->n; i > 0; i--) {
1262 if (A->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001263 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001264 }
1265 }
1266 if (i == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001267 result_is_zero = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001268 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001269
Jens Wiklander32b31802023-10-06 16:59:46 +02001270 for (j = B->n; j > 0; j--) {
1271 if (B->p[j - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001272 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001273 }
1274 }
1275 if (j == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001276 result_is_zero = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001277 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001278
Jens Wiklander32b31802023-10-06 16:59:46 +02001279 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1280 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Jens Wiklander817466c2018-05-22 13:49:31 +02001281
Tom Van Eyckb0563632024-06-13 16:20:14 +02001282 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Jens Wiklander817466c2018-05-22 13:49:31 +02001283
Jerome Forissier79013242021-07-28 10:24:04 +02001284 /* If the result is 0, we don't shortcut the operation, which reduces
1285 * but does not eliminate side channels leaking the zero-ness. We do
1286 * need to take care to set the sign bit properly since the library does
1287 * not fully support an MPI object with a value of 0 and s == -1. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001288 if (result_is_zero) {
Jerome Forissier79013242021-07-28 10:24:04 +02001289 X->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001290 } else {
Jerome Forissier79013242021-07-28 10:24:04 +02001291 X->s = A->s * B->s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001292 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001293
1294cleanup:
1295
Jens Wiklander32b31802023-10-06 16:59:46 +02001296 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Jens Wiklander817466c2018-05-22 13:49:31 +02001297
Jens Wiklander32b31802023-10-06 16:59:46 +02001298 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001299}
1300
1301/*
1302 * Baseline multiplication: X = A * b
1303 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001304int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001305{
Jerome Forissier79013242021-07-28 10:24:04 +02001306 size_t n = A->n;
Jens Wiklander32b31802023-10-06 16:59:46 +02001307 while (n > 0 && A->p[n - 1] == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001308 --n;
Jerome Forissier79013242021-07-28 10:24:04 +02001309 }
1310
Jens Wiklander32b31802023-10-06 16:59:46 +02001311 /* The general method below doesn't work if b==0. */
1312 if (b == 0 || n == 0) {
1313 return mbedtls_mpi_lset(X, 0);
1314 }
1315
1316 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Jerome Forissier79013242021-07-28 10:24:04 +02001317 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1318 /* In general, A * b requires 1 limb more than b. If
1319 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1320 * number of limbs as A and the call to grow() is not required since
1321 * copy() will take care of the growth if needed. However, experimentally,
1322 * making the call to grow() unconditional causes slightly fewer
1323 * calls to calloc() in ECP code, presumably because it reuses the
1324 * same mpi for a while and this way the mpi is more likely to directly
Jens Wiklander32b31802023-10-06 16:59:46 +02001325 * grow to its final size.
1326 *
1327 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1328 * A,X can be the same. */
1329 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1330 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1331 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Jerome Forissier79013242021-07-28 10:24:04 +02001332
1333cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001334 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001335}
1336
1337/*
1338 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1339 * mbedtls_mpi_uint divisor, d
1340 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001341static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1342 mbedtls_mpi_uint u0,
1343 mbedtls_mpi_uint d,
1344 mbedtls_mpi_uint *r)
Jens Wiklander817466c2018-05-22 13:49:31 +02001345{
1346#if defined(MBEDTLS_HAVE_UDBL)
1347 mbedtls_t_udbl dividend, quotient;
1348#else
1349 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Jens Wiklander32b31802023-10-06 16:59:46 +02001350 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001351 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1352 mbedtls_mpi_uint u0_msw, u0_lsw;
1353 size_t s;
1354#endif
1355
1356 /*
1357 * Check for overflow
1358 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001359 if (0 == d || u1 >= d) {
1360 if (r != NULL) {
1361 *r = ~(mbedtls_mpi_uint) 0u;
1362 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001363
Jens Wiklander32b31802023-10-06 16:59:46 +02001364 return ~(mbedtls_mpi_uint) 0u;
Jens Wiklander817466c2018-05-22 13:49:31 +02001365 }
1366
1367#if defined(MBEDTLS_HAVE_UDBL)
1368 dividend = (mbedtls_t_udbl) u1 << biL;
1369 dividend |= (mbedtls_t_udbl) u0;
1370 quotient = dividend / d;
Jens Wiklander32b31802023-10-06 16:59:46 +02001371 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1372 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1373 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001374
Jens Wiklander32b31802023-10-06 16:59:46 +02001375 if (r != NULL) {
1376 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1377 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001378
1379 return (mbedtls_mpi_uint) quotient;
1380#else
1381
1382 /*
1383 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1384 * Vol. 2 - Seminumerical Algorithms, Knuth
1385 */
1386
1387 /*
1388 * Normalize the divisor, d, and dividend, u0, u1
1389 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001390 s = mbedtls_mpi_core_clz(d);
Jens Wiklander817466c2018-05-22 13:49:31 +02001391 d = d << s;
1392
1393 u1 = u1 << s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001394 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001395 u0 = u0 << s;
1396
1397 d1 = d >> biH;
1398 d0 = d & uint_halfword_mask;
1399
1400 u0_msw = u0 >> biH;
1401 u0_lsw = u0 & uint_halfword_mask;
1402
1403 /*
1404 * Find the first quotient and remainder
1405 */
1406 q1 = u1 / d1;
1407 r0 = u1 - d1 * q1;
1408
Jens Wiklander32b31802023-10-06 16:59:46 +02001409 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001410 q1 -= 1;
1411 r0 += d1;
1412
Jens Wiklander32b31802023-10-06 16:59:46 +02001413 if (r0 >= radix) {
1414 break;
1415 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001416 }
1417
Jens Wiklander32b31802023-10-06 16:59:46 +02001418 rAX = (u1 * radix) + (u0_msw - q1 * d);
Jens Wiklander817466c2018-05-22 13:49:31 +02001419 q0 = rAX / d1;
1420 r0 = rAX - q0 * d1;
1421
Jens Wiklander32b31802023-10-06 16:59:46 +02001422 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001423 q0 -= 1;
1424 r0 += d1;
1425
Jens Wiklander32b31802023-10-06 16:59:46 +02001426 if (r0 >= radix) {
1427 break;
1428 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001429 }
1430
Jens Wiklander32b31802023-10-06 16:59:46 +02001431 if (r != NULL) {
1432 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1433 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001434
1435 quotient = q1 * radix + q0;
1436
1437 return quotient;
1438#endif
1439}
1440
1441/*
1442 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
1443 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001444int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1445 const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001446{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001447 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001448 size_t i, n, t, k;
1449 mbedtls_mpi X, Y, Z, T1, T2;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001450 mbedtls_mpi_uint TP2[3];
Jens Wiklander817466c2018-05-22 13:49:31 +02001451
Jens Wiklander32b31802023-10-06 16:59:46 +02001452 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1453 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1454 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001455
Jens Wiklander5e0191a2018-11-08 11:18:22 +01001456 mbedtls_mpi_init_mempool(&X); mbedtls_mpi_init_mempool(&Y);
1457 mbedtls_mpi_init_mempool(&Z); mbedtls_mpi_init_mempool(&T1);
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001458 /*
1459 * Avoid dynamic memory allocations for constant-size T2.
1460 *
1461 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1462 * so nobody increase the size of the MPI and we're safe to use an on-stack
1463 * buffer.
1464 */
1465 T2.s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001466 T2.n = sizeof(TP2) / sizeof(*TP2);
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001467 T2.p = TP2;
Jens Wiklander817466c2018-05-22 13:49:31 +02001468
Jens Wiklander32b31802023-10-06 16:59:46 +02001469 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1470 if (Q != NULL) {
1471 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1472 }
1473 if (R != NULL) {
1474 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1475 }
1476 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001477 }
1478
Jens Wiklander32b31802023-10-06 16:59:46 +02001479 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1480 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001481 X.s = Y.s = 1;
1482
Jens Wiklander32b31802023-10-06 16:59:46 +02001483 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1484 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1485 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Jens Wiklander817466c2018-05-22 13:49:31 +02001486
Jens Wiklander32b31802023-10-06 16:59:46 +02001487 k = mbedtls_mpi_bitlen(&Y) % biL;
1488 if (k < biL - 1) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001489 k = biL - 1 - k;
Jens Wiklander32b31802023-10-06 16:59:46 +02001490 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1491 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1492 } else {
1493 k = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001494 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001495
1496 n = X.n - 1;
1497 t = Y.n - 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001498 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001499
Jens Wiklander32b31802023-10-06 16:59:46 +02001500 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001501 Z.p[n - t]++;
Jens Wiklander32b31802023-10-06 16:59:46 +02001502 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02001503 }
Jens Wiklander32b31802023-10-06 16:59:46 +02001504 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001505
Jens Wiklander32b31802023-10-06 16:59:46 +02001506 for (i = n; i > t; i--) {
1507 if (X.p[i] >= Y.p[t]) {
1508 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1509 } else {
1510 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1511 Y.p[t], NULL);
Jens Wiklander817466c2018-05-22 13:49:31 +02001512 }
1513
Jens Wiklander32b31802023-10-06 16:59:46 +02001514 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1515 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001516 T2.p[2] = X.p[i];
1517
Jens Wiklander817466c2018-05-22 13:49:31 +02001518 Z.p[i - t - 1]++;
Jens Wiklander32b31802023-10-06 16:59:46 +02001519 do {
Jens Wiklander817466c2018-05-22 13:49:31 +02001520 Z.p[i - t - 1]--;
1521
Jens Wiklander32b31802023-10-06 16:59:46 +02001522 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1523 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Jens Wiklander817466c2018-05-22 13:49:31 +02001524 T1.p[1] = Y.p[t];
Jens Wiklander32b31802023-10-06 16:59:46 +02001525 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1526 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001527
Jens Wiklander32b31802023-10-06 16:59:46 +02001528 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1529 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1530 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001531
Jens Wiklander32b31802023-10-06 16:59:46 +02001532 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1533 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1534 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1535 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001536 Z.p[i - t - 1]--;
1537 }
1538 }
1539
Jens Wiklander32b31802023-10-06 16:59:46 +02001540 if (Q != NULL) {
1541 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Jens Wiklander817466c2018-05-22 13:49:31 +02001542 Q->s = A->s * B->s;
1543 }
1544
Jens Wiklander32b31802023-10-06 16:59:46 +02001545 if (R != NULL) {
1546 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Jens Wiklander817466c2018-05-22 13:49:31 +02001547 X.s = A->s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001548 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001549
Jens Wiklander32b31802023-10-06 16:59:46 +02001550 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001551 R->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001552 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001553 }
1554
1555cleanup:
1556
Jens Wiklander32b31802023-10-06 16:59:46 +02001557 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1558 mbedtls_mpi_free(&T1);
1559 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Jens Wiklander817466c2018-05-22 13:49:31 +02001560
Jens Wiklander32b31802023-10-06 16:59:46 +02001561 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001562}
1563
1564/*
1565 * Division by int: A = Q * b + R
1566 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001567int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1568 const mbedtls_mpi *A,
1569 mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001570{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001571 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001572 mbedtls_mpi_uint p[1];
1573
Jens Wiklander32b31802023-10-06 16:59:46 +02001574 p[0] = mpi_sint_abs(b);
Tom Van Eyckb0563632024-06-13 16:20:14 +02001575 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001576 B.n = 1;
1577 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001578
Jens Wiklander32b31802023-10-06 16:59:46 +02001579 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001580}
1581
1582/*
1583 * Modulo: R = A mod B
1584 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001585int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001586{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001587 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001588
Jens Wiklander32b31802023-10-06 16:59:46 +02001589 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1590 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1591 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001592
Jens Wiklander32b31802023-10-06 16:59:46 +02001593 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001594
Jens Wiklander32b31802023-10-06 16:59:46 +02001595 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1596 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1597 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001598
Jens Wiklander32b31802023-10-06 16:59:46 +02001599 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1600 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1601 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001602
1603cleanup:
1604
Jens Wiklander32b31802023-10-06 16:59:46 +02001605 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001606}
1607
1608/*
1609 * Modulo: r = A mod b
1610 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001611int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001612{
1613 size_t i;
1614 mbedtls_mpi_uint x, y, z;
1615
Jens Wiklander32b31802023-10-06 16:59:46 +02001616 if (b == 0) {
1617 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1618 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001619
Jens Wiklander32b31802023-10-06 16:59:46 +02001620 if (b < 0) {
1621 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1622 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001623
1624 /*
1625 * handle trivial cases
1626 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001627 if (b == 1 || A->n == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001628 *r = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +02001629 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001630 }
1631
Jens Wiklander32b31802023-10-06 16:59:46 +02001632 if (b == 2) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001633 *r = A->p[0] & 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001634 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001635 }
1636
1637 /*
1638 * general case
1639 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001640 for (i = A->n, y = 0; i > 0; i--) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001641 x = A->p[i - 1];
Jens Wiklander32b31802023-10-06 16:59:46 +02001642 y = (y << biH) | (x >> biH);
Jens Wiklander817466c2018-05-22 13:49:31 +02001643 z = y / b;
1644 y -= z * b;
1645
1646 x <<= biH;
Jens Wiklander32b31802023-10-06 16:59:46 +02001647 y = (y << biH) | (x >> biH);
Jens Wiklander817466c2018-05-22 13:49:31 +02001648 z = y / b;
1649 y -= z * b;
1650 }
1651
1652 /*
1653 * If A is negative, then the current y represents a negative value.
1654 * Flipping it to the positive side.
1655 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001656 if (A->s < 0 && y != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001657 y = b - y;
Jens Wiklander32b31802023-10-06 16:59:46 +02001658 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001659
1660 *r = y;
1661
Jens Wiklander32b31802023-10-06 16:59:46 +02001662 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001663}
1664
Jens Wiklanderbf7ce252018-11-07 08:11:29 +01001665/**
1666 * \remark Replaced by our own because the original has been removed since
1667 * mbedtls v3.6.0.
1668*/
1669void mbedtls_mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
1670{
1671 *mm = mbedtls_mpi_core_montmul_init(N->p);
1672}
1673
1674/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1675 *
1676 * \param[in,out] A One of the numbers to multiply.
1677 * It must have at least as many limbs as N
1678 * (A->n >= N->n), and any limbs beyond n are ignored.
1679 * On successful completion, A contains the result of
1680 * the multiplication A * B * R^-1 mod N where
1681 * R = (2^ciL)^n.
1682 * \param[in] B One of the numbers to multiply.
1683 * It must be nonzero and must not have more limbs than N
1684 * (B->n <= N->n).
1685 * \param[in] N The modulus. \p N must be odd.
1686 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1687 * This is -N^-1 mod 2^ciL.
1688 * \param[in,out] T A bignum for temporary storage.
1689 * It must be at least twice the limb size of N plus 1
1690 * (T->n >= 2 * N->n + 1).
1691 * Its initial content is unused and
1692 * its final content is indeterminate.
1693 * It does not get reallocated.
1694 * \remark Replaced by our own because the original has been removed since
1695 * mbedtls v3.6.0.
1696 */
1697void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1698 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1699 mbedtls_mpi *T)
1700{
1701 mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
1702}
1703
1704/**
1705 * Montgomery reduction: A = A * R^-1 mod N
1706 *
1707 * See mbedtls_mpi_montmul() regarding constraints and guarantees on the parameters.
1708 *
1709 * \remark Replaced by our own because the original has been removed since
1710 * mbedtls v3.6.0.
1711 */
1712void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1713 mbedtls_mpi_uint mm, mbedtls_mpi *T)
1714{
1715 mbedtls_mpi_uint z = 1;
1716 mbedtls_mpi U;
1717
1718 U.n = U.s = (int) z;
1719 U.p = &z;
1720
1721 mbedtls_mpi_montmul(A, &U, N, mm, T);
1722}
1723
Jens Wiklander817466c2018-05-22 13:49:31 +02001724/*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001725 * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,
1726 * this function is not constant time with respect to the exponent (parameter E).
Jens Wiklander817466c2018-05-22 13:49:31 +02001727 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001728static int mbedtls_mpi_exp_mod_optionally_safe(mbedtls_mpi *X, const mbedtls_mpi *A,
1729 const mbedtls_mpi *E, int E_public,
1730 const mbedtls_mpi *N, mbedtls_mpi *prec_RR)
Jens Wiklander817466c2018-05-22 13:49:31 +02001731{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001732 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001733
Jens Wiklander32b31802023-10-06 16:59:46 +02001734 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1735 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1736 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001737
Jens Wiklander32b31802023-10-06 16:59:46 +02001738 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1739 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1740 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001741
Jens Wiklander32b31802023-10-06 16:59:46 +02001742 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1743 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1744 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1745 }
Jerome Forissier79013242021-07-28 10:24:04 +02001746
Jens Wiklander817466c2018-05-22 13:49:31 +02001747 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001748 * Ensure that the exponent that we are passing to the core is not NULL.
Jens Wiklander817466c2018-05-22 13:49:31 +02001749 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001750 if (E->n == 0) {
1751 ret = mbedtls_mpi_lset(X, 1);
1752 return ret;
Jens Wiklander32b31802023-10-06 16:59:46 +02001753 }
Jens Wiklander32b31802023-10-06 16:59:46 +02001754
Jens Wiklander32b31802023-10-06 16:59:46 +02001755 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001756 * Allocate working memory for mbedtls_mpi_core_exp_mod()
Jens Wiklander32b31802023-10-06 16:59:46 +02001757 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001758 size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);
1759 mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint));
1760 if (T == NULL) {
1761 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001762 }
1763
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001764 mbedtls_mpi RR;
Jens Wiklander5e0191a2018-11-08 11:18:22 +01001765 mbedtls_mpi_init_mempool(&RR);
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001766
Jens Wiklander817466c2018-05-22 13:49:31 +02001767 /*
1768 * If 1st call, pre-compute R^2 mod N
1769 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001770 if (prec_RR == NULL || prec_RR->p == NULL) {
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001771 MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001772
Jens Wiklander32b31802023-10-06 16:59:46 +02001773 if (prec_RR != NULL) {
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001774 *prec_RR = RR;
Jens Wiklander32b31802023-10-06 16:59:46 +02001775 }
1776 } else {
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001777 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
1778 RR = *prec_RR;
Jens Wiklander817466c2018-05-22 13:49:31 +02001779 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001780
1781 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001782 * To preserve constness we need to make a copy of A. Using X for this to
1783 * save memory.
Jens Wiklander817466c2018-05-22 13:49:31 +02001784 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001785 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
Jens Wiklander817466c2018-05-22 13:49:31 +02001786
1787 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001788 * Compensate for negative A (and correct at the end).
Jens Wiklander817466c2018-05-22 13:49:31 +02001789 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001790 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001791
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001792 /*
1793 * Make sure that X is in a form that is safe for consumption by
1794 * the core functions.
1795 *
1796 * - The core functions will not touch the limbs of X above N->n. The
1797 * result will be correct if those limbs are 0, which the mod call
1798 * ensures.
1799 * - Also, X must have at least as many limbs as N for the calls to the
1800 * core functions.
1801 */
1802 if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
1803 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001804 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001805 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
Jens Wiklander817466c2018-05-22 13:49:31 +02001806
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001807 /*
1808 * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
1809 */
1810 {
1811 mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
1812 mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
1813 if (E_public == MBEDTLS_MPI_IS_PUBLIC) {
1814 mbedtls_mpi_core_exp_mod_unsafe(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
1815 } else {
1816 mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
Jens Wiklander817466c2018-05-22 13:49:31 +02001817 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001818 mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
Jens Wiklander817466c2018-05-22 13:49:31 +02001819 }
1820
1821 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001822 * Correct for negative A.
Jens Wiklander817466c2018-05-22 13:49:31 +02001823 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001824 if (A->s == -1 && (E->p[0] & 1) != 0) {
1825 mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
1826 X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001827
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001828 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001829 }
1830
Jens Wiklander817466c2018-05-22 13:49:31 +02001831cleanup:
1832
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001833 mbedtls_mpi_zeroize_and_free(T, T_limbs);
Jens Wiklander817466c2018-05-22 13:49:31 +02001834
Jens Wiklander32b31802023-10-06 16:59:46 +02001835 if (prec_RR == NULL || prec_RR->p == NULL) {
1836 mbedtls_mpi_free(&RR);
1837 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001838
Jens Wiklander32b31802023-10-06 16:59:46 +02001839 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001840}
1841
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001842int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1843 const mbedtls_mpi *E, const mbedtls_mpi *N,
1844 mbedtls_mpi *prec_RR)
1845{
Sungbae Yoo85df2562024-11-21 14:21:29 +00001846#if (defined(__KERNEL__) && defined(CFG_CORE_UNSAFE_MODEXP)) || \
1847 (!defined(__KERNEL__) && defined(CFG_TA_MEBDTLS_UNSAFE_MODEXP))
1848 return mbedtls_mpi_exp_mod_unsafe(X, A, E, N, prec_RR);
1849#else
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001850 return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_SECRET, N, prec_RR);
Sungbae Yoo85df2562024-11-21 14:21:29 +00001851#endif
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001852}
1853
Jens Wiklanderbf7ce252018-11-07 08:11:29 +01001854
1855/*
1856 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1857 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001858int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,
1859 const mbedtls_mpi *E, const mbedtls_mpi *N,
1860 mbedtls_mpi *prec_RR)
1861{
1862 return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_PUBLIC, N, prec_RR);
1863}
1864
Jens Wiklander817466c2018-05-22 13:49:31 +02001865/*
1866 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1867 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001868int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001869{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001870 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001871 size_t lz, lzt;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001872 mbedtls_mpi TA, TB;
Jens Wiklander817466c2018-05-22 13:49:31 +02001873
Jens Wiklander5e0191a2018-11-08 11:18:22 +01001874 mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001875
Jens Wiklander32b31802023-10-06 16:59:46 +02001876 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1877 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001878
Jens Wiklander32b31802023-10-06 16:59:46 +02001879 lz = mbedtls_mpi_lsb(&TA);
1880 lzt = mbedtls_mpi_lsb(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001881
Jerome Forissier79013242021-07-28 10:24:04 +02001882 /* The loop below gives the correct result when A==0 but not when B==0.
1883 * So have a special case for B==0. Leverage the fact that we just
1884 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1885 * slightly more efficient than cmp_int(). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001886 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1887 ret = mbedtls_mpi_copy(G, A);
Jerome Forissier79013242021-07-28 10:24:04 +02001888 goto cleanup;
1889 }
1890
Jens Wiklander32b31802023-10-06 16:59:46 +02001891 if (lzt < lz) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001892 lz = lzt;
Jens Wiklander32b31802023-10-06 16:59:46 +02001893 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001894
Jens Wiklander817466c2018-05-22 13:49:31 +02001895 TA.s = TB.s = 1;
1896
Jerome Forissier79013242021-07-28 10:24:04 +02001897 /* We mostly follow the procedure described in HAC 14.54, but with some
1898 * minor differences:
1899 * - Sequences of multiplications or divisions by 2 are grouped into a
1900 * single shift operation.
1901 * - The procedure in HAC assumes that 0 < TB <= TA.
1902 * - The condition TB <= TA is not actually necessary for correctness.
1903 * TA and TB have symmetric roles except for the loop termination
1904 * condition, and the shifts at the beginning of the loop body
1905 * remove any significance from the ordering of TA vs TB before
1906 * the shifts.
1907 * - If TA = 0, the loop goes through 0 iterations and the result is
1908 * correctly TB.
1909 * - The case TB = 0 was short-circuited above.
1910 *
1911 * For the correctness proof below, decompose the original values of
1912 * A and B as
1913 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1914 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1915 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1916 * and gcd(A',B') is odd or 0.
1917 *
1918 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1919 * The code maintains the following invariant:
1920 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
1921 */
1922
1923 /* Proof that the loop terminates:
1924 * At each iteration, either the right-shift by 1 is made on a nonzero
1925 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
1926 * by at least 1, or the right-shift by 1 is made on zero and then
1927 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
1928 * since in that case TB is calculated from TB-TA with the condition TB>TA).
1929 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001930 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001931 /* Divisions by 2 preserve the invariant (I). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001932 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
1933 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001934
Jerome Forissier79013242021-07-28 10:24:04 +02001935 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
1936 * TA-TB is even so the division by 2 has an integer result.
1937 * Invariant (I) is preserved since any odd divisor of both TA and TB
1938 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Jerome Forissier039e02d2022-08-09 17:10:15 +02001939 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Jerome Forissier79013242021-07-28 10:24:04 +02001940 * divides TA.
1941 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001942 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
1943 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
1944 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
1945 } else {
1946 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
1947 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001948 }
Jerome Forissier79013242021-07-28 10:24:04 +02001949 /* Note that one of TA or TB is still odd. */
Jens Wiklander817466c2018-05-22 13:49:31 +02001950 }
1951
Jerome Forissier79013242021-07-28 10:24:04 +02001952 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
1953 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
1954 * - If there was at least one loop iteration, then one of TA or TB is odd,
1955 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
1956 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
1957 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
1958 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
1959 */
1960
Jens Wiklander32b31802023-10-06 16:59:46 +02001961 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
1962 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Jens Wiklander817466c2018-05-22 13:49:31 +02001963
1964cleanup:
1965
Jens Wiklander32b31802023-10-06 16:59:46 +02001966 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001967
Jens Wiklander32b31802023-10-06 16:59:46 +02001968 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001969}
1970
Jens Wiklander817466c2018-05-22 13:49:31 +02001971/*
1972 * Fill X with size bytes of random.
Jens Wiklander32b31802023-10-06 16:59:46 +02001973 * The bytes returned from the RNG are used in a specific order which
1974 * is suitable for deterministic ECDSA (see the specification of
1975 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Jens Wiklander817466c2018-05-22 13:49:31 +02001976 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001977int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
1978 int (*f_rng)(void *, unsigned char *, size_t),
1979 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02001980{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001981 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001982 const size_t limbs = CHARS_TO_LIMBS(size);
Jerome Forissier5b25c762020-04-07 11:18:49 +02001983
Jerome Forissier5b25c762020-04-07 11:18:49 +02001984 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +02001985 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
1986 if (size == 0) {
1987 return 0;
1988 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001989
Jens Wiklander32b31802023-10-06 16:59:46 +02001990 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02001991
1992cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001993 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001994}
1995
Jens Wiklander32b31802023-10-06 16:59:46 +02001996int mbedtls_mpi_random(mbedtls_mpi *X,
1997 mbedtls_mpi_sint min,
1998 const mbedtls_mpi *N,
1999 int (*f_rng)(void *, unsigned char *, size_t),
2000 void *p_rng)
Jerome Forissier79013242021-07-28 10:24:04 +02002001{
Jens Wiklander32b31802023-10-06 16:59:46 +02002002 if (min < 0) {
2003 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2004 }
2005 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2006 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2007 }
Jerome Forissier79013242021-07-28 10:24:04 +02002008
2009 /* Ensure that target MPI has exactly the same number of limbs
2010 * as the upper bound, even if the upper bound has leading zeros.
Jens Wiklander32b31802023-10-06 16:59:46 +02002011 * This is necessary for mbedtls_mpi_core_random. */
2012 int ret = mbedtls_mpi_resize_clear(X, N->n);
2013 if (ret != 0) {
2014 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02002015 }
Jerome Forissier79013242021-07-28 10:24:04 +02002016
Jens Wiklander32b31802023-10-06 16:59:46 +02002017 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Jerome Forissier79013242021-07-28 10:24:04 +02002018}
2019
Jens Wiklander817466c2018-05-22 13:49:31 +02002020/*
2021 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2022 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002023int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Jens Wiklander817466c2018-05-22 13:49:31 +02002024{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02002025 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02002026 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
2027
Jens Wiklander32b31802023-10-06 16:59:46 +02002028 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2029 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2030 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002031
Jens Wiklander5e0191a2018-11-08 11:18:22 +01002032 mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TU);
2033 mbedtls_mpi_init_mempool(&U1); mbedtls_mpi_init_mempool(&U2);
2034 mbedtls_mpi_init_mempool(&G); mbedtls_mpi_init_mempool(&TB);
2035 mbedtls_mpi_init_mempool(&TV); mbedtls_mpi_init_mempool(&V1);
2036 mbedtls_mpi_init_mempool(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02002037
Jens Wiklander32b31802023-10-06 16:59:46 +02002038 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002039
Jens Wiklander32b31802023-10-06 16:59:46 +02002040 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002041 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2042 goto cleanup;
2043 }
2044
Jens Wiklander32b31802023-10-06 16:59:46 +02002045 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2046 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2047 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2048 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002049
Jens Wiklander32b31802023-10-06 16:59:46 +02002050 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2051 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2052 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2053 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002054
Jens Wiklander32b31802023-10-06 16:59:46 +02002055 do {
2056 while ((TU.p[0] & 1) == 0) {
2057 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002058
Jens Wiklander32b31802023-10-06 16:59:46 +02002059 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2060 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2061 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02002062 }
2063
Jens Wiklander32b31802023-10-06 16:59:46 +02002064 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2065 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002066 }
2067
Jens Wiklander32b31802023-10-06 16:59:46 +02002068 while ((TV.p[0] & 1) == 0) {
2069 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002070
Jens Wiklander32b31802023-10-06 16:59:46 +02002071 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2072 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2073 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02002074 }
2075
Jens Wiklander32b31802023-10-06 16:59:46 +02002076 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2077 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002078 }
2079
Jens Wiklander32b31802023-10-06 16:59:46 +02002080 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2081 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2082 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2083 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2084 } else {
2085 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2086 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2087 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Jens Wiklander817466c2018-05-22 13:49:31 +02002088 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002089 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2090
2091 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2092 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002093 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002094
Jens Wiklander32b31802023-10-06 16:59:46 +02002095 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2096 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2097 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002098
Jens Wiklander32b31802023-10-06 16:59:46 +02002099 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002100
2101cleanup:
2102
Jens Wiklander32b31802023-10-06 16:59:46 +02002103 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2104 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2105 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02002106
Jens Wiklander32b31802023-10-06 16:59:46 +02002107 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002108}
2109
2110#if defined(MBEDTLS_GENPRIME)
2111
Tom Van Eyckb0563632024-06-13 16:20:14 +02002112/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
2113static const unsigned char small_prime_gaps[] = {
2114 2, 2, 4, 2, 4, 2, 4, 6,
2115 2, 6, 4, 2, 4, 6, 6, 2,
2116 6, 4, 2, 6, 4, 6, 8, 4,
2117 2, 4, 2, 4, 14, 4, 6, 2,
2118 10, 2, 6, 6, 4, 6, 6, 2,
2119 10, 2, 4, 2, 12, 12, 4, 2,
2120 4, 6, 2, 10, 6, 6, 6, 2,
2121 6, 4, 2, 10, 14, 4, 2, 4,
2122 14, 6, 10, 2, 4, 6, 8, 6,
2123 6, 4, 6, 8, 4, 8, 10, 2,
2124 10, 2, 6, 4, 6, 8, 4, 2,
2125 4, 12, 8, 4, 8, 4, 6, 12,
2126 2, 18, 6, 10, 6, 6, 2, 6,
2127 10, 6, 6, 2, 6, 6, 4, 2,
2128 12, 10, 2, 4, 6, 6, 2, 12,
2129 4, 6, 8, 10, 8, 10, 8, 6,
2130 6, 4, 8, 6, 4, 8, 4, 14,
2131 10, 12, 2, 10, 2, 4, 2, 10,
2132 14, 4, 2, 4, 14, 4, 2, 4,
2133 20, 4, 8, 10, 8, 4, 6, 6,
2134 14, 4, 6, 6, 8, 6, /*reaches 997*/
2135 0 /* the last entry is effectively unused */
Jens Wiklander817466c2018-05-22 13:49:31 +02002136};
2137
2138/*
2139 * Small divisors test (X must be positive)
2140 *
2141 * Return values:
2142 * 0: no small factor (possible prime, more tests needed)
2143 * 1: certain prime
2144 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2145 * other negative: error
2146 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002147static int mpi_check_small_factors(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +02002148{
2149 int ret = 0;
2150 size_t i;
2151 mbedtls_mpi_uint r;
Tom Van Eyckb0563632024-06-13 16:20:14 +02002152 unsigned p = 3; /* The first odd prime */
Jens Wiklander817466c2018-05-22 13:49:31 +02002153
Jens Wiklander32b31802023-10-06 16:59:46 +02002154 if ((X->p[0] & 1) == 0) {
2155 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2156 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002157
Tom Van Eyckb0563632024-06-13 16:20:14 +02002158 for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2159 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
Jens Wiklander32b31802023-10-06 16:59:46 +02002160 if (r == 0) {
Tom Van Eyckb0563632024-06-13 16:20:14 +02002161 if (mbedtls_mpi_cmp_int(X, p) == 0) {
2162 return 1;
2163 } else {
2164 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2165 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002166 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002167 }
2168
2169cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002170 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002171}
2172
2173/*
2174 * Miller-Rabin pseudo-primality test (HAC 4.24)
2175 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002176static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2177 int (*f_rng)(void *, unsigned char *, size_t),
2178 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002179{
2180 int ret, count;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002181 size_t i, j, k, s;
Jens Wiklander817466c2018-05-22 13:49:31 +02002182 mbedtls_mpi W, R, T, A, RR;
2183
Jens Wiklander5e0191a2018-11-08 11:18:22 +01002184 mbedtls_mpi_init_mempool(&W); mbedtls_mpi_init_mempool(&R);
2185 mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A);
2186 mbedtls_mpi_init_mempool(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002187
2188 /*
2189 * W = |X| - 1
2190 * R = W >> lsb( W )
2191 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002192 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2193 s = mbedtls_mpi_lsb(&W);
2194 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2195 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Jens Wiklander817466c2018-05-22 13:49:31 +02002196
Jens Wiklander32b31802023-10-06 16:59:46 +02002197 for (i = 0; i < rounds; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002198 /*
2199 * pick a random A, 1 < A < |X| - 1
2200 */
Jens Wiklander817466c2018-05-22 13:49:31 +02002201 count = 0;
2202 do {
Jens Wiklander32b31802023-10-06 16:59:46 +02002203 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +02002204
Jens Wiklander32b31802023-10-06 16:59:46 +02002205 j = mbedtls_mpi_bitlen(&A);
2206 k = mbedtls_mpi_bitlen(&W);
Jens Wiklander817466c2018-05-22 13:49:31 +02002207 if (j > k) {
Jens Wiklander32b31802023-10-06 16:59:46 +02002208 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002209 }
2210
Jens Wiklander65e7ec82018-11-27 12:21:24 +01002211 if (count++ > 300) {
Jens Wiklander336e3292019-01-17 11:14:38 +01002212 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2213 goto cleanup;
Jens Wiklander817466c2018-05-22 13:49:31 +02002214 }
2215
Jens Wiklander32b31802023-10-06 16:59:46 +02002216 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2217 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02002218
2219 /*
2220 * A = A^R mod |X|
2221 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002222 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Jens Wiklander817466c2018-05-22 13:49:31 +02002223
Jens Wiklander32b31802023-10-06 16:59:46 +02002224 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2225 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002226 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +02002227 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002228
2229 j = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02002230 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002231 /*
2232 * A = A * A mod |X|
2233 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002234 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2235 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02002236
Jens Wiklander32b31802023-10-06 16:59:46 +02002237 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002238 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02002239 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002240
2241 j++;
2242 }
2243
2244 /*
2245 * not prime if A != |X| - 1 or A == 1
2246 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002247 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2248 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002249 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2250 break;
2251 }
2252 }
2253
2254cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002255 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2256 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2257 mbedtls_mpi_free(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002258
Jens Wiklander32b31802023-10-06 16:59:46 +02002259 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002260}
2261
2262/*
2263 * Pseudo-primality test: small factors, then Miller-Rabin
2264 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002265int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2266 int (*f_rng)(void *, unsigned char *, size_t),
2267 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002268{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02002269 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02002270 mbedtls_mpi XX;
2271
2272 XX.s = 1;
2273 XX.n = X->n;
2274 XX.p = X->p;
2275
Jens Wiklander32b31802023-10-06 16:59:46 +02002276 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2277 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2278 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002279 }
2280
Jens Wiklander32b31802023-10-06 16:59:46 +02002281 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2282 return 0;
2283 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002284
Jens Wiklander32b31802023-10-06 16:59:46 +02002285 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2286 if (ret == 1) {
2287 return 0;
2288 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002289
Jens Wiklander32b31802023-10-06 16:59:46 +02002290 return ret;
2291 }
2292
2293 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002294}
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002295
Jens Wiklander817466c2018-05-22 13:49:31 +02002296/*
2297 * Prime number generation
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002298 *
2299 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2300 * be either 1024 bits or 1536 bits long, and flags must contain
2301 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Jens Wiklander817466c2018-05-22 13:49:31 +02002302 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002303int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2304 int (*f_rng)(void *, unsigned char *, size_t),
2305 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002306{
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002307#ifdef MBEDTLS_HAVE_INT64
2308// ceil(2^63.5)
2309#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2310#else
2311// ceil(2^31.5)
2312#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2313#endif
2314 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002315 size_t k, n;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002316 int rounds;
Jens Wiklander817466c2018-05-22 13:49:31 +02002317 mbedtls_mpi_uint r;
2318 mbedtls_mpi Y;
2319
Jens Wiklander32b31802023-10-06 16:59:46 +02002320 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2321 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2322 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002323
Jens Wiklander5e0191a2018-11-08 11:18:22 +01002324 mbedtls_mpi_init_mempool(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002325
Jens Wiklander32b31802023-10-06 16:59:46 +02002326 n = BITS_TO_LIMBS(nbits);
Jens Wiklander817466c2018-05-22 13:49:31 +02002327
Jens Wiklander32b31802023-10-06 16:59:46 +02002328 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002329 /*
2330 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2331 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002332 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2333 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2334 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2335 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002336 /*
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002337 * 2^-100 error probability, number of rounds computed based on HAC,
2338 * fact 4.48
Jens Wiklander817466c2018-05-22 13:49:31 +02002339 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002340 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2341 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2342 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2343 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002344 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002345
Jens Wiklander32b31802023-10-06 16:59:46 +02002346 while (1) {
2347 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002348 /* 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 +02002349 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2350 continue;
2351 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002352
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002353 k = n * biL;
Jens Wiklander32b31802023-10-06 16:59:46 +02002354 if (k > nbits) {
2355 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2356 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002357 X->p[0] |= 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002358
Jens Wiklander32b31802023-10-06 16:59:46 +02002359 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2360 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02002361
Jens Wiklander32b31802023-10-06 16:59:46 +02002362 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002363 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002364 }
2365 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002366 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02002367 * A necessary condition for Y and X = 2Y + 1 to be prime
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002368 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2369 * Make sure it is satisfied, while keeping X = 3 mod 4
Jens Wiklander817466c2018-05-22 13:49:31 +02002370 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002371
2372 X->p[0] |= 2;
2373
Jens Wiklander32b31802023-10-06 16:59:46 +02002374 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2375 if (r == 0) {
2376 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2377 } else if (r == 1) {
2378 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2379 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002380
2381 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Jens Wiklander32b31802023-10-06 16:59:46 +02002382 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2383 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002384
Jens Wiklander32b31802023-10-06 16:59:46 +02002385 while (1) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002386 /*
2387 * First, check small factors for X and Y
2388 * before doing Miller-Rabin on any of them
2389 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002390 if ((ret = mpi_check_small_factors(X)) == 0 &&
2391 (ret = mpi_check_small_factors(&Y)) == 0 &&
2392 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2393 == 0 &&
2394 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2395 == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002396 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002397 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002398
Jens Wiklander32b31802023-10-06 16:59:46 +02002399 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002400 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002401 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002402
2403 /*
2404 * Next candidates. We want to preserve Y = (X-1) / 2 and
2405 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2406 * so up Y by 6 and X by 12.
2407 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002408 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2409 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002410 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002411 }
2412 }
2413
2414cleanup:
2415
Jens Wiklander32b31802023-10-06 16:59:46 +02002416 mbedtls_mpi_free(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002417
Jens Wiklander32b31802023-10-06 16:59:46 +02002418 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002419}
2420
2421#endif /* MBEDTLS_GENPRIME */
2422
2423#if defined(MBEDTLS_SELF_TEST)
2424
2425#define GCD_PAIR_COUNT 3
2426
2427static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2428{
2429 { 693, 609, 21 },
2430 { 1764, 868, 28 },
2431 { 768454923, 542167814, 1 }
2432};
2433
2434/*
2435 * Checkup routine
2436 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002437int mbedtls_mpi_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +02002438{
2439 int ret, i;
2440 mbedtls_mpi A, E, N, X, Y, U, V;
2441
Jens Wiklander5e0191a2018-11-08 11:18:22 +01002442 mbedtls_mpi_init_mempool(&A); mbedtls_mpi_init_mempool(&E);
2443 mbedtls_mpi_init_mempool(&N); mbedtls_mpi_init_mempool(&X);
2444 mbedtls_mpi_init_mempool(&Y); mbedtls_mpi_init_mempool(&U);
2445 mbedtls_mpi_init_mempool(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002446
Jens Wiklander32b31802023-10-06 16:59:46 +02002447 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2448 "EFE021C2645FD1DC586E69184AF4A31E" \
2449 "D5F53E93B5F123FA41680867BA110131" \
2450 "944FE7952E2517337780CB0DB80E61AA" \
2451 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002452
Jens Wiklander32b31802023-10-06 16:59:46 +02002453 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2454 "B2E7EFD37075B9F03FF989C7C5051C20" \
2455 "34D2A323810251127E7BF8625A4F49A5" \
2456 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2457 "5B5C25763222FEFCCFC38B832366C29E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002458
Jens Wiklander32b31802023-10-06 16:59:46 +02002459 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2460 "0066A198186C18C10B2F5ED9B522752A" \
2461 "9830B69916E535C8F047518A889A43A5" \
2462 "94B6BED27A168D31D4A52F88925AA8F5"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002463
Jens Wiklander32b31802023-10-06 16:59:46 +02002464 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002465
Jens Wiklander32b31802023-10-06 16:59:46 +02002466 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2467 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2468 "9E857EA95A03512E2BAE7391688D264A" \
2469 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2470 "8001B72E848A38CAE1C65F78E56ABDEF" \
2471 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2472 "ECF677152EF804370C1A305CAF3B5BF1" \
2473 "30879B56C61DE584A0F53A2447A51E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002474
Jens Wiklander32b31802023-10-06 16:59:46 +02002475 if (verbose != 0) {
2476 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2477 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002478
Jens Wiklander32b31802023-10-06 16:59:46 +02002479 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2480 if (verbose != 0) {
2481 mbedtls_printf("failed\n");
2482 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002483
2484 ret = 1;
2485 goto cleanup;
2486 }
2487
Jens Wiklander32b31802023-10-06 16:59:46 +02002488 if (verbose != 0) {
2489 mbedtls_printf("passed\n");
2490 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002491
Jens Wiklander32b31802023-10-06 16:59:46 +02002492 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002493
Jens Wiklander32b31802023-10-06 16:59:46 +02002494 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2495 "256567336059E52CAE22925474705F39A94"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002496
Jens Wiklander32b31802023-10-06 16:59:46 +02002497 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2498 "6613F26162223DF488E9CD48CC132C7A" \
2499 "0AC93C701B001B092E4E5B9F73BCD27B" \
2500 "9EE50D0657C77F374E903CDFA4C642"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002501
Jens Wiklander32b31802023-10-06 16:59:46 +02002502 if (verbose != 0) {
2503 mbedtls_printf(" MPI test #2 (div_mpi): ");
2504 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002505
Jens Wiklander32b31802023-10-06 16:59:46 +02002506 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2507 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2508 if (verbose != 0) {
2509 mbedtls_printf("failed\n");
2510 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002511
2512 ret = 1;
2513 goto cleanup;
2514 }
2515
Jens Wiklander32b31802023-10-06 16:59:46 +02002516 if (verbose != 0) {
2517 mbedtls_printf("passed\n");
2518 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002519
Jens Wiklander32b31802023-10-06 16:59:46 +02002520 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Jens Wiklander817466c2018-05-22 13:49:31 +02002521
Jens Wiklander32b31802023-10-06 16:59:46 +02002522 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2523 "36E139AEA55215609D2816998ED020BB" \
2524 "BD96C37890F65171D948E9BC7CBAA4D9" \
2525 "325D24D6A3C12710F10A09FA08AB87"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002526
Jens Wiklander32b31802023-10-06 16:59:46 +02002527 if (verbose != 0) {
2528 mbedtls_printf(" MPI test #3 (exp_mod): ");
2529 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002530
Jens Wiklander32b31802023-10-06 16:59:46 +02002531 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2532 if (verbose != 0) {
2533 mbedtls_printf("failed\n");
2534 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002535
2536 ret = 1;
2537 goto cleanup;
2538 }
2539
Jens Wiklander32b31802023-10-06 16:59:46 +02002540 if (verbose != 0) {
2541 mbedtls_printf("passed\n");
2542 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002543
Jens Wiklander32b31802023-10-06 16:59:46 +02002544 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002545
Jens Wiklander32b31802023-10-06 16:59:46 +02002546 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2547 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2548 "C3DBA76456363A10869622EAC2DD84EC" \
2549 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002550
Jens Wiklander32b31802023-10-06 16:59:46 +02002551 if (verbose != 0) {
2552 mbedtls_printf(" MPI test #4 (inv_mod): ");
2553 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002554
Jens Wiklander32b31802023-10-06 16:59:46 +02002555 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2556 if (verbose != 0) {
2557 mbedtls_printf("failed\n");
2558 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002559
2560 ret = 1;
2561 goto cleanup;
2562 }
2563
Jens Wiklander32b31802023-10-06 16:59:46 +02002564 if (verbose != 0) {
2565 mbedtls_printf("passed\n");
2566 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002567
Jens Wiklander32b31802023-10-06 16:59:46 +02002568 if (verbose != 0) {
2569 mbedtls_printf(" MPI test #5 (simple gcd): ");
2570 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002571
Jens Wiklander32b31802023-10-06 16:59:46 +02002572 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2573 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2574 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Jens Wiklander817466c2018-05-22 13:49:31 +02002575
Jens Wiklander32b31802023-10-06 16:59:46 +02002576 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02002577
Jens Wiklander32b31802023-10-06 16:59:46 +02002578 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2579 if (verbose != 0) {
2580 mbedtls_printf("failed at %d\n", i);
2581 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002582
2583 ret = 1;
2584 goto cleanup;
2585 }
2586 }
2587
Jens Wiklander32b31802023-10-06 16:59:46 +02002588 if (verbose != 0) {
2589 mbedtls_printf("passed\n");
2590 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002591
2592cleanup:
2593
Jens Wiklander32b31802023-10-06 16:59:46 +02002594 if (ret != 0 && verbose != 0) {
2595 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2596 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002597
Jens Wiklander32b31802023-10-06 16:59:46 +02002598 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2599 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002600
Jens Wiklander32b31802023-10-06 16:59:46 +02002601 if (verbose != 0) {
2602 mbedtls_printf("\n");
2603 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002604
Jens Wiklander32b31802023-10-06 16:59:46 +02002605 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002606}
2607
2608#endif /* MBEDTLS_SELF_TEST */
2609
2610#endif /* MBEDTLS_BIGNUM_C */