blob: 7b8b966a64cdd37330a5007c8c1ff4cf6c8f1b2e [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);
Jens Wiklander02e95982024-12-12 11:56:46 +01001759 mbedtls_mpi_uint *T = mempool_calloc(mbedtls_mpi_mempool, T_limbs,
1760 sizeof(mbedtls_mpi_uint));
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001761 if (T == NULL) {
1762 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001763 }
1764
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001765 mbedtls_mpi RR;
Jens Wiklander5e0191a2018-11-08 11:18:22 +01001766 mbedtls_mpi_init_mempool(&RR);
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001767
Jens Wiklander817466c2018-05-22 13:49:31 +02001768 /*
1769 * If 1st call, pre-compute R^2 mod N
1770 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001771 if (prec_RR == NULL || prec_RR->p == NULL) {
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001772 MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001773
Jens Wiklander32b31802023-10-06 16:59:46 +02001774 if (prec_RR != NULL) {
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001775 *prec_RR = RR;
Jens Wiklander32b31802023-10-06 16:59:46 +02001776 }
1777 } else {
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001778 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
1779 RR = *prec_RR;
Jens Wiklander817466c2018-05-22 13:49:31 +02001780 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001781
1782 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001783 * To preserve constness we need to make a copy of A. Using X for this to
1784 * save memory.
Jens Wiklander817466c2018-05-22 13:49:31 +02001785 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001786 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
Jens Wiklander817466c2018-05-22 13:49:31 +02001787
1788 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001789 * Compensate for negative A (and correct at the end).
Jens Wiklander817466c2018-05-22 13:49:31 +02001790 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001791 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001792
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001793 /*
1794 * Make sure that X is in a form that is safe for consumption by
1795 * the core functions.
1796 *
1797 * - The core functions will not touch the limbs of X above N->n. The
1798 * result will be correct if those limbs are 0, which the mod call
1799 * ensures.
1800 * - Also, X must have at least as many limbs as N for the calls to the
1801 * core functions.
1802 */
1803 if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
1804 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001805 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001806 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
Jens Wiklander817466c2018-05-22 13:49:31 +02001807
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001808 /*
1809 * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
1810 */
1811 {
1812 mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
1813 mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
1814 if (E_public == MBEDTLS_MPI_IS_PUBLIC) {
1815 mbedtls_mpi_core_exp_mod_unsafe(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
1816 } else {
1817 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 +02001818 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001819 mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
Jens Wiklander817466c2018-05-22 13:49:31 +02001820 }
1821
1822 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001823 * Correct for negative A.
Jens Wiklander817466c2018-05-22 13:49:31 +02001824 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001825 if (A->s == -1 && (E->p[0] & 1) != 0) {
1826 mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
1827 X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001828
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001829 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001830 }
1831
Jens Wiklander817466c2018-05-22 13:49:31 +02001832cleanup:
1833
Jens Wiklander02e95982024-12-12 11:56:46 +01001834 mbedtls_mpi_zeroize(T, T_limbs);
1835 mempool_free(mbedtls_mpi_mempool, T);
Jens Wiklander817466c2018-05-22 13:49:31 +02001836
Jens Wiklander32b31802023-10-06 16:59:46 +02001837 if (prec_RR == NULL || prec_RR->p == NULL) {
1838 mbedtls_mpi_free(&RR);
1839 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001840
Jens Wiklander32b31802023-10-06 16:59:46 +02001841 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001842}
1843
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001844int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1845 const mbedtls_mpi *E, const mbedtls_mpi *N,
1846 mbedtls_mpi *prec_RR)
1847{
Sungbae Yoo85df2562024-11-21 14:21:29 +00001848#if (defined(__KERNEL__) && defined(CFG_CORE_UNSAFE_MODEXP)) || \
Alvin Chang470c1132025-03-20 16:26:30 +08001849 (!defined(__KERNEL__) && defined(CFG_TA_MBEDTLS_UNSAFE_MODEXP))
Sungbae Yoo85df2562024-11-21 14:21:29 +00001850 return mbedtls_mpi_exp_mod_unsafe(X, A, E, N, prec_RR);
1851#else
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001852 return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_SECRET, N, prec_RR);
Sungbae Yoo85df2562024-11-21 14:21:29 +00001853#endif
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001854}
1855
Jens Wiklanderbf7ce252018-11-07 08:11:29 +01001856
1857/*
1858 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1859 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001860int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,
1861 const mbedtls_mpi *E, const mbedtls_mpi *N,
1862 mbedtls_mpi *prec_RR)
1863{
1864 return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_PUBLIC, N, prec_RR);
1865}
1866
Jens Wiklander817466c2018-05-22 13:49:31 +02001867/*
1868 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1869 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001870int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001871{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001872 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001873 size_t lz, lzt;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001874 mbedtls_mpi TA, TB;
Jens Wiklander817466c2018-05-22 13:49:31 +02001875
Jens Wiklander5e0191a2018-11-08 11:18:22 +01001876 mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001877
Jens Wiklander32b31802023-10-06 16:59:46 +02001878 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1879 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001880
Jens Wiklander32b31802023-10-06 16:59:46 +02001881 lz = mbedtls_mpi_lsb(&TA);
1882 lzt = mbedtls_mpi_lsb(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001883
Jerome Forissier79013242021-07-28 10:24:04 +02001884 /* The loop below gives the correct result when A==0 but not when B==0.
1885 * So have a special case for B==0. Leverage the fact that we just
1886 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1887 * slightly more efficient than cmp_int(). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001888 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1889 ret = mbedtls_mpi_copy(G, A);
Jerome Forissier79013242021-07-28 10:24:04 +02001890 goto cleanup;
1891 }
1892
Jens Wiklander32b31802023-10-06 16:59:46 +02001893 if (lzt < lz) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001894 lz = lzt;
Jens Wiklander32b31802023-10-06 16:59:46 +02001895 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001896
Jens Wiklander817466c2018-05-22 13:49:31 +02001897 TA.s = TB.s = 1;
1898
Jerome Forissier79013242021-07-28 10:24:04 +02001899 /* We mostly follow the procedure described in HAC 14.54, but with some
1900 * minor differences:
1901 * - Sequences of multiplications or divisions by 2 are grouped into a
1902 * single shift operation.
1903 * - The procedure in HAC assumes that 0 < TB <= TA.
1904 * - The condition TB <= TA is not actually necessary for correctness.
1905 * TA and TB have symmetric roles except for the loop termination
1906 * condition, and the shifts at the beginning of the loop body
1907 * remove any significance from the ordering of TA vs TB before
1908 * the shifts.
1909 * - If TA = 0, the loop goes through 0 iterations and the result is
1910 * correctly TB.
1911 * - The case TB = 0 was short-circuited above.
1912 *
1913 * For the correctness proof below, decompose the original values of
1914 * A and B as
1915 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1916 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1917 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1918 * and gcd(A',B') is odd or 0.
1919 *
1920 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1921 * The code maintains the following invariant:
1922 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
1923 */
1924
1925 /* Proof that the loop terminates:
1926 * At each iteration, either the right-shift by 1 is made on a nonzero
1927 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
1928 * by at least 1, or the right-shift by 1 is made on zero and then
1929 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
1930 * since in that case TB is calculated from TB-TA with the condition TB>TA).
1931 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001932 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001933 /* Divisions by 2 preserve the invariant (I). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001934 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
1935 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001936
Jerome Forissier79013242021-07-28 10:24:04 +02001937 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
1938 * TA-TB is even so the division by 2 has an integer result.
1939 * Invariant (I) is preserved since any odd divisor of both TA and TB
1940 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Jerome Forissier039e02d2022-08-09 17:10:15 +02001941 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Jerome Forissier79013242021-07-28 10:24:04 +02001942 * divides TA.
1943 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001944 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
1945 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
1946 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
1947 } else {
1948 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
1949 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001950 }
Jerome Forissier79013242021-07-28 10:24:04 +02001951 /* Note that one of TA or TB is still odd. */
Jens Wiklander817466c2018-05-22 13:49:31 +02001952 }
1953
Jerome Forissier79013242021-07-28 10:24:04 +02001954 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
1955 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
1956 * - If there was at least one loop iteration, then one of TA or TB is odd,
1957 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
1958 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
1959 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
1960 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
1961 */
1962
Jens Wiklander32b31802023-10-06 16:59:46 +02001963 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
1964 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Jens Wiklander817466c2018-05-22 13:49:31 +02001965
1966cleanup:
1967
Jens Wiklander32b31802023-10-06 16:59:46 +02001968 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001969
Jens Wiklander32b31802023-10-06 16:59:46 +02001970 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001971}
1972
Jens Wiklander817466c2018-05-22 13:49:31 +02001973/*
1974 * Fill X with size bytes of random.
Jens Wiklander32b31802023-10-06 16:59:46 +02001975 * The bytes returned from the RNG are used in a specific order which
1976 * is suitable for deterministic ECDSA (see the specification of
1977 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Jens Wiklander817466c2018-05-22 13:49:31 +02001978 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001979int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
1980 int (*f_rng)(void *, unsigned char *, size_t),
1981 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02001982{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001983 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001984 const size_t limbs = CHARS_TO_LIMBS(size);
Jerome Forissier5b25c762020-04-07 11:18:49 +02001985
Jerome Forissier5b25c762020-04-07 11:18:49 +02001986 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +02001987 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
1988 if (size == 0) {
1989 return 0;
1990 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001991
Jens Wiklander32b31802023-10-06 16:59:46 +02001992 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02001993
1994cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001995 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001996}
1997
Jens Wiklander32b31802023-10-06 16:59:46 +02001998int mbedtls_mpi_random(mbedtls_mpi *X,
1999 mbedtls_mpi_sint min,
2000 const mbedtls_mpi *N,
2001 int (*f_rng)(void *, unsigned char *, size_t),
2002 void *p_rng)
Jerome Forissier79013242021-07-28 10:24:04 +02002003{
Jens Wiklander32b31802023-10-06 16:59:46 +02002004 if (min < 0) {
2005 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2006 }
2007 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2008 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2009 }
Jerome Forissier79013242021-07-28 10:24:04 +02002010
2011 /* Ensure that target MPI has exactly the same number of limbs
2012 * as the upper bound, even if the upper bound has leading zeros.
Jens Wiklander32b31802023-10-06 16:59:46 +02002013 * This is necessary for mbedtls_mpi_core_random. */
2014 int ret = mbedtls_mpi_resize_clear(X, N->n);
2015 if (ret != 0) {
2016 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02002017 }
Jerome Forissier79013242021-07-28 10:24:04 +02002018
Jens Wiklander32b31802023-10-06 16:59:46 +02002019 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Jerome Forissier79013242021-07-28 10:24:04 +02002020}
2021
Jens Wiklander817466c2018-05-22 13:49:31 +02002022/*
2023 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2024 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002025int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Jens Wiklander817466c2018-05-22 13:49:31 +02002026{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02002027 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02002028 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
2029
Jens Wiklander32b31802023-10-06 16:59:46 +02002030 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2031 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2032 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002033
Jens Wiklander5e0191a2018-11-08 11:18:22 +01002034 mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TU);
2035 mbedtls_mpi_init_mempool(&U1); mbedtls_mpi_init_mempool(&U2);
2036 mbedtls_mpi_init_mempool(&G); mbedtls_mpi_init_mempool(&TB);
2037 mbedtls_mpi_init_mempool(&TV); mbedtls_mpi_init_mempool(&V1);
2038 mbedtls_mpi_init_mempool(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02002039
Jens Wiklander32b31802023-10-06 16:59:46 +02002040 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002041
Jens Wiklander32b31802023-10-06 16:59:46 +02002042 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002043 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2044 goto cleanup;
2045 }
2046
Jens Wiklander32b31802023-10-06 16:59:46 +02002047 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2048 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2049 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2050 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002051
Jens Wiklander32b31802023-10-06 16:59:46 +02002052 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2053 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2054 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2055 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002056
Jens Wiklander32b31802023-10-06 16:59:46 +02002057 do {
2058 while ((TU.p[0] & 1) == 0) {
2059 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002060
Jens Wiklander32b31802023-10-06 16:59:46 +02002061 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2062 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2063 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02002064 }
2065
Jens Wiklander32b31802023-10-06 16:59:46 +02002066 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2067 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002068 }
2069
Jens Wiklander32b31802023-10-06 16:59:46 +02002070 while ((TV.p[0] & 1) == 0) {
2071 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002072
Jens Wiklander32b31802023-10-06 16:59:46 +02002073 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2074 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2075 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02002076 }
2077
Jens Wiklander32b31802023-10-06 16:59:46 +02002078 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2079 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002080 }
2081
Jens Wiklander32b31802023-10-06 16:59:46 +02002082 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2083 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2084 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2085 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2086 } else {
2087 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2088 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2089 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Jens Wiklander817466c2018-05-22 13:49:31 +02002090 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002091 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2092
2093 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2094 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002095 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002096
Jens Wiklander32b31802023-10-06 16:59:46 +02002097 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2098 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2099 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002100
Jens Wiklander32b31802023-10-06 16:59:46 +02002101 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002102
2103cleanup:
2104
Jens Wiklander32b31802023-10-06 16:59:46 +02002105 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2106 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2107 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02002108
Jens Wiklander32b31802023-10-06 16:59:46 +02002109 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002110}
2111
2112#if defined(MBEDTLS_GENPRIME)
2113
Tom Van Eyckb0563632024-06-13 16:20:14 +02002114/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
2115static const unsigned char small_prime_gaps[] = {
2116 2, 2, 4, 2, 4, 2, 4, 6,
2117 2, 6, 4, 2, 4, 6, 6, 2,
2118 6, 4, 2, 6, 4, 6, 8, 4,
2119 2, 4, 2, 4, 14, 4, 6, 2,
2120 10, 2, 6, 6, 4, 6, 6, 2,
2121 10, 2, 4, 2, 12, 12, 4, 2,
2122 4, 6, 2, 10, 6, 6, 6, 2,
2123 6, 4, 2, 10, 14, 4, 2, 4,
2124 14, 6, 10, 2, 4, 6, 8, 6,
2125 6, 4, 6, 8, 4, 8, 10, 2,
2126 10, 2, 6, 4, 6, 8, 4, 2,
2127 4, 12, 8, 4, 8, 4, 6, 12,
2128 2, 18, 6, 10, 6, 6, 2, 6,
2129 10, 6, 6, 2, 6, 6, 4, 2,
2130 12, 10, 2, 4, 6, 6, 2, 12,
2131 4, 6, 8, 10, 8, 10, 8, 6,
2132 6, 4, 8, 6, 4, 8, 4, 14,
2133 10, 12, 2, 10, 2, 4, 2, 10,
2134 14, 4, 2, 4, 14, 4, 2, 4,
2135 20, 4, 8, 10, 8, 4, 6, 6,
2136 14, 4, 6, 6, 8, 6, /*reaches 997*/
2137 0 /* the last entry is effectively unused */
Jens Wiklander817466c2018-05-22 13:49:31 +02002138};
2139
2140/*
2141 * Small divisors test (X must be positive)
2142 *
2143 * Return values:
2144 * 0: no small factor (possible prime, more tests needed)
2145 * 1: certain prime
2146 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2147 * other negative: error
2148 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002149static int mpi_check_small_factors(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +02002150{
2151 int ret = 0;
2152 size_t i;
2153 mbedtls_mpi_uint r;
Tom Van Eyckb0563632024-06-13 16:20:14 +02002154 unsigned p = 3; /* The first odd prime */
Jens Wiklander817466c2018-05-22 13:49:31 +02002155
Jens Wiklander32b31802023-10-06 16:59:46 +02002156 if ((X->p[0] & 1) == 0) {
2157 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2158 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002159
Tom Van Eyckb0563632024-06-13 16:20:14 +02002160 for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2161 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
Jens Wiklander32b31802023-10-06 16:59:46 +02002162 if (r == 0) {
Tom Van Eyckb0563632024-06-13 16:20:14 +02002163 if (mbedtls_mpi_cmp_int(X, p) == 0) {
2164 return 1;
2165 } else {
2166 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2167 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002168 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002169 }
2170
2171cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002172 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002173}
2174
2175/*
2176 * Miller-Rabin pseudo-primality test (HAC 4.24)
2177 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002178static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2179 int (*f_rng)(void *, unsigned char *, size_t),
2180 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002181{
2182 int ret, count;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002183 size_t i, j, k, s;
Jens Wiklander817466c2018-05-22 13:49:31 +02002184 mbedtls_mpi W, R, T, A, RR;
2185
Jens Wiklander5e0191a2018-11-08 11:18:22 +01002186 mbedtls_mpi_init_mempool(&W); mbedtls_mpi_init_mempool(&R);
2187 mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A);
2188 mbedtls_mpi_init_mempool(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002189
2190 /*
2191 * W = |X| - 1
2192 * R = W >> lsb( W )
2193 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002194 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2195 s = mbedtls_mpi_lsb(&W);
2196 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2197 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Jens Wiklander817466c2018-05-22 13:49:31 +02002198
Jens Wiklander32b31802023-10-06 16:59:46 +02002199 for (i = 0; i < rounds; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002200 /*
2201 * pick a random A, 1 < A < |X| - 1
2202 */
Jens Wiklander817466c2018-05-22 13:49:31 +02002203 count = 0;
2204 do {
Jens Wiklander32b31802023-10-06 16:59:46 +02002205 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +02002206
Jens Wiklander32b31802023-10-06 16:59:46 +02002207 j = mbedtls_mpi_bitlen(&A);
2208 k = mbedtls_mpi_bitlen(&W);
Jens Wiklander817466c2018-05-22 13:49:31 +02002209 if (j > k) {
Jens Wiklander32b31802023-10-06 16:59:46 +02002210 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002211 }
2212
Jens Wiklander65e7ec82018-11-27 12:21:24 +01002213 if (count++ > 300) {
Jens Wiklander336e3292019-01-17 11:14:38 +01002214 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2215 goto cleanup;
Jens Wiklander817466c2018-05-22 13:49:31 +02002216 }
2217
Jens Wiklander32b31802023-10-06 16:59:46 +02002218 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2219 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02002220
2221 /*
2222 * A = A^R mod |X|
2223 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002224 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Jens Wiklander817466c2018-05-22 13:49:31 +02002225
Jens Wiklander32b31802023-10-06 16:59:46 +02002226 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2227 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002228 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +02002229 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002230
2231 j = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02002232 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002233 /*
2234 * A = A * A mod |X|
2235 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002236 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2237 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02002238
Jens Wiklander32b31802023-10-06 16:59:46 +02002239 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002240 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02002241 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002242
2243 j++;
2244 }
2245
2246 /*
2247 * not prime if A != |X| - 1 or A == 1
2248 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002249 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2250 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002251 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2252 break;
2253 }
2254 }
2255
2256cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002257 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2258 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2259 mbedtls_mpi_free(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002260
Jens Wiklander32b31802023-10-06 16:59:46 +02002261 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002262}
2263
2264/*
2265 * Pseudo-primality test: small factors, then Miller-Rabin
2266 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002267int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2268 int (*f_rng)(void *, unsigned char *, size_t),
2269 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002270{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02002271 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02002272 mbedtls_mpi XX;
2273
2274 XX.s = 1;
2275 XX.n = X->n;
2276 XX.p = X->p;
2277
Jens Wiklander32b31802023-10-06 16:59:46 +02002278 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2279 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2280 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002281 }
2282
Jens Wiklander32b31802023-10-06 16:59:46 +02002283 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2284 return 0;
2285 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002286
Jens Wiklander32b31802023-10-06 16:59:46 +02002287 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2288 if (ret == 1) {
2289 return 0;
2290 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002291
Jens Wiklander32b31802023-10-06 16:59:46 +02002292 return ret;
2293 }
2294
2295 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002296}
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002297
Jens Wiklander817466c2018-05-22 13:49:31 +02002298/*
2299 * Prime number generation
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002300 *
2301 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2302 * be either 1024 bits or 1536 bits long, and flags must contain
2303 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Jens Wiklander817466c2018-05-22 13:49:31 +02002304 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002305int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2306 int (*f_rng)(void *, unsigned char *, size_t),
2307 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002308{
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002309#ifdef MBEDTLS_HAVE_INT64
2310// ceil(2^63.5)
2311#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2312#else
2313// ceil(2^31.5)
2314#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2315#endif
2316 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002317 size_t k, n;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002318 int rounds;
Jens Wiklander817466c2018-05-22 13:49:31 +02002319 mbedtls_mpi_uint r;
2320 mbedtls_mpi Y;
2321
Jens Wiklander32b31802023-10-06 16:59:46 +02002322 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2323 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2324 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002325
Jens Wiklander5e0191a2018-11-08 11:18:22 +01002326 mbedtls_mpi_init_mempool(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002327
Jens Wiklander32b31802023-10-06 16:59:46 +02002328 n = BITS_TO_LIMBS(nbits);
Jens Wiklander817466c2018-05-22 13:49:31 +02002329
Jens Wiklander32b31802023-10-06 16:59:46 +02002330 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002331 /*
2332 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2333 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002334 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2335 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2336 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2337 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002338 /*
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002339 * 2^-100 error probability, number of rounds computed based on HAC,
2340 * fact 4.48
Jens Wiklander817466c2018-05-22 13:49:31 +02002341 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002342 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2343 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2344 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2345 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002346 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002347
Jens Wiklander32b31802023-10-06 16:59:46 +02002348 while (1) {
2349 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002350 /* 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 +02002351 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2352 continue;
2353 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002354
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002355 k = n * biL;
Jens Wiklander32b31802023-10-06 16:59:46 +02002356 if (k > nbits) {
2357 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2358 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002359 X->p[0] |= 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002360
Jens Wiklander32b31802023-10-06 16:59:46 +02002361 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2362 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02002363
Jens Wiklander32b31802023-10-06 16:59:46 +02002364 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002365 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002366 }
2367 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002368 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02002369 * A necessary condition for Y and X = 2Y + 1 to be prime
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002370 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2371 * Make sure it is satisfied, while keeping X = 3 mod 4
Jens Wiklander817466c2018-05-22 13:49:31 +02002372 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002373
2374 X->p[0] |= 2;
2375
Jens Wiklander32b31802023-10-06 16:59:46 +02002376 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2377 if (r == 0) {
2378 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2379 } else if (r == 1) {
2380 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2381 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002382
2383 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Jens Wiklander32b31802023-10-06 16:59:46 +02002384 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2385 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002386
Jens Wiklander32b31802023-10-06 16:59:46 +02002387 while (1) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002388 /*
2389 * First, check small factors for X and Y
2390 * before doing Miller-Rabin on any of them
2391 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002392 if ((ret = mpi_check_small_factors(X)) == 0 &&
2393 (ret = mpi_check_small_factors(&Y)) == 0 &&
2394 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2395 == 0 &&
2396 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2397 == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002398 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002399 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002400
Jens Wiklander32b31802023-10-06 16:59:46 +02002401 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002402 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002403 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002404
2405 /*
2406 * Next candidates. We want to preserve Y = (X-1) / 2 and
2407 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2408 * so up Y by 6 and X by 12.
2409 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002410 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2411 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002412 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002413 }
2414 }
2415
2416cleanup:
2417
Jens Wiklander32b31802023-10-06 16:59:46 +02002418 mbedtls_mpi_free(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002419
Jens Wiklander32b31802023-10-06 16:59:46 +02002420 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002421}
2422
2423#endif /* MBEDTLS_GENPRIME */
2424
2425#if defined(MBEDTLS_SELF_TEST)
2426
2427#define GCD_PAIR_COUNT 3
2428
2429static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2430{
2431 { 693, 609, 21 },
2432 { 1764, 868, 28 },
2433 { 768454923, 542167814, 1 }
2434};
2435
2436/*
2437 * Checkup routine
2438 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002439int mbedtls_mpi_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +02002440{
2441 int ret, i;
2442 mbedtls_mpi A, E, N, X, Y, U, V;
2443
Jens Wiklander5e0191a2018-11-08 11:18:22 +01002444 mbedtls_mpi_init_mempool(&A); mbedtls_mpi_init_mempool(&E);
2445 mbedtls_mpi_init_mempool(&N); mbedtls_mpi_init_mempool(&X);
2446 mbedtls_mpi_init_mempool(&Y); mbedtls_mpi_init_mempool(&U);
2447 mbedtls_mpi_init_mempool(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002448
Jens Wiklander32b31802023-10-06 16:59:46 +02002449 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2450 "EFE021C2645FD1DC586E69184AF4A31E" \
2451 "D5F53E93B5F123FA41680867BA110131" \
2452 "944FE7952E2517337780CB0DB80E61AA" \
2453 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002454
Jens Wiklander32b31802023-10-06 16:59:46 +02002455 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2456 "B2E7EFD37075B9F03FF989C7C5051C20" \
2457 "34D2A323810251127E7BF8625A4F49A5" \
2458 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2459 "5B5C25763222FEFCCFC38B832366C29E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002460
Jens Wiklander32b31802023-10-06 16:59:46 +02002461 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2462 "0066A198186C18C10B2F5ED9B522752A" \
2463 "9830B69916E535C8F047518A889A43A5" \
2464 "94B6BED27A168D31D4A52F88925AA8F5"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002465
Jens Wiklander32b31802023-10-06 16:59:46 +02002466 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002467
Jens Wiklander32b31802023-10-06 16:59:46 +02002468 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2469 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2470 "9E857EA95A03512E2BAE7391688D264A" \
2471 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2472 "8001B72E848A38CAE1C65F78E56ABDEF" \
2473 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2474 "ECF677152EF804370C1A305CAF3B5BF1" \
2475 "30879B56C61DE584A0F53A2447A51E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002476
Jens Wiklander32b31802023-10-06 16:59:46 +02002477 if (verbose != 0) {
2478 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2479 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002480
Jens Wiklander32b31802023-10-06 16:59:46 +02002481 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2482 if (verbose != 0) {
2483 mbedtls_printf("failed\n");
2484 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002485
2486 ret = 1;
2487 goto cleanup;
2488 }
2489
Jens Wiklander32b31802023-10-06 16:59:46 +02002490 if (verbose != 0) {
2491 mbedtls_printf("passed\n");
2492 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002493
Jens Wiklander32b31802023-10-06 16:59:46 +02002494 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002495
Jens Wiklander32b31802023-10-06 16:59:46 +02002496 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2497 "256567336059E52CAE22925474705F39A94"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002498
Jens Wiklander32b31802023-10-06 16:59:46 +02002499 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2500 "6613F26162223DF488E9CD48CC132C7A" \
2501 "0AC93C701B001B092E4E5B9F73BCD27B" \
2502 "9EE50D0657C77F374E903CDFA4C642"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002503
Jens Wiklander32b31802023-10-06 16:59:46 +02002504 if (verbose != 0) {
2505 mbedtls_printf(" MPI test #2 (div_mpi): ");
2506 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002507
Jens Wiklander32b31802023-10-06 16:59:46 +02002508 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2509 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2510 if (verbose != 0) {
2511 mbedtls_printf("failed\n");
2512 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002513
2514 ret = 1;
2515 goto cleanup;
2516 }
2517
Jens Wiklander32b31802023-10-06 16:59:46 +02002518 if (verbose != 0) {
2519 mbedtls_printf("passed\n");
2520 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002521
Jens Wiklander32b31802023-10-06 16:59:46 +02002522 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Jens Wiklander817466c2018-05-22 13:49:31 +02002523
Jens Wiklander32b31802023-10-06 16:59:46 +02002524 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2525 "36E139AEA55215609D2816998ED020BB" \
2526 "BD96C37890F65171D948E9BC7CBAA4D9" \
2527 "325D24D6A3C12710F10A09FA08AB87"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002528
Jens Wiklander32b31802023-10-06 16:59:46 +02002529 if (verbose != 0) {
2530 mbedtls_printf(" MPI test #3 (exp_mod): ");
2531 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002532
Jens Wiklander32b31802023-10-06 16:59:46 +02002533 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2534 if (verbose != 0) {
2535 mbedtls_printf("failed\n");
2536 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002537
2538 ret = 1;
2539 goto cleanup;
2540 }
2541
Jens Wiklander32b31802023-10-06 16:59:46 +02002542 if (verbose != 0) {
2543 mbedtls_printf("passed\n");
2544 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002545
Jens Wiklander32b31802023-10-06 16:59:46 +02002546 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002547
Jens Wiklander32b31802023-10-06 16:59:46 +02002548 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2549 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2550 "C3DBA76456363A10869622EAC2DD84EC" \
2551 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002552
Jens Wiklander32b31802023-10-06 16:59:46 +02002553 if (verbose != 0) {
2554 mbedtls_printf(" MPI test #4 (inv_mod): ");
2555 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002556
Jens Wiklander32b31802023-10-06 16:59:46 +02002557 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2558 if (verbose != 0) {
2559 mbedtls_printf("failed\n");
2560 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002561
2562 ret = 1;
2563 goto cleanup;
2564 }
2565
Jens Wiklander32b31802023-10-06 16:59:46 +02002566 if (verbose != 0) {
2567 mbedtls_printf("passed\n");
2568 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002569
Jens Wiklander32b31802023-10-06 16:59:46 +02002570 if (verbose != 0) {
2571 mbedtls_printf(" MPI test #5 (simple gcd): ");
2572 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002573
Jens Wiklander32b31802023-10-06 16:59:46 +02002574 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2575 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2576 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Jens Wiklander817466c2018-05-22 13:49:31 +02002577
Jens Wiklander32b31802023-10-06 16:59:46 +02002578 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02002579
Jens Wiklander32b31802023-10-06 16:59:46 +02002580 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2581 if (verbose != 0) {
2582 mbedtls_printf("failed at %d\n", i);
2583 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002584
2585 ret = 1;
2586 goto cleanup;
2587 }
2588 }
2589
Jens Wiklander32b31802023-10-06 16:59:46 +02002590 if (verbose != 0) {
2591 mbedtls_printf("passed\n");
2592 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002593
2594cleanup:
2595
Jens Wiklander32b31802023-10-06 16:59:46 +02002596 if (ret != 0 && verbose != 0) {
2597 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2598 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002599
Jens Wiklander32b31802023-10-06 16:59:46 +02002600 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2601 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002602
Jens Wiklander32b31802023-10-06 16:59:46 +02002603 if (verbose != 0) {
2604 mbedtls_printf("\n");
2605 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002606
Jens Wiklander32b31802023-10-06 16:59:46 +02002607 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002608}
2609
2610#endif /* MBEDTLS_SELF_TEST */
2611
2612#endif /* MBEDTLS_BIGNUM_C */