blob: 539ddfe015faa2b36bb4598f498ae0f5acb9b3c1 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * Multi-precision integer library
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
Tom Van Eyckc1633172024-04-09 18:44:13 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7
8/*
9 * The following sources were referenced in the design of this Multi-precision
10 * Integer library:
11 *
12 * [1] Handbook of Applied Cryptography - 1997
13 * Menezes, van Oorschot and Vanstone
14 *
15 * [2] Multi-Precision Math
16 * Tom St Denis
17 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
18 *
19 * [3] GNU Multi-Precision Arithmetic Library
20 * https://gmplib.org/manual/index.html
21 *
22 */
23
Jerome Forissier79013242021-07-28 10:24:04 +020024#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020025
26#if defined(MBEDTLS_BIGNUM_C)
27
28#include "mbedtls/bignum.h"
Jens Wiklander32b31802023-10-06 16:59:46 +020029#include "bignum_core.h"
30#include "bn_mul.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010031#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020032#include "mbedtls/error.h"
Jerome Forissier039e02d2022-08-09 17:10:15 +020033#include "constant_time_internal.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020034
Jerome Forissier039e02d2022-08-09 17:10:15 +020035#include <limits.h>
Jens Wiklander817466c2018-05-22 13:49:31 +020036#include <string.h>
37
Jens Wiklander817466c2018-05-22 13:49:31 +020038#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020039
Jens Wiklander98bd5fe2018-11-08 11:18:22 +010040
Jens Wiklander817466c2018-05-22 13:49:31 +020041
Tom Van Eyckc1633172024-04-09 18:44:13 +020042/*
43 * Conditionally select an MPI sign in constant time.
44 * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid
45 * values.)
46 */
47static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,
48 signed short sign1, signed short sign2)
49{
50 return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;
51}
Jens Wiklander817466c2018-05-22 13:49:31 +020052
Tom Van Eyckc1633172024-04-09 18:44:13 +020053/*
54 * Compare signed values in constant time
55 */
56int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
57 const mbedtls_mpi *Y,
58 unsigned *ret)
59{
60 mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
61
62 if (X->n != Y->n) {
63 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
64 }
65
66 /*
67 * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.
68 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
69 */
70 X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
71 Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
72
73 /*
74 * If the signs are different, then the positive operand is the bigger.
75 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
76 * is false if X is positive (X_is_negative == 0).
77 */
78 different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
79 result = mbedtls_ct_bool_and(different_sign, X_is_negative);
80
81 /*
82 * Assuming signs are the same, compare X and Y. We switch the comparison
83 * order if they are negative so that we get the right result, regardles of
84 * sign.
85 */
86
87 /* This array is used to conditionally swap the pointers in const time */
88 void * const p[2] = { X->p, Y->p };
89 size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
90 mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
91
92 /*
93 * Store in result iff the signs are the same (i.e., iff different_sign == false). If
94 * the signs differ, result has already been set, so we don't change it.
95 */
96 result = mbedtls_ct_bool_or(result,
97 mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
98
99 *ret = mbedtls_ct_uint_if_else_0(result, 1);
100
101 return 0;
102}
103
104/*
105 * Conditionally assign X = Y, without leaking information
106 * about whether the assignment was made or not.
107 * (Leaking information about the respective sizes of X and Y is ok however.)
108 */
109#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
110 (_MSC_FULL_VER < 193131103)
111/*
112 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
113 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
114 */
115__declspec(noinline)
116#endif
117int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
118 const mbedtls_mpi *Y,
119 unsigned char assign)
120{
121 int ret = 0;
122
123 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
124
125 {
126 mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
127
128 X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);
129
130 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
131
132 mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
133 for (size_t i = Y->n; i < X->n; i++) {
134 X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
135 }
136 }
137
138cleanup:
139 return ret;
140}
141
142/*
143 * Conditionally swap X and Y, without leaking information
144 * about whether the swap was made or not.
145 * Here it is not ok to simply swap the pointers, which would lead to
146 * different memory access patterns when X and Y are used afterwards.
147 */
148int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
149 mbedtls_mpi *Y,
150 unsigned char swap)
151{
152 int ret = 0;
153 int s;
154
155 if (X == Y) {
156 return 0;
157 }
158
159 mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
160
161 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
162 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
163
164 s = X->s;
165 X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);
166 Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);
167
168 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
169
170cleanup:
171 return ret;
172}
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100173
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100174/* Implementation that should never be optimized out by the compiler */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200175#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100176
Jens Wiklander817466c2018-05-22 13:49:31 +0200177/*
178 * Initialize one MPI
179 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200180void mbedtls_mpi_init(mbedtls_mpi *X)
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100181{
Tom Van Eyckc1633172024-04-09 18:44:13 +0200182 X->s = 1;
183 X->n = 0;
184 X->p = NULL;
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100185}
186
Jens Wiklander817466c2018-05-22 13:49:31 +0200187/*
188 * Unallocate one MPI
189 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200190void mbedtls_mpi_free(mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200191{
Jens Wiklander32b31802023-10-06 16:59:46 +0200192 if (X == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200193 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200194 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200195
Jens Wiklander32b31802023-10-06 16:59:46 +0200196 if (X->p != NULL) {
Tom Van Eyckc1633172024-04-09 18:44:13 +0200197 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200198 }
199
200 X->s = 1;
201 X->n = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100202 X->p = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200203}
204
205/*
206 * Enlarge to the specified number of limbs
207 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200208int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Jens Wiklander817466c2018-05-22 13:49:31 +0200209{
210 mbedtls_mpi_uint *p;
211
Jens Wiklander32b31802023-10-06 16:59:46 +0200212 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
213 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
214 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200215
Jens Wiklander32b31802023-10-06 16:59:46 +0200216 if (X->n < nblimbs) {
Tom Van Eyckc1633172024-04-09 18:44:13 +0200217 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
218 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100219 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200220
Jens Wiklander32b31802023-10-06 16:59:46 +0200221 if (X->p != NULL) {
222 memcpy(p, X->p, X->n * ciL);
Tom Van Eyckc1633172024-04-09 18:44:13 +0200223 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100224 }
225
Tom Van Eyckc1633172024-04-09 18:44:13 +0200226 /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
227 * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
228 X->n = (unsigned short) nblimbs;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100229 X->p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +0200230 }
231
Jens Wiklander32b31802023-10-06 16:59:46 +0200232 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200233}
234
235/*
236 * Resize down as much as possible,
237 * while keeping at least the specified number of limbs
238 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200239int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Jens Wiklander817466c2018-05-22 13:49:31 +0200240{
241 mbedtls_mpi_uint *p;
242 size_t i;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100243
Jens Wiklander32b31802023-10-06 16:59:46 +0200244 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
245 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
246 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200247
Jerome Forissier5b25c762020-04-07 11:18:49 +0200248 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200249 if (X->n <= nblimbs) {
250 return mbedtls_mpi_grow(X, nblimbs);
251 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200252 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Jens Wiklander817466c2018-05-22 13:49:31 +0200253
Jens Wiklander32b31802023-10-06 16:59:46 +0200254 for (i = X->n - 1; i > 0; i--) {
255 if (X->p[i] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200256 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200257 }
258 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200259 i++;
260
Jens Wiklander32b31802023-10-06 16:59:46 +0200261 if (i < nblimbs) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200262 i = nblimbs;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100263 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200264
Tom Van Eyckc1633172024-04-09 18:44:13 +0200265 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
266 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200267 }
268
269 if (X->p != NULL) {
270 memcpy(p, X->p, i * ciL);
Tom Van Eyckc1633172024-04-09 18:44:13 +0200271 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200272 }
273
Tom Van Eyckc1633172024-04-09 18:44:13 +0200274 /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
275 * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
276 X->n = (unsigned short) i;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100277 X->p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +0200278
Jens Wiklander32b31802023-10-06 16:59:46 +0200279 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200280}
281
Jerome Forissier79013242021-07-28 10:24:04 +0200282/* Resize X to have exactly n limbs and set it to 0. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200283static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Jerome Forissier79013242021-07-28 10:24:04 +0200284{
Jens Wiklander32b31802023-10-06 16:59:46 +0200285 if (limbs == 0) {
286 mbedtls_mpi_free(X);
287 return 0;
288 } else if (X->n == limbs) {
289 memset(X->p, 0, limbs * ciL);
Jerome Forissier79013242021-07-28 10:24:04 +0200290 X->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200291 return 0;
292 } else {
293 mbedtls_mpi_free(X);
294 return mbedtls_mpi_grow(X, limbs);
Jerome Forissier79013242021-07-28 10:24:04 +0200295 }
296}
297
Jens Wiklander817466c2018-05-22 13:49:31 +0200298/*
Jerome Forissier79013242021-07-28 10:24:04 +0200299 * Copy the contents of Y into X.
300 *
301 * This function is not constant-time. Leading zeros in Y may be removed.
302 *
303 * Ensure that X does not shrink. This is not guaranteed by the public API,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200304 * but some code in the bignum module might still rely on this property.
Jens Wiklander817466c2018-05-22 13:49:31 +0200305 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200306int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200307{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100308 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200309 size_t i;
310
Jens Wiklander32b31802023-10-06 16:59:46 +0200311 if (X == Y) {
312 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200313 }
314
Jens Wiklander32b31802023-10-06 16:59:46 +0200315 if (Y->n == 0) {
316 if (X->n != 0) {
317 X->s = 1;
318 memset(X->p, 0, X->n * ciL);
319 }
320 return 0;
321 }
322
323 for (i = Y->n - 1; i > 0; i--) {
324 if (Y->p[i] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200325 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200326 }
327 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200328 i++;
329
330 X->s = Y->s;
331
Jens Wiklander32b31802023-10-06 16:59:46 +0200332 if (X->n < i) {
333 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
334 } else {
335 memset(X->p + i, 0, (X->n - i) * ciL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100336 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200337
Jens Wiklander32b31802023-10-06 16:59:46 +0200338 memcpy(X->p, Y->p, i * ciL);
Jens Wiklander817466c2018-05-22 13:49:31 +0200339
340cleanup:
341
Jens Wiklander32b31802023-10-06 16:59:46 +0200342 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200343}
344
345/*
346 * Swap the contents of X and Y
347 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200348void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200349{
350 mbedtls_mpi T;
351
Jens Wiklander32b31802023-10-06 16:59:46 +0200352 memcpy(&T, X, sizeof(mbedtls_mpi));
353 memcpy(X, Y, sizeof(mbedtls_mpi));
354 memcpy(Y, &T, sizeof(mbedtls_mpi));
355}
356
357static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
358{
359 if (z >= 0) {
360 return z;
361 }
362 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
363 * A naive -z would have undefined behavior.
364 * Write this in a way that makes popular compilers happy (GCC, Clang,
365 * MSVC). */
366 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Jens Wiklander817466c2018-05-22 13:49:31 +0200367}
368
Tom Van Eyckc1633172024-04-09 18:44:13 +0200369/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
370 * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
371#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
372
Jens Wiklander817466c2018-05-22 13:49:31 +0200373/*
374 * Set value from integer
375 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200376int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Jens Wiklander817466c2018-05-22 13:49:31 +0200377{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200378 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200379
Jens Wiklander32b31802023-10-06 16:59:46 +0200380 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
381 memset(X->p, 0, X->n * ciL);
Jens Wiklander817466c2018-05-22 13:49:31 +0200382
Jens Wiklander32b31802023-10-06 16:59:46 +0200383 X->p[0] = mpi_sint_abs(z);
Tom Van Eyckc1633172024-04-09 18:44:13 +0200384 X->s = TO_SIGN(z);
Jens Wiklander817466c2018-05-22 13:49:31 +0200385
386cleanup:
387
Jens Wiklander32b31802023-10-06 16:59:46 +0200388 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200389}
390
391/*
392 * Get a specific bit
393 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200394int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Jens Wiklander817466c2018-05-22 13:49:31 +0200395{
Jens Wiklander32b31802023-10-06 16:59:46 +0200396 if (X->n * biL <= pos) {
397 return 0;
398 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200399
Jens Wiklander32b31802023-10-06 16:59:46 +0200400 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Jens Wiklander817466c2018-05-22 13:49:31 +0200401}
402
403/*
404 * Set a bit to a specific value of 0 or 1
405 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200406int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Jens Wiklander817466c2018-05-22 13:49:31 +0200407{
408 int ret = 0;
409 size_t off = pos / biL;
410 size_t idx = pos % biL;
411
Jens Wiklander32b31802023-10-06 16:59:46 +0200412 if (val != 0 && val != 1) {
413 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200414 }
415
Jens Wiklander32b31802023-10-06 16:59:46 +0200416 if (X->n * biL <= pos) {
417 if (val == 0) {
418 return 0;
419 }
420
421 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
422 }
423
424 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200425 X->p[off] |= (mbedtls_mpi_uint) val << idx;
426
427cleanup:
428
Jens Wiklander32b31802023-10-06 16:59:46 +0200429 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200430}
431
432/*
433 * Return the number of less significant zero-bits
434 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200435size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200436{
Tom Van Eyckc1633172024-04-09 18:44:13 +0200437 size_t i;
Jens Wiklander817466c2018-05-22 13:49:31 +0200438
Tom Van Eyckc1633172024-04-09 18:44:13 +0200439#if defined(__has_builtin)
440#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
441 #define mbedtls_mpi_uint_ctz __builtin_ctz
442#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
443 #define mbedtls_mpi_uint_ctz __builtin_ctzl
444#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
445 #define mbedtls_mpi_uint_ctz __builtin_ctzll
446#endif
447#endif
448
449#if defined(mbedtls_mpi_uint_ctz)
Jens Wiklander32b31802023-10-06 16:59:46 +0200450 for (i = 0; i < X->n; i++) {
Tom Van Eyckc1633172024-04-09 18:44:13 +0200451 if (X->p[i] != 0) {
452 return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
453 }
454 }
455#else
456 size_t count = 0;
457 for (i = 0; i < X->n; i++) {
458 for (size_t j = 0; j < biL; j++, count++) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200459 if (((X->p[i] >> j) & 1) != 0) {
460 return count;
461 }
462 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200463 }
Tom Van Eyckc1633172024-04-09 18:44:13 +0200464#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200465
Jens Wiklander32b31802023-10-06 16:59:46 +0200466 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200467}
468
469/*
470 * Return the number of bits
471 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200472size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200473{
Jens Wiklander32b31802023-10-06 16:59:46 +0200474 return mbedtls_mpi_core_bitlen(X->p, X->n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200475}
476
477/*
478 * Return the total size in bytes
479 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200480size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200481{
Jens Wiklander32b31802023-10-06 16:59:46 +0200482 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Jens Wiklander817466c2018-05-22 13:49:31 +0200483}
484
485/*
486 * Convert an ASCII character to digit value
487 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200488static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Jens Wiklander817466c2018-05-22 13:49:31 +0200489{
490 *d = 255;
491
Jens Wiklander32b31802023-10-06 16:59:46 +0200492 if (c >= 0x30 && c <= 0x39) {
493 *d = c - 0x30;
494 }
495 if (c >= 0x41 && c <= 0x46) {
496 *d = c - 0x37;
497 }
498 if (c >= 0x61 && c <= 0x66) {
499 *d = c - 0x57;
500 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200501
Jens Wiklander32b31802023-10-06 16:59:46 +0200502 if (*d >= (mbedtls_mpi_uint) radix) {
503 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
504 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200505
Jens Wiklander32b31802023-10-06 16:59:46 +0200506 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200507}
508
509/*
510 * Import from an ASCII string
511 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200512int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Jens Wiklander817466c2018-05-22 13:49:31 +0200513{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200514 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200515 size_t i, j, slen, n;
Jerome Forissier79013242021-07-28 10:24:04 +0200516 int sign = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +0200517 mbedtls_mpi_uint d;
518 mbedtls_mpi T;
519
Jens Wiklander32b31802023-10-06 16:59:46 +0200520 if (radix < 2 || radix > 16) {
521 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jerome Forissier79013242021-07-28 10:24:04 +0200522 }
523
Tom Van Eyckc1633172024-04-09 18:44:13 +0200524 mbedtls_mpi_init(&T);
Jens Wiklander32b31802023-10-06 16:59:46 +0200525
526 if (s[0] == 0) {
527 mbedtls_mpi_free(X);
528 return 0;
529 }
530
531 if (s[0] == '-') {
Jerome Forissier79013242021-07-28 10:24:04 +0200532 ++s;
533 sign = -1;
534 }
535
Jens Wiklander32b31802023-10-06 16:59:46 +0200536 slen = strlen(s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200537
Jens Wiklander32b31802023-10-06 16:59:46 +0200538 if (radix == 16) {
Tom Van Eyckc1633172024-04-09 18:44:13 +0200539 if (slen > SIZE_MAX >> 2) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200540 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200541 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200542
Jens Wiklander32b31802023-10-06 16:59:46 +0200543 n = BITS_TO_LIMBS(slen << 2);
544
545 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
546 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
547
548 for (i = slen, j = 0; i > 0; i--, j++) {
549 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
550 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
551 }
552 } else {
553 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
554
555 for (i = 0; i < slen; i++) {
556 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
557 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
558 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Jens Wiklander817466c2018-05-22 13:49:31 +0200559 }
560 }
561
Jens Wiklander32b31802023-10-06 16:59:46 +0200562 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200563 X->s = -1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200564 }
Jerome Forissier79013242021-07-28 10:24:04 +0200565
Jens Wiklander817466c2018-05-22 13:49:31 +0200566cleanup:
567
Jens Wiklander32b31802023-10-06 16:59:46 +0200568 mbedtls_mpi_free(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200569
Jens Wiklander32b31802023-10-06 16:59:46 +0200570 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200571}
572
573/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200574 * Helper to write the digits high-order first.
Jens Wiklander817466c2018-05-22 13:49:31 +0200575 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200576static int mpi_write_hlp(mbedtls_mpi *X, int radix,
577 char **p, const size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200578{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200579 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200580 mbedtls_mpi_uint r;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200581 size_t length = 0;
582 char *p_end = *p + buflen;
Jens Wiklander817466c2018-05-22 13:49:31 +0200583
Jens Wiklander32b31802023-10-06 16:59:46 +0200584 do {
585 if (length >= buflen) {
586 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200587 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200588
Jens Wiklander32b31802023-10-06 16:59:46 +0200589 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
590 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Jerome Forissier5b25c762020-04-07 11:18:49 +0200591 /*
592 * Write the residue in the current position, as an ASCII character.
593 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200594 if (r < 0xA) {
595 *(--p_end) = (char) ('0' + r);
596 } else {
597 *(--p_end) = (char) ('A' + (r - 0xA));
598 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200599
Jerome Forissier5b25c762020-04-07 11:18:49 +0200600 length++;
Jens Wiklander32b31802023-10-06 16:59:46 +0200601 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200602
Jens Wiklander32b31802023-10-06 16:59:46 +0200603 memmove(*p, p_end, length);
Jerome Forissier5b25c762020-04-07 11:18:49 +0200604 *p += length;
Jens Wiklander817466c2018-05-22 13:49:31 +0200605
606cleanup:
607
Jens Wiklander32b31802023-10-06 16:59:46 +0200608 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200609}
610
611/*
612 * Export into an ASCII string
613 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200614int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
615 char *buf, size_t buflen, size_t *olen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200616{
617 int ret = 0;
618 size_t n;
619 char *p;
620 mbedtls_mpi T;
621
Jens Wiklander32b31802023-10-06 16:59:46 +0200622 if (radix < 2 || radix > 16) {
623 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
624 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200625
Jens Wiklander32b31802023-10-06 16:59:46 +0200626 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
627 if (radix >= 4) {
628 n >>= 1; /* Number of 4-adic digits necessary to present
Jerome Forissier5b25c762020-04-07 11:18:49 +0200629 * `n`. If radix > 4, this might be a strict
630 * overapproximation of the number of
631 * radix-adic digits needed to present `n`. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200632 }
633 if (radix >= 16) {
634 n >>= 1; /* Number of hexadecimal digits necessary to
Jerome Forissier5b25c762020-04-07 11:18:49 +0200635 * present `n`. */
636
Jens Wiklander32b31802023-10-06 16:59:46 +0200637 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200638 n += 1; /* Terminating null byte */
639 n += 1; /* Compensate for the divisions above, which round down `n`
640 * in case it's not even. */
641 n += 1; /* Potential '-'-sign. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200642 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200643 * which always uses an even number of hex-digits. */
Jens Wiklander817466c2018-05-22 13:49:31 +0200644
Jens Wiklander32b31802023-10-06 16:59:46 +0200645 if (buflen < n) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200646 *olen = n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200647 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200648 }
649
650 p = buf;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200651 mbedtls_mpi_init(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200652
Jens Wiklander32b31802023-10-06 16:59:46 +0200653 if (X->s == -1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200654 *p++ = '-';
Jerome Forissier5b25c762020-04-07 11:18:49 +0200655 buflen--;
656 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200657
Jens Wiklander32b31802023-10-06 16:59:46 +0200658 if (radix == 16) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200659 int c;
660 size_t i, j, k;
661
Jens Wiklander32b31802023-10-06 16:59:46 +0200662 for (i = X->n, k = 0; i > 0; i--) {
663 for (j = ciL; j > 0; j--) {
664 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Jens Wiklander817466c2018-05-22 13:49:31 +0200665
Jens Wiklander32b31802023-10-06 16:59:46 +0200666 if (c == 0 && k == 0 && (i + j) != 2) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200667 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +0200668 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200669
670 *(p++) = "0123456789ABCDEF" [c / 16];
671 *(p++) = "0123456789ABCDEF" [c % 16];
672 k = 1;
673 }
674 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200675 } else {
676 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +0200677
Jens Wiklander32b31802023-10-06 16:59:46 +0200678 if (T.s == -1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200679 T.s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200680 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200681
Jens Wiklander32b31802023-10-06 16:59:46 +0200682 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200683 }
684
685 *p++ = '\0';
Tom Van Eyckc1633172024-04-09 18:44:13 +0200686 *olen = (size_t) (p - buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200687
688cleanup:
689
Jens Wiklander32b31802023-10-06 16:59:46 +0200690 mbedtls_mpi_free(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200691
Jens Wiklander32b31802023-10-06 16:59:46 +0200692 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200693}
694
695#if defined(MBEDTLS_FS_IO)
696/*
697 * Read X from an opened file
698 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200699int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Jens Wiklander817466c2018-05-22 13:49:31 +0200700{
701 mbedtls_mpi_uint d;
702 size_t slen;
703 char *p;
704 /*
705 * Buffer should have space for (short) label and decimal formatted MPI,
706 * newline characters and '\0'
707 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200708 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200709
Jens Wiklander32b31802023-10-06 16:59:46 +0200710 if (radix < 2 || radix > 16) {
711 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
712 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100713
Jens Wiklander32b31802023-10-06 16:59:46 +0200714 memset(s, 0, sizeof(s));
715 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
716 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
717 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200718
Jens Wiklander32b31802023-10-06 16:59:46 +0200719 slen = strlen(s);
720 if (slen == sizeof(s) - 2) {
721 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
722 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200723
Jens Wiklander32b31802023-10-06 16:59:46 +0200724 if (slen > 0 && s[slen - 1] == '\n') {
725 slen--; s[slen] = '\0';
726 }
727 if (slen > 0 && s[slen - 1] == '\r') {
728 slen--; s[slen] = '\0';
729 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200730
731 p = s + slen;
Jens Wiklander32b31802023-10-06 16:59:46 +0200732 while (p-- > s) {
733 if (mpi_get_digit(&d, radix, *p) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200734 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200735 }
736 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200737
Jens Wiklander32b31802023-10-06 16:59:46 +0200738 return mbedtls_mpi_read_string(X, radix, p + 1);
Jens Wiklander817466c2018-05-22 13:49:31 +0200739}
740
741/*
742 * Write X into an opened file (or stdout if fout == NULL)
743 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200744int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Jens Wiklander817466c2018-05-22 13:49:31 +0200745{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200746 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200747 size_t n, slen, plen;
748 /*
749 * Buffer should have space for (short) label and decimal formatted MPI,
750 * newline characters and '\0'
751 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200752 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100753
Jens Wiklander32b31802023-10-06 16:59:46 +0200754 if (radix < 2 || radix > 16) {
755 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
756 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200757
Jens Wiklander32b31802023-10-06 16:59:46 +0200758 memset(s, 0, sizeof(s));
Jens Wiklander817466c2018-05-22 13:49:31 +0200759
Jens Wiklander32b31802023-10-06 16:59:46 +0200760 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Jens Wiklander817466c2018-05-22 13:49:31 +0200761
Jens Wiklander32b31802023-10-06 16:59:46 +0200762 if (p == NULL) {
763 p = "";
764 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200765
Jens Wiklander32b31802023-10-06 16:59:46 +0200766 plen = strlen(p);
767 slen = strlen(s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200768 s[slen++] = '\r';
769 s[slen++] = '\n';
770
Jens Wiklander32b31802023-10-06 16:59:46 +0200771 if (fout != NULL) {
772 if (fwrite(p, 1, plen, fout) != plen ||
773 fwrite(s, 1, slen, fout) != slen) {
774 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
775 }
776 } else {
777 mbedtls_printf("%s%s", p, s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200778 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200779
780cleanup:
781
Jens Wiklander32b31802023-10-06 16:59:46 +0200782 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200783}
784#endif /* MBEDTLS_FS_IO */
785
786/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200787 * Import X from unsigned binary data, little endian
Jens Wiklander32b31802023-10-06 16:59:46 +0200788 *
789 * This function is guaranteed to return an MPI with exactly the necessary
790 * number of limbs (in particular, it does not skip 0s in the input).
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200791 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200792int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
793 const unsigned char *buf, size_t buflen)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200794{
795 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200796 const size_t limbs = CHARS_TO_LIMBS(buflen);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200797
798 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +0200799 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200800
Jens Wiklander32b31802023-10-06 16:59:46 +0200801 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200802
803cleanup:
804
805 /*
806 * This function is also used to import keys. However, wiping the buffers
807 * upon failure is not necessary because failure only can happen before any
808 * input is copied.
809 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200810 return ret;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200811}
812
813/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200814 * Import X from unsigned binary data, big endian
Jens Wiklander32b31802023-10-06 16:59:46 +0200815 *
816 * This function is guaranteed to return an MPI with exactly the necessary
817 * number of limbs (in particular, it does not skip 0s in the input).
Jens Wiklander817466c2018-05-22 13:49:31 +0200818 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200819int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200820{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200821 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200822 const size_t limbs = CHARS_TO_LIMBS(buflen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200823
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100824 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +0200825 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Jens Wiklander29762732019-04-17 12:28:43 +0200826
Jens Wiklander32b31802023-10-06 16:59:46 +0200827 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200828
829cleanup:
830
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200831 /*
832 * This function is also used to import keys. However, wiping the buffers
833 * upon failure is not necessary because failure only can happen before any
834 * input is copied.
835 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200836 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200837}
838
839/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200840 * Export X into unsigned binary data, little endian
841 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200842int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
843 unsigned char *buf, size_t buflen)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200844{
Jens Wiklander32b31802023-10-06 16:59:46 +0200845 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200846}
847
848/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200849 * Export X into unsigned binary data, big endian
850 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200851int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
852 unsigned char *buf, size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200853{
Jens Wiklander32b31802023-10-06 16:59:46 +0200854 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200855}
856
857/*
858 * Left-shift: X <<= count
859 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200860int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Jens Wiklander817466c2018-05-22 13:49:31 +0200861{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200862 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200863 size_t i;
Jens Wiklander817466c2018-05-22 13:49:31 +0200864
Jens Wiklander32b31802023-10-06 16:59:46 +0200865 i = mbedtls_mpi_bitlen(X) + count;
Jens Wiklander817466c2018-05-22 13:49:31 +0200866
Jens Wiklander32b31802023-10-06 16:59:46 +0200867 if (X->n * biL < i) {
868 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
869 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200870
871 ret = 0;
872
Tom Van Eyckc1633172024-04-09 18:44:13 +0200873 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Jens Wiklander817466c2018-05-22 13:49:31 +0200874cleanup:
875
Jens Wiklander32b31802023-10-06 16:59:46 +0200876 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200877}
878
879/*
880 * Right-shift: X >>= count
881 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200882int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Jens Wiklander817466c2018-05-22 13:49:31 +0200883{
Jens Wiklander32b31802023-10-06 16:59:46 +0200884 if (X->n != 0) {
885 mbedtls_mpi_core_shift_r(X->p, X->n, count);
Jens Wiklander817466c2018-05-22 13:49:31 +0200886 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200887 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200888}
889
890/*
891 * Compare unsigned values
892 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200893int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200894{
895 size_t i, j;
896
Jens Wiklander32b31802023-10-06 16:59:46 +0200897 for (i = X->n; i > 0; i--) {
898 if (X->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200899 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200900 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200901 }
902
Jens Wiklander32b31802023-10-06 16:59:46 +0200903 for (j = Y->n; j > 0; j--) {
904 if (Y->p[j - 1] != 0) {
905 break;
906 }
907 }
908
Tom Van Eyckc1633172024-04-09 18:44:13 +0200909 /* If i == j == 0, i.e. abs(X) == abs(Y),
910 * we end up returning 0 at the end of the function. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200911
912 if (i > j) {
913 return 1;
914 }
915 if (j > i) {
916 return -1;
917 }
918
919 for (; i > 0; i--) {
920 if (X->p[i - 1] > Y->p[i - 1]) {
921 return 1;
922 }
923 if (X->p[i - 1] < Y->p[i - 1]) {
924 return -1;
925 }
926 }
927
928 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200929}
930
931/*
932 * Compare signed values
933 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200934int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200935{
936 size_t i, j;
937
Jens Wiklander32b31802023-10-06 16:59:46 +0200938 for (i = X->n; i > 0; i--) {
939 if (X->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200940 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200941 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200942 }
943
Jens Wiklander32b31802023-10-06 16:59:46 +0200944 for (j = Y->n; j > 0; j--) {
945 if (Y->p[j - 1] != 0) {
946 break;
947 }
948 }
949
950 if (i == 0 && j == 0) {
951 return 0;
952 }
953
954 if (i > j) {
955 return X->s;
956 }
957 if (j > i) {
958 return -Y->s;
959 }
960
961 if (X->s > 0 && Y->s < 0) {
962 return 1;
963 }
964 if (Y->s > 0 && X->s < 0) {
965 return -1;
966 }
967
968 for (; i > 0; i--) {
969 if (X->p[i - 1] > Y->p[i - 1]) {
970 return X->s;
971 }
972 if (X->p[i - 1] < Y->p[i - 1]) {
973 return -X->s;
974 }
975 }
976
977 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200978}
979
980/*
981 * Compare signed values
982 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200983int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Jens Wiklander817466c2018-05-22 13:49:31 +0200984{
985 mbedtls_mpi Y;
986 mbedtls_mpi_uint p[1];
987
Jens Wiklander32b31802023-10-06 16:59:46 +0200988 *p = mpi_sint_abs(z);
Tom Van Eyckc1633172024-04-09 18:44:13 +0200989 Y.s = TO_SIGN(z);
Jens Wiklander817466c2018-05-22 13:49:31 +0200990 Y.n = 1;
991 Y.p = p;
992
Jens Wiklander32b31802023-10-06 16:59:46 +0200993 return mbedtls_mpi_cmp_mpi(X, &Y);
Jens Wiklander817466c2018-05-22 13:49:31 +0200994}
995
996/*
997 * Unsigned addition: X = |A| + |B| (HAC 14.7)
998 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200999int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001000{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001001 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001002 size_t j;
Tom Van Eyckc1633172024-04-09 18:44:13 +02001003 mbedtls_mpi_uint *p;
1004 mbedtls_mpi_uint c;
Jens Wiklander817466c2018-05-22 13:49:31 +02001005
Jens Wiklander32b31802023-10-06 16:59:46 +02001006 if (X == B) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001007 const mbedtls_mpi *T = A; A = X; B = T;
1008 }
1009
Jens Wiklander32b31802023-10-06 16:59:46 +02001010 if (X != A) {
1011 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1012 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001013
1014 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02001015 * X must always be positive as a result of unsigned additions.
Jens Wiklander817466c2018-05-22 13:49:31 +02001016 */
1017 X->s = 1;
1018
Jens Wiklander32b31802023-10-06 16:59:46 +02001019 for (j = B->n; j > 0; j--) {
1020 if (B->p[j - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001021 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001022 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001023 }
1024
Jens Wiklander32b31802023-10-06 16:59:46 +02001025 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1026 * and B is 0 (of any size). */
1027 if (j == 0) {
1028 return 0;
1029 }
1030
1031 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
1032
1033 /* j is the number of non-zero limbs of B. Add those to X. */
1034
Tom Van Eyckc1633172024-04-09 18:44:13 +02001035 p = X->p;
Jens Wiklander32b31802023-10-06 16:59:46 +02001036
Tom Van Eyckc1633172024-04-09 18:44:13 +02001037 c = mbedtls_mpi_core_add(p, p, B->p, j);
Jens Wiklander32b31802023-10-06 16:59:46 +02001038
1039 p += j;
1040
1041 /* Now propagate any carry */
1042
1043 while (c != 0) {
1044 if (j >= X->n) {
1045 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
1046 p = X->p + j;
Jens Wiklander817466c2018-05-22 13:49:31 +02001047 }
1048
Jens Wiklander32b31802023-10-06 16:59:46 +02001049 *p += c; c = (*p < c); j++; p++;
Jens Wiklander817466c2018-05-22 13:49:31 +02001050 }
1051
1052cleanup:
1053
Jens Wiklander32b31802023-10-06 16:59:46 +02001054 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001055}
1056
1057/*
Jerome Forissier79013242021-07-28 10:24:04 +02001058 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Jens Wiklander817466c2018-05-22 13:49:31 +02001059 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001060int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001061{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001062 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001063 size_t n;
Jerome Forissier79013242021-07-28 10:24:04 +02001064 mbedtls_mpi_uint carry;
Jens Wiklander817466c2018-05-22 13:49:31 +02001065
Jens Wiklander32b31802023-10-06 16:59:46 +02001066 for (n = B->n; n > 0; n--) {
1067 if (B->p[n - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001068 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001069 }
1070 }
1071 if (n > A->n) {
Jerome Forissier79013242021-07-28 10:24:04 +02001072 /* B >= (2^ciL)^n > A */
1073 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1074 goto cleanup;
1075 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001076
Jens Wiklander32b31802023-10-06 16:59:46 +02001077 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Jerome Forissier79013242021-07-28 10:24:04 +02001078
1079 /* Set the high limbs of X to match A. Don't touch the lower limbs
1080 * because X might be aliased to B, and we must not overwrite the
1081 * significant digits of B. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001082 if (A->n > n && A != X) {
1083 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1084 }
1085 if (X->n > A->n) {
1086 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1087 }
Jerome Forissier79013242021-07-28 10:24:04 +02001088
Jens Wiklander32b31802023-10-06 16:59:46 +02001089 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1090 if (carry != 0) {
1091 /* Propagate the carry through the rest of X. */
1092 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
1093
1094 /* If we have further carry/borrow, the result is negative. */
1095 if (carry != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001096 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1097 goto cleanup;
1098 }
Jerome Forissier79013242021-07-28 10:24:04 +02001099 }
1100
1101 /* X should always be positive as a result of unsigned subtractions. */
1102 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001103
1104cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001105 return ret;
1106}
1107
1108/* Common function for signed addition and subtraction.
1109 * Calculate A + B * flip_B where flip_B is 1 or -1.
1110 */
1111static int add_sub_mpi(mbedtls_mpi *X,
1112 const mbedtls_mpi *A, const mbedtls_mpi *B,
1113 int flip_B)
1114{
1115 int ret, s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001116
1117 s = A->s;
1118 if (A->s * B->s * flip_B < 0) {
1119 int cmp = mbedtls_mpi_cmp_abs(A, B);
1120 if (cmp >= 0) {
1121 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
1122 /* If |A| = |B|, the result is 0 and we must set the sign bit
1123 * to +1 regardless of which of A or B was negative. Otherwise,
1124 * since |A| > |B|, the sign is the sign of A. */
1125 X->s = cmp == 0 ? 1 : s;
1126 } else {
1127 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
1128 /* Since |A| < |B|, the sign is the opposite of A. */
1129 X->s = -s;
1130 }
1131 } else {
1132 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
1133 X->s = s;
1134 }
1135
1136cleanup:
1137
1138 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001139}
1140
1141/*
1142 * Signed addition: X = A + B
1143 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001144int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001145{
Jens Wiklander32b31802023-10-06 16:59:46 +02001146 return add_sub_mpi(X, A, B, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001147}
1148
1149/*
1150 * Signed subtraction: X = A - B
1151 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001152int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001153{
Jens Wiklander32b31802023-10-06 16:59:46 +02001154 return add_sub_mpi(X, A, B, -1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001155}
1156
1157/*
1158 * Signed addition: X = A + b
1159 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001160int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001161{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001162 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001163 mbedtls_mpi_uint p[1];
1164
Jens Wiklander32b31802023-10-06 16:59:46 +02001165 p[0] = mpi_sint_abs(b);
Tom Van Eyckc1633172024-04-09 18:44:13 +02001166 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001167 B.n = 1;
1168 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001169
Jens Wiklander32b31802023-10-06 16:59:46 +02001170 return mbedtls_mpi_add_mpi(X, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001171}
1172
1173/*
1174 * Signed subtraction: X = A - b
1175 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001176int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001177{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001178 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001179 mbedtls_mpi_uint p[1];
1180
Jens Wiklander32b31802023-10-06 16:59:46 +02001181 p[0] = mpi_sint_abs(b);
Tom Van Eyckc1633172024-04-09 18:44:13 +02001182 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001183 B.n = 1;
1184 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001185
Jens Wiklander32b31802023-10-06 16:59:46 +02001186 return mbedtls_mpi_sub_mpi(X, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001187}
1188
1189/*
1190 * Baseline multiplication: X = A * B (HAC 14.12)
1191 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001192int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001193{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001194 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001195 size_t i, j;
1196 mbedtls_mpi TA, TB;
Jerome Forissier79013242021-07-28 10:24:04 +02001197 int result_is_zero = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001198
Tom Van Eyckc1633172024-04-09 18:44:13 +02001199 mbedtls_mpi_init(&TA);
1200 mbedtls_mpi_init(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001201
Jens Wiklander32b31802023-10-06 16:59:46 +02001202 if (X == A) {
1203 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1204 }
1205 if (X == B) {
1206 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1207 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001208
Jens Wiklander32b31802023-10-06 16:59:46 +02001209 for (i = A->n; i > 0; i--) {
1210 if (A->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001211 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001212 }
1213 }
1214 if (i == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001215 result_is_zero = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001216 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001217
Jens Wiklander32b31802023-10-06 16:59:46 +02001218 for (j = B->n; j > 0; j--) {
1219 if (B->p[j - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001220 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001221 }
1222 }
1223 if (j == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001224 result_is_zero = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001225 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001226
Jens Wiklander32b31802023-10-06 16:59:46 +02001227 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1228 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Jens Wiklander817466c2018-05-22 13:49:31 +02001229
Tom Van Eyckc1633172024-04-09 18:44:13 +02001230 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Jens Wiklander817466c2018-05-22 13:49:31 +02001231
Jerome Forissier79013242021-07-28 10:24:04 +02001232 /* If the result is 0, we don't shortcut the operation, which reduces
1233 * but does not eliminate side channels leaking the zero-ness. We do
1234 * need to take care to set the sign bit properly since the library does
1235 * not fully support an MPI object with a value of 0 and s == -1. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001236 if (result_is_zero) {
Jerome Forissier79013242021-07-28 10:24:04 +02001237 X->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001238 } else {
Jerome Forissier79013242021-07-28 10:24:04 +02001239 X->s = A->s * B->s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001240 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001241
1242cleanup:
1243
Jens Wiklander32b31802023-10-06 16:59:46 +02001244 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Jens Wiklander817466c2018-05-22 13:49:31 +02001245
Jens Wiklander32b31802023-10-06 16:59:46 +02001246 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001247}
1248
1249/*
1250 * Baseline multiplication: X = A * b
1251 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001252int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001253{
Jerome Forissier79013242021-07-28 10:24:04 +02001254 size_t n = A->n;
Jens Wiklander32b31802023-10-06 16:59:46 +02001255 while (n > 0 && A->p[n - 1] == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001256 --n;
Jerome Forissier79013242021-07-28 10:24:04 +02001257 }
1258
Jens Wiklander32b31802023-10-06 16:59:46 +02001259 /* The general method below doesn't work if b==0. */
1260 if (b == 0 || n == 0) {
1261 return mbedtls_mpi_lset(X, 0);
1262 }
1263
1264 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Jerome Forissier79013242021-07-28 10:24:04 +02001265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1266 /* In general, A * b requires 1 limb more than b. If
1267 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1268 * number of limbs as A and the call to grow() is not required since
1269 * copy() will take care of the growth if needed. However, experimentally,
1270 * making the call to grow() unconditional causes slightly fewer
1271 * calls to calloc() in ECP code, presumably because it reuses the
1272 * same mpi for a while and this way the mpi is more likely to directly
Jens Wiklander32b31802023-10-06 16:59:46 +02001273 * grow to its final size.
1274 *
1275 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1276 * A,X can be the same. */
1277 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1278 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1279 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Jerome Forissier79013242021-07-28 10:24:04 +02001280
1281cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001282 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001283}
1284
1285/*
1286 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1287 * mbedtls_mpi_uint divisor, d
1288 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001289static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1290 mbedtls_mpi_uint u0,
1291 mbedtls_mpi_uint d,
1292 mbedtls_mpi_uint *r)
Jens Wiklander817466c2018-05-22 13:49:31 +02001293{
1294#if defined(MBEDTLS_HAVE_UDBL)
1295 mbedtls_t_udbl dividend, quotient;
1296#else
1297 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Jens Wiklander32b31802023-10-06 16:59:46 +02001298 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001299 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1300 mbedtls_mpi_uint u0_msw, u0_lsw;
1301 size_t s;
1302#endif
1303
1304 /*
1305 * Check for overflow
1306 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001307 if (0 == d || u1 >= d) {
1308 if (r != NULL) {
1309 *r = ~(mbedtls_mpi_uint) 0u;
1310 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001311
Jens Wiklander32b31802023-10-06 16:59:46 +02001312 return ~(mbedtls_mpi_uint) 0u;
Jens Wiklander817466c2018-05-22 13:49:31 +02001313 }
1314
1315#if defined(MBEDTLS_HAVE_UDBL)
1316 dividend = (mbedtls_t_udbl) u1 << biL;
1317 dividend |= (mbedtls_t_udbl) u0;
1318 quotient = dividend / d;
Jens Wiklander32b31802023-10-06 16:59:46 +02001319 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1320 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1321 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001322
Jens Wiklander32b31802023-10-06 16:59:46 +02001323 if (r != NULL) {
1324 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1325 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001326
1327 return (mbedtls_mpi_uint) quotient;
1328#else
1329
1330 /*
1331 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1332 * Vol. 2 - Seminumerical Algorithms, Knuth
1333 */
1334
1335 /*
1336 * Normalize the divisor, d, and dividend, u0, u1
1337 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001338 s = mbedtls_mpi_core_clz(d);
Jens Wiklander817466c2018-05-22 13:49:31 +02001339 d = d << s;
1340
1341 u1 = u1 << s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001342 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001343 u0 = u0 << s;
1344
1345 d1 = d >> biH;
1346 d0 = d & uint_halfword_mask;
1347
1348 u0_msw = u0 >> biH;
1349 u0_lsw = u0 & uint_halfword_mask;
1350
1351 /*
1352 * Find the first quotient and remainder
1353 */
1354 q1 = u1 / d1;
1355 r0 = u1 - d1 * q1;
1356
Jens Wiklander32b31802023-10-06 16:59:46 +02001357 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001358 q1 -= 1;
1359 r0 += d1;
1360
Jens Wiklander32b31802023-10-06 16:59:46 +02001361 if (r0 >= radix) {
1362 break;
1363 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001364 }
1365
Jens Wiklander32b31802023-10-06 16:59:46 +02001366 rAX = (u1 * radix) + (u0_msw - q1 * d);
Jens Wiklander817466c2018-05-22 13:49:31 +02001367 q0 = rAX / d1;
1368 r0 = rAX - q0 * d1;
1369
Jens Wiklander32b31802023-10-06 16:59:46 +02001370 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001371 q0 -= 1;
1372 r0 += d1;
1373
Jens Wiklander32b31802023-10-06 16:59:46 +02001374 if (r0 >= radix) {
1375 break;
1376 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001377 }
1378
Jens Wiklander32b31802023-10-06 16:59:46 +02001379 if (r != NULL) {
1380 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1381 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001382
1383 quotient = q1 * radix + q0;
1384
1385 return quotient;
1386#endif
1387}
1388
1389/*
1390 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
1391 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001392int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1393 const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001394{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001395 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001396 size_t i, n, t, k;
1397 mbedtls_mpi X, Y, Z, T1, T2;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001398 mbedtls_mpi_uint TP2[3];
Jens Wiklander817466c2018-05-22 13:49:31 +02001399
Jens Wiklander32b31802023-10-06 16:59:46 +02001400 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1401 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1402 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001403
Tom Van Eyckc1633172024-04-09 18:44:13 +02001404 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1405 mbedtls_mpi_init(&T1);
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001406 /*
1407 * Avoid dynamic memory allocations for constant-size T2.
1408 *
1409 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1410 * so nobody increase the size of the MPI and we're safe to use an on-stack
1411 * buffer.
1412 */
1413 T2.s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001414 T2.n = sizeof(TP2) / sizeof(*TP2);
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001415 T2.p = TP2;
Jens Wiklander817466c2018-05-22 13:49:31 +02001416
Jens Wiklander32b31802023-10-06 16:59:46 +02001417 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1418 if (Q != NULL) {
1419 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1420 }
1421 if (R != NULL) {
1422 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1423 }
1424 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001425 }
1426
Jens Wiklander32b31802023-10-06 16:59:46 +02001427 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1428 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001429 X.s = Y.s = 1;
1430
Jens Wiklander32b31802023-10-06 16:59:46 +02001431 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1432 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1433 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Jens Wiklander817466c2018-05-22 13:49:31 +02001434
Jens Wiklander32b31802023-10-06 16:59:46 +02001435 k = mbedtls_mpi_bitlen(&Y) % biL;
1436 if (k < biL - 1) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001437 k = biL - 1 - k;
Jens Wiklander32b31802023-10-06 16:59:46 +02001438 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1439 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1440 } else {
1441 k = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001442 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001443
1444 n = X.n - 1;
1445 t = Y.n - 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001446 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001447
Jens Wiklander32b31802023-10-06 16:59:46 +02001448 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001449 Z.p[n - t]++;
Jens Wiklander32b31802023-10-06 16:59:46 +02001450 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02001451 }
Jens Wiklander32b31802023-10-06 16:59:46 +02001452 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001453
Jens Wiklander32b31802023-10-06 16:59:46 +02001454 for (i = n; i > t; i--) {
1455 if (X.p[i] >= Y.p[t]) {
1456 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1457 } else {
1458 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1459 Y.p[t], NULL);
Jens Wiklander817466c2018-05-22 13:49:31 +02001460 }
1461
Jens Wiklander32b31802023-10-06 16:59:46 +02001462 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1463 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001464 T2.p[2] = X.p[i];
1465
Jens Wiklander817466c2018-05-22 13:49:31 +02001466 Z.p[i - t - 1]++;
Jens Wiklander32b31802023-10-06 16:59:46 +02001467 do {
Jens Wiklander817466c2018-05-22 13:49:31 +02001468 Z.p[i - t - 1]--;
1469
Jens Wiklander32b31802023-10-06 16:59:46 +02001470 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1471 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Jens Wiklander817466c2018-05-22 13:49:31 +02001472 T1.p[1] = Y.p[t];
Jens Wiklander32b31802023-10-06 16:59:46 +02001473 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1474 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001475
Jens Wiklander32b31802023-10-06 16:59:46 +02001476 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1477 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1478 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001479
Jens Wiklander32b31802023-10-06 16:59:46 +02001480 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1481 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1482 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1483 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001484 Z.p[i - t - 1]--;
1485 }
1486 }
1487
Jens Wiklander32b31802023-10-06 16:59:46 +02001488 if (Q != NULL) {
1489 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Jens Wiklander817466c2018-05-22 13:49:31 +02001490 Q->s = A->s * B->s;
1491 }
1492
Jens Wiklander32b31802023-10-06 16:59:46 +02001493 if (R != NULL) {
1494 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Jens Wiklander817466c2018-05-22 13:49:31 +02001495 X.s = A->s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001496 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001497
Jens Wiklander32b31802023-10-06 16:59:46 +02001498 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001499 R->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001500 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001501 }
1502
1503cleanup:
1504
Jens Wiklander32b31802023-10-06 16:59:46 +02001505 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1506 mbedtls_mpi_free(&T1);
1507 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Jens Wiklander817466c2018-05-22 13:49:31 +02001508
Jens Wiklander32b31802023-10-06 16:59:46 +02001509 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001510}
1511
1512/*
1513 * Division by int: A = Q * b + R
1514 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001515int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1516 const mbedtls_mpi *A,
1517 mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001518{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001519 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001520 mbedtls_mpi_uint p[1];
1521
Jens Wiklander32b31802023-10-06 16:59:46 +02001522 p[0] = mpi_sint_abs(b);
Tom Van Eyckc1633172024-04-09 18:44:13 +02001523 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001524 B.n = 1;
1525 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001526
Jens Wiklander32b31802023-10-06 16:59:46 +02001527 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001528}
1529
1530/*
1531 * Modulo: R = A mod B
1532 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001533int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001534{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001535 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001536
Jens Wiklander32b31802023-10-06 16:59:46 +02001537 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1538 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1539 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001540
Jens Wiklander32b31802023-10-06 16:59:46 +02001541 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001542
Jens Wiklander32b31802023-10-06 16:59:46 +02001543 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1544 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1545 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001546
Jens Wiklander32b31802023-10-06 16:59:46 +02001547 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1548 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1549 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001550
1551cleanup:
1552
Jens Wiklander32b31802023-10-06 16:59:46 +02001553 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001554}
1555
1556/*
1557 * Modulo: r = A mod b
1558 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001559int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001560{
1561 size_t i;
1562 mbedtls_mpi_uint x, y, z;
1563
Jens Wiklander32b31802023-10-06 16:59:46 +02001564 if (b == 0) {
1565 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1566 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001567
Jens Wiklander32b31802023-10-06 16:59:46 +02001568 if (b < 0) {
1569 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1570 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001571
1572 /*
1573 * handle trivial cases
1574 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001575 if (b == 1 || A->n == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001576 *r = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +02001577 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001578 }
1579
Jens Wiklander32b31802023-10-06 16:59:46 +02001580 if (b == 2) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001581 *r = A->p[0] & 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001582 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001583 }
1584
1585 /*
1586 * general case
1587 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001588 for (i = A->n, y = 0; i > 0; i--) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001589 x = A->p[i - 1];
Jens Wiklander32b31802023-10-06 16:59:46 +02001590 y = (y << biH) | (x >> biH);
Jens Wiklander817466c2018-05-22 13:49:31 +02001591 z = y / b;
1592 y -= z * b;
1593
1594 x <<= biH;
Jens Wiklander32b31802023-10-06 16:59:46 +02001595 y = (y << biH) | (x >> biH);
Jens Wiklander817466c2018-05-22 13:49:31 +02001596 z = y / b;
1597 y -= z * b;
1598 }
1599
1600 /*
1601 * If A is negative, then the current y represents a negative value.
1602 * Flipping it to the positive side.
1603 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001604 if (A->s < 0 && y != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001605 y = b - y;
Jens Wiklander32b31802023-10-06 16:59:46 +02001606 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001607
1608 *r = y;
1609
Jens Wiklander32b31802023-10-06 16:59:46 +02001610 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001611}
1612
Jens Wiklander12e83fc2018-11-07 08:11:29 +01001613/**
1614 * \remark Replaced by our own because the original has been removed since
1615 * mbedtls v3.6.0.
1616*/
1617void mbedtls_mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
1618{
1619 *mm = mbedtls_mpi_core_montmul_init(N->p);
1620}
1621
1622/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1623 *
1624 * \param[in,out] A One of the numbers to multiply.
1625 * It must have at least as many limbs as N
1626 * (A->n >= N->n), and any limbs beyond n are ignored.
1627 * On successful completion, A contains the result of
1628 * the multiplication A * B * R^-1 mod N where
1629 * R = (2^ciL)^n.
1630 * \param[in] B One of the numbers to multiply.
1631 * It must be nonzero and must not have more limbs than N
1632 * (B->n <= N->n).
1633 * \param[in] N The modulus. \p N must be odd.
1634 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1635 * This is -N^-1 mod 2^ciL.
1636 * \param[in,out] T A bignum for temporary storage.
1637 * It must be at least twice the limb size of N plus 1
1638 * (T->n >= 2 * N->n + 1).
1639 * Its initial content is unused and
1640 * its final content is indeterminate.
1641 * It does not get reallocated.
1642 * \remark Replaced by our own because the original has been removed since
1643 * mbedtls v3.6.0.
1644 */
1645void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1646 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1647 mbedtls_mpi *T)
1648{
1649 mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
1650}
1651
1652/**
1653 * Montgomery reduction: A = A * R^-1 mod N
1654 *
1655 * See mbedtls_mpi_montmul() regarding constraints and guarantees on the parameters.
1656 *
1657 * \remark Replaced by our own because the original has been removed since
1658 * mbedtls v3.6.0.
1659 */
1660void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1661 mbedtls_mpi_uint mm, mbedtls_mpi *T)
1662{
1663 mbedtls_mpi_uint z = 1;
1664 mbedtls_mpi U;
1665
1666 U.n = U.s = (int) z;
1667 U.p = &z;
1668
1669 mbedtls_mpi_montmul(A, &U, N, mm, T);
1670}
1671
1672/*
1673 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1674 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001675int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1676 const mbedtls_mpi *E, const mbedtls_mpi *N,
1677 mbedtls_mpi *prec_RR)
Jens Wiklander817466c2018-05-22 13:49:31 +02001678{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001679 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001680
Jens Wiklander32b31802023-10-06 16:59:46 +02001681 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1682 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1683 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001684
Jens Wiklander32b31802023-10-06 16:59:46 +02001685 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1686 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1687 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001688
Jens Wiklander32b31802023-10-06 16:59:46 +02001689 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1690 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1691 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1692 }
Jerome Forissier79013242021-07-28 10:24:04 +02001693
Jens Wiklander817466c2018-05-22 13:49:31 +02001694 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001695 * Ensure that the exponent that we are passing to the core is not NULL.
Jens Wiklander817466c2018-05-22 13:49:31 +02001696 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001697 if (E->n == 0) {
1698 ret = mbedtls_mpi_lset(X, 1);
1699 return ret;
Jens Wiklander32b31802023-10-06 16:59:46 +02001700 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001701
1702 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001703 * Allocate working memory for mbedtls_mpi_core_exp_mod()
Jens Wiklander817466c2018-05-22 13:49:31 +02001704 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001705 size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);
1706 mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint));
1707 if (T == NULL) {
1708 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001709 }
1710
Tom Van Eyckc1633172024-04-09 18:44:13 +02001711 mbedtls_mpi RR;
1712 mbedtls_mpi_init(&RR);
1713
Jens Wiklander817466c2018-05-22 13:49:31 +02001714 /*
1715 * If 1st call, pre-compute R^2 mod N
1716 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001717 if (prec_RR == NULL || prec_RR->p == NULL) {
Tom Van Eyckc1633172024-04-09 18:44:13 +02001718 MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001719
Jens Wiklander32b31802023-10-06 16:59:46 +02001720 if (prec_RR != NULL) {
Tom Van Eyckc1633172024-04-09 18:44:13 +02001721 *prec_RR = RR;
Jens Wiklander32b31802023-10-06 16:59:46 +02001722 }
1723 } else {
Tom Van Eyckc1633172024-04-09 18:44:13 +02001724 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
1725 RR = *prec_RR;
Jens Wiklander817466c2018-05-22 13:49:31 +02001726 }
1727
1728 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001729 * To preserve constness we need to make a copy of A. Using X for this to
1730 * save memory.
Jens Wiklander817466c2018-05-22 13:49:31 +02001731 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001732 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
Jens Wiklander817466c2018-05-22 13:49:31 +02001733
Tom Van Eyckc1633172024-04-09 18:44:13 +02001734 /*
1735 * Compensate for negative A (and correct at the end).
1736 */
1737 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001738
Tom Van Eyckc1633172024-04-09 18:44:13 +02001739 /*
1740 * Make sure that X is in a form that is safe for consumption by
1741 * the core functions.
1742 *
1743 * - The core functions will not touch the limbs of X above N->n. The
1744 * result will be correct if those limbs are 0, which the mod call
1745 * ensures.
1746 * - Also, X must have at least as many limbs as N for the calls to the
1747 * core functions.
1748 */
1749 if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
1750 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
1751 }
1752 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
1753
1754 /*
1755 * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
1756 */
1757 {
1758 mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
1759 mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
1760 mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
1761 mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
Jens Wiklander817466c2018-05-22 13:49:31 +02001762 }
1763
1764 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001765 * Correct for negative A.
Jens Wiklander817466c2018-05-22 13:49:31 +02001766 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001767 if (A->s == -1 && (E->p[0] & 1) != 0) {
1768 mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
1769 X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001770
Tom Van Eyckc1633172024-04-09 18:44:13 +02001771 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001772 }
1773
1774cleanup:
1775
Tom Van Eyckc1633172024-04-09 18:44:13 +02001776 mbedtls_mpi_zeroize_and_free(T, T_limbs);
Jens Wiklander817466c2018-05-22 13:49:31 +02001777
Jens Wiklander32b31802023-10-06 16:59:46 +02001778 if (prec_RR == NULL || prec_RR->p == NULL) {
1779 mbedtls_mpi_free(&RR);
1780 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001781
Jens Wiklander32b31802023-10-06 16:59:46 +02001782 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001783}
1784
1785/*
1786 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1787 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001788int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001789{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001790 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001791 size_t lz, lzt;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001792 mbedtls_mpi TA, TB;
Jens Wiklander817466c2018-05-22 13:49:31 +02001793
Tom Van Eyckc1633172024-04-09 18:44:13 +02001794 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001795
Jens Wiklander32b31802023-10-06 16:59:46 +02001796 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1797 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001798
Jens Wiklander32b31802023-10-06 16:59:46 +02001799 lz = mbedtls_mpi_lsb(&TA);
1800 lzt = mbedtls_mpi_lsb(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001801
Jerome Forissier79013242021-07-28 10:24:04 +02001802 /* The loop below gives the correct result when A==0 but not when B==0.
1803 * So have a special case for B==0. Leverage the fact that we just
1804 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1805 * slightly more efficient than cmp_int(). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001806 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1807 ret = mbedtls_mpi_copy(G, A);
Jerome Forissier79013242021-07-28 10:24:04 +02001808 goto cleanup;
1809 }
1810
Jens Wiklander32b31802023-10-06 16:59:46 +02001811 if (lzt < lz) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001812 lz = lzt;
Jens Wiklander32b31802023-10-06 16:59:46 +02001813 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001814
Jens Wiklander817466c2018-05-22 13:49:31 +02001815 TA.s = TB.s = 1;
1816
Jerome Forissier79013242021-07-28 10:24:04 +02001817 /* We mostly follow the procedure described in HAC 14.54, but with some
1818 * minor differences:
1819 * - Sequences of multiplications or divisions by 2 are grouped into a
1820 * single shift operation.
1821 * - The procedure in HAC assumes that 0 < TB <= TA.
1822 * - The condition TB <= TA is not actually necessary for correctness.
1823 * TA and TB have symmetric roles except for the loop termination
1824 * condition, and the shifts at the beginning of the loop body
1825 * remove any significance from the ordering of TA vs TB before
1826 * the shifts.
1827 * - If TA = 0, the loop goes through 0 iterations and the result is
1828 * correctly TB.
1829 * - The case TB = 0 was short-circuited above.
1830 *
1831 * For the correctness proof below, decompose the original values of
1832 * A and B as
1833 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1834 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1835 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1836 * and gcd(A',B') is odd or 0.
1837 *
1838 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1839 * The code maintains the following invariant:
1840 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
1841 */
1842
1843 /* Proof that the loop terminates:
1844 * At each iteration, either the right-shift by 1 is made on a nonzero
1845 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
1846 * by at least 1, or the right-shift by 1 is made on zero and then
1847 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
1848 * since in that case TB is calculated from TB-TA with the condition TB>TA).
1849 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001850 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001851 /* Divisions by 2 preserve the invariant (I). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001852 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
1853 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001854
Jerome Forissier79013242021-07-28 10:24:04 +02001855 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
1856 * TA-TB is even so the division by 2 has an integer result.
1857 * Invariant (I) is preserved since any odd divisor of both TA and TB
1858 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Jerome Forissier039e02d2022-08-09 17:10:15 +02001859 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Jerome Forissier79013242021-07-28 10:24:04 +02001860 * divides TA.
1861 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001862 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
1863 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
1864 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
1865 } else {
1866 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
1867 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001868 }
Jerome Forissier79013242021-07-28 10:24:04 +02001869 /* Note that one of TA or TB is still odd. */
Jens Wiklander817466c2018-05-22 13:49:31 +02001870 }
1871
Jerome Forissier79013242021-07-28 10:24:04 +02001872 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
1873 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
1874 * - If there was at least one loop iteration, then one of TA or TB is odd,
1875 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
1876 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
1877 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
1878 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
1879 */
1880
Jens Wiklander32b31802023-10-06 16:59:46 +02001881 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
1882 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Jens Wiklander817466c2018-05-22 13:49:31 +02001883
1884cleanup:
1885
Jens Wiklander32b31802023-10-06 16:59:46 +02001886 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001887
Jens Wiklander32b31802023-10-06 16:59:46 +02001888 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001889}
1890
Jens Wiklander817466c2018-05-22 13:49:31 +02001891/*
1892 * Fill X with size bytes of random.
Jens Wiklander32b31802023-10-06 16:59:46 +02001893 * The bytes returned from the RNG are used in a specific order which
1894 * is suitable for deterministic ECDSA (see the specification of
1895 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Jens Wiklander817466c2018-05-22 13:49:31 +02001896 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001897int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
1898 int (*f_rng)(void *, unsigned char *, size_t),
1899 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02001900{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001901 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001902 const size_t limbs = CHARS_TO_LIMBS(size);
Jerome Forissier5b25c762020-04-07 11:18:49 +02001903
Jerome Forissier5b25c762020-04-07 11:18:49 +02001904 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +02001905 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
1906 if (size == 0) {
1907 return 0;
1908 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001909
Jens Wiklander32b31802023-10-06 16:59:46 +02001910 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02001911
1912cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001913 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001914}
1915
Jens Wiklander32b31802023-10-06 16:59:46 +02001916int mbedtls_mpi_random(mbedtls_mpi *X,
1917 mbedtls_mpi_sint min,
1918 const mbedtls_mpi *N,
1919 int (*f_rng)(void *, unsigned char *, size_t),
1920 void *p_rng)
Jerome Forissier79013242021-07-28 10:24:04 +02001921{
Jens Wiklander32b31802023-10-06 16:59:46 +02001922 if (min < 0) {
1923 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1924 }
1925 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
1926 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1927 }
Jerome Forissier79013242021-07-28 10:24:04 +02001928
1929 /* Ensure that target MPI has exactly the same number of limbs
1930 * as the upper bound, even if the upper bound has leading zeros.
Jens Wiklander32b31802023-10-06 16:59:46 +02001931 * This is necessary for mbedtls_mpi_core_random. */
1932 int ret = mbedtls_mpi_resize_clear(X, N->n);
1933 if (ret != 0) {
1934 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001935 }
Jerome Forissier79013242021-07-28 10:24:04 +02001936
Jens Wiklander32b31802023-10-06 16:59:46 +02001937 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Jerome Forissier79013242021-07-28 10:24:04 +02001938}
1939
Jens Wiklander817466c2018-05-22 13:49:31 +02001940/*
1941 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1942 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001943int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Jens Wiklander817466c2018-05-22 13:49:31 +02001944{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001945 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001946 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1947
Jens Wiklander32b31802023-10-06 16:59:46 +02001948 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
1949 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1950 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001951
Tom Van Eyckc1633172024-04-09 18:44:13 +02001952 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
1953 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
1954 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02001955
Jens Wiklander32b31802023-10-06 16:59:46 +02001956 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001957
Jens Wiklander32b31802023-10-06 16:59:46 +02001958 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001959 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
1960 goto cleanup;
1961 }
1962
Jens Wiklander32b31802023-10-06 16:59:46 +02001963 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
1964 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
1965 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
1966 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001967
Jens Wiklander32b31802023-10-06 16:59:46 +02001968 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
1969 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
1970 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
1971 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001972
Jens Wiklander32b31802023-10-06 16:59:46 +02001973 do {
1974 while ((TU.p[0] & 1) == 0) {
1975 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001976
Jens Wiklander32b31802023-10-06 16:59:46 +02001977 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
1978 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
1979 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02001980 }
1981
Jens Wiklander32b31802023-10-06 16:59:46 +02001982 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
1983 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001984 }
1985
Jens Wiklander32b31802023-10-06 16:59:46 +02001986 while ((TV.p[0] & 1) == 0) {
1987 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001988
Jens Wiklander32b31802023-10-06 16:59:46 +02001989 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
1990 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
1991 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02001992 }
1993
Jens Wiklander32b31802023-10-06 16:59:46 +02001994 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
1995 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001996 }
1997
Jens Wiklander32b31802023-10-06 16:59:46 +02001998 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
1999 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2000 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2001 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2002 } else {
2003 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2004 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2005 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Jens Wiklander817466c2018-05-22 13:49:31 +02002006 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002007 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2008
2009 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2010 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002011 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002012
Jens Wiklander32b31802023-10-06 16:59:46 +02002013 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2014 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2015 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002016
Jens Wiklander32b31802023-10-06 16:59:46 +02002017 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002018
2019cleanup:
2020
Jens Wiklander32b31802023-10-06 16:59:46 +02002021 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2022 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2023 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02002024
Jens Wiklander32b31802023-10-06 16:59:46 +02002025 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002026}
2027
2028#if defined(MBEDTLS_GENPRIME)
2029
Tom Van Eyckc1633172024-04-09 18:44:13 +02002030/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
2031static const unsigned char small_prime_gaps[] = {
2032 2, 2, 4, 2, 4, 2, 4, 6,
2033 2, 6, 4, 2, 4, 6, 6, 2,
2034 6, 4, 2, 6, 4, 6, 8, 4,
2035 2, 4, 2, 4, 14, 4, 6, 2,
2036 10, 2, 6, 6, 4, 6, 6, 2,
2037 10, 2, 4, 2, 12, 12, 4, 2,
2038 4, 6, 2, 10, 6, 6, 6, 2,
2039 6, 4, 2, 10, 14, 4, 2, 4,
2040 14, 6, 10, 2, 4, 6, 8, 6,
2041 6, 4, 6, 8, 4, 8, 10, 2,
2042 10, 2, 6, 4, 6, 8, 4, 2,
2043 4, 12, 8, 4, 8, 4, 6, 12,
2044 2, 18, 6, 10, 6, 6, 2, 6,
2045 10, 6, 6, 2, 6, 6, 4, 2,
2046 12, 10, 2, 4, 6, 6, 2, 12,
2047 4, 6, 8, 10, 8, 10, 8, 6,
2048 6, 4, 8, 6, 4, 8, 4, 14,
2049 10, 12, 2, 10, 2, 4, 2, 10,
2050 14, 4, 2, 4, 14, 4, 2, 4,
2051 20, 4, 8, 10, 8, 4, 6, 6,
2052 14, 4, 6, 6, 8, 6, /*reaches 997*/
2053 0 /* the last entry is effectively unused */
Jens Wiklander817466c2018-05-22 13:49:31 +02002054};
2055
2056/*
2057 * Small divisors test (X must be positive)
2058 *
2059 * Return values:
2060 * 0: no small factor (possible prime, more tests needed)
2061 * 1: certain prime
2062 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2063 * other negative: error
2064 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002065static int mpi_check_small_factors(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +02002066{
2067 int ret = 0;
2068 size_t i;
2069 mbedtls_mpi_uint r;
Tom Van Eyckc1633172024-04-09 18:44:13 +02002070 unsigned p = 3; /* The first odd prime */
Jens Wiklander817466c2018-05-22 13:49:31 +02002071
Jens Wiklander32b31802023-10-06 16:59:46 +02002072 if ((X->p[0] & 1) == 0) {
2073 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2074 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002075
Tom Van Eyckc1633172024-04-09 18:44:13 +02002076 for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2077 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
Jens Wiklander32b31802023-10-06 16:59:46 +02002078 if (r == 0) {
Tom Van Eyckc1633172024-04-09 18:44:13 +02002079 if (mbedtls_mpi_cmp_int(X, p) == 0) {
2080 return 1;
2081 } else {
2082 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2083 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002084 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002085 }
2086
2087cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002088 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002089}
2090
2091/*
2092 * Miller-Rabin pseudo-primality test (HAC 4.24)
2093 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002094static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2095 int (*f_rng)(void *, unsigned char *, size_t),
2096 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002097{
2098 int ret, count;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002099 size_t i, j, k, s;
Jens Wiklander817466c2018-05-22 13:49:31 +02002100 mbedtls_mpi W, R, T, A, RR;
2101
Tom Van Eyckc1633172024-04-09 18:44:13 +02002102 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2103 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2104 mbedtls_mpi_init(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002105
2106 /*
2107 * W = |X| - 1
2108 * R = W >> lsb( W )
2109 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002110 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2111 s = mbedtls_mpi_lsb(&W);
2112 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2113 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Jens Wiklander817466c2018-05-22 13:49:31 +02002114
Jens Wiklander32b31802023-10-06 16:59:46 +02002115 for (i = 0; i < rounds; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002116 /*
2117 * pick a random A, 1 < A < |X| - 1
2118 */
Jens Wiklander817466c2018-05-22 13:49:31 +02002119 count = 0;
2120 do {
Jens Wiklander32b31802023-10-06 16:59:46 +02002121 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +02002122
Jens Wiklander32b31802023-10-06 16:59:46 +02002123 j = mbedtls_mpi_bitlen(&A);
2124 k = mbedtls_mpi_bitlen(&W);
Jens Wiklander817466c2018-05-22 13:49:31 +02002125 if (j > k) {
Jens Wiklander32b31802023-10-06 16:59:46 +02002126 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002127 }
2128
Tom Van Eyckc1633172024-04-09 18:44:13 +02002129 if (count++ > 30) {
Jens Wiklander336e3292019-01-17 11:14:38 +01002130 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2131 goto cleanup;
Jens Wiklander817466c2018-05-22 13:49:31 +02002132 }
2133
Jens Wiklander32b31802023-10-06 16:59:46 +02002134 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2135 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02002136
2137 /*
2138 * A = A^R mod |X|
2139 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002140 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Jens Wiklander817466c2018-05-22 13:49:31 +02002141
Jens Wiklander32b31802023-10-06 16:59:46 +02002142 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2143 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002144 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +02002145 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002146
2147 j = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02002148 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002149 /*
2150 * A = A * A mod |X|
2151 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002152 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2153 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02002154
Jens Wiklander32b31802023-10-06 16:59:46 +02002155 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002156 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02002157 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002158
2159 j++;
2160 }
2161
2162 /*
2163 * not prime if A != |X| - 1 or A == 1
2164 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002165 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2166 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002167 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2168 break;
2169 }
2170 }
2171
2172cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002173 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2174 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2175 mbedtls_mpi_free(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002176
Jens Wiklander32b31802023-10-06 16:59:46 +02002177 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002178}
2179
2180/*
2181 * Pseudo-primality test: small factors, then Miller-Rabin
2182 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002183int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2184 int (*f_rng)(void *, unsigned char *, size_t),
2185 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002186{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02002187 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02002188 mbedtls_mpi XX;
2189
2190 XX.s = 1;
2191 XX.n = X->n;
2192 XX.p = X->p;
2193
Jens Wiklander32b31802023-10-06 16:59:46 +02002194 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2195 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2196 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002197 }
2198
Jens Wiklander32b31802023-10-06 16:59:46 +02002199 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2200 return 0;
2201 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002202
Jens Wiklander32b31802023-10-06 16:59:46 +02002203 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2204 if (ret == 1) {
2205 return 0;
2206 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002207
Jens Wiklander32b31802023-10-06 16:59:46 +02002208 return ret;
2209 }
2210
2211 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002212}
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002213
Jens Wiklander817466c2018-05-22 13:49:31 +02002214/*
2215 * Prime number generation
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002216 *
2217 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2218 * be either 1024 bits or 1536 bits long, and flags must contain
2219 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Jens Wiklander817466c2018-05-22 13:49:31 +02002220 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002221int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2222 int (*f_rng)(void *, unsigned char *, size_t),
2223 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002224{
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002225#ifdef MBEDTLS_HAVE_INT64
2226// ceil(2^63.5)
2227#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2228#else
2229// ceil(2^31.5)
2230#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2231#endif
2232 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002233 size_t k, n;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002234 int rounds;
Jens Wiklander817466c2018-05-22 13:49:31 +02002235 mbedtls_mpi_uint r;
2236 mbedtls_mpi Y;
2237
Jens Wiklander32b31802023-10-06 16:59:46 +02002238 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2239 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2240 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002241
Tom Van Eyckc1633172024-04-09 18:44:13 +02002242 mbedtls_mpi_init(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002243
Jens Wiklander32b31802023-10-06 16:59:46 +02002244 n = BITS_TO_LIMBS(nbits);
Jens Wiklander817466c2018-05-22 13:49:31 +02002245
Jens Wiklander32b31802023-10-06 16:59:46 +02002246 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002247 /*
2248 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2249 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002250 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2251 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2252 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2253 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002254 /*
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002255 * 2^-100 error probability, number of rounds computed based on HAC,
2256 * fact 4.48
Jens Wiklander817466c2018-05-22 13:49:31 +02002257 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002258 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2259 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2260 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2261 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002262 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002263
Jens Wiklander32b31802023-10-06 16:59:46 +02002264 while (1) {
2265 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002266 /* 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 +02002267 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2268 continue;
2269 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002270
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002271 k = n * biL;
Jens Wiklander32b31802023-10-06 16:59:46 +02002272 if (k > nbits) {
2273 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2274 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002275 X->p[0] |= 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002276
Jens Wiklander32b31802023-10-06 16:59:46 +02002277 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2278 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02002279
Jens Wiklander32b31802023-10-06 16:59:46 +02002280 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002281 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002282 }
2283 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002284 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02002285 * A necessary condition for Y and X = 2Y + 1 to be prime
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002286 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2287 * Make sure it is satisfied, while keeping X = 3 mod 4
Jens Wiklander817466c2018-05-22 13:49:31 +02002288 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002289
2290 X->p[0] |= 2;
2291
Jens Wiklander32b31802023-10-06 16:59:46 +02002292 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2293 if (r == 0) {
2294 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2295 } else if (r == 1) {
2296 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2297 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002298
2299 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Jens Wiklander32b31802023-10-06 16:59:46 +02002300 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2301 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002302
Jens Wiklander32b31802023-10-06 16:59:46 +02002303 while (1) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002304 /*
2305 * First, check small factors for X and Y
2306 * before doing Miller-Rabin on any of them
2307 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002308 if ((ret = mpi_check_small_factors(X)) == 0 &&
2309 (ret = mpi_check_small_factors(&Y)) == 0 &&
2310 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2311 == 0 &&
2312 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2313 == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002314 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002315 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002316
Jens Wiklander32b31802023-10-06 16:59:46 +02002317 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002318 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002319 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002320
2321 /*
2322 * Next candidates. We want to preserve Y = (X-1) / 2 and
2323 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2324 * so up Y by 6 and X by 12.
2325 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002326 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2327 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002328 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002329 }
2330 }
2331
2332cleanup:
2333
Jens Wiklander32b31802023-10-06 16:59:46 +02002334 mbedtls_mpi_free(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002335
Jens Wiklander32b31802023-10-06 16:59:46 +02002336 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002337}
2338
2339#endif /* MBEDTLS_GENPRIME */
2340
2341#if defined(MBEDTLS_SELF_TEST)
2342
2343#define GCD_PAIR_COUNT 3
2344
2345static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2346{
2347 { 693, 609, 21 },
2348 { 1764, 868, 28 },
2349 { 768454923, 542167814, 1 }
2350};
2351
2352/*
2353 * Checkup routine
2354 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002355int mbedtls_mpi_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +02002356{
2357 int ret, i;
2358 mbedtls_mpi A, E, N, X, Y, U, V;
2359
Tom Van Eyckc1633172024-04-09 18:44:13 +02002360 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2361 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002362
Jens Wiklander32b31802023-10-06 16:59:46 +02002363 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2364 "EFE021C2645FD1DC586E69184AF4A31E" \
2365 "D5F53E93B5F123FA41680867BA110131" \
2366 "944FE7952E2517337780CB0DB80E61AA" \
2367 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002368
Jens Wiklander32b31802023-10-06 16:59:46 +02002369 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2370 "B2E7EFD37075B9F03FF989C7C5051C20" \
2371 "34D2A323810251127E7BF8625A4F49A5" \
2372 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2373 "5B5C25763222FEFCCFC38B832366C29E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002374
Jens Wiklander32b31802023-10-06 16:59:46 +02002375 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2376 "0066A198186C18C10B2F5ED9B522752A" \
2377 "9830B69916E535C8F047518A889A43A5" \
2378 "94B6BED27A168D31D4A52F88925AA8F5"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002379
Jens Wiklander32b31802023-10-06 16:59:46 +02002380 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002381
Jens Wiklander32b31802023-10-06 16:59:46 +02002382 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2383 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2384 "9E857EA95A03512E2BAE7391688D264A" \
2385 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2386 "8001B72E848A38CAE1C65F78E56ABDEF" \
2387 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2388 "ECF677152EF804370C1A305CAF3B5BF1" \
2389 "30879B56C61DE584A0F53A2447A51E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002390
Jens Wiklander32b31802023-10-06 16:59:46 +02002391 if (verbose != 0) {
2392 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2393 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002394
Jens Wiklander32b31802023-10-06 16:59:46 +02002395 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2396 if (verbose != 0) {
2397 mbedtls_printf("failed\n");
2398 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002399
2400 ret = 1;
2401 goto cleanup;
2402 }
2403
Jens Wiklander32b31802023-10-06 16:59:46 +02002404 if (verbose != 0) {
2405 mbedtls_printf("passed\n");
2406 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002407
Jens Wiklander32b31802023-10-06 16:59:46 +02002408 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002409
Jens Wiklander32b31802023-10-06 16:59:46 +02002410 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2411 "256567336059E52CAE22925474705F39A94"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002412
Jens Wiklander32b31802023-10-06 16:59:46 +02002413 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2414 "6613F26162223DF488E9CD48CC132C7A" \
2415 "0AC93C701B001B092E4E5B9F73BCD27B" \
2416 "9EE50D0657C77F374E903CDFA4C642"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002417
Jens Wiklander32b31802023-10-06 16:59:46 +02002418 if (verbose != 0) {
2419 mbedtls_printf(" MPI test #2 (div_mpi): ");
2420 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002421
Jens Wiklander32b31802023-10-06 16:59:46 +02002422 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2423 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2424 if (verbose != 0) {
2425 mbedtls_printf("failed\n");
2426 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002427
2428 ret = 1;
2429 goto cleanup;
2430 }
2431
Jens Wiklander32b31802023-10-06 16:59:46 +02002432 if (verbose != 0) {
2433 mbedtls_printf("passed\n");
2434 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002435
Jens Wiklander32b31802023-10-06 16:59:46 +02002436 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Jens Wiklander817466c2018-05-22 13:49:31 +02002437
Jens Wiklander32b31802023-10-06 16:59:46 +02002438 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2439 "36E139AEA55215609D2816998ED020BB" \
2440 "BD96C37890F65171D948E9BC7CBAA4D9" \
2441 "325D24D6A3C12710F10A09FA08AB87"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002442
Jens Wiklander32b31802023-10-06 16:59:46 +02002443 if (verbose != 0) {
2444 mbedtls_printf(" MPI test #3 (exp_mod): ");
2445 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002446
Jens Wiklander32b31802023-10-06 16:59:46 +02002447 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2448 if (verbose != 0) {
2449 mbedtls_printf("failed\n");
2450 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002451
2452 ret = 1;
2453 goto cleanup;
2454 }
2455
Jens Wiklander32b31802023-10-06 16:59:46 +02002456 if (verbose != 0) {
2457 mbedtls_printf("passed\n");
2458 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002459
Jens Wiklander32b31802023-10-06 16:59:46 +02002460 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002461
Jens Wiklander32b31802023-10-06 16:59:46 +02002462 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2463 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2464 "C3DBA76456363A10869622EAC2DD84EC" \
2465 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002466
Jens Wiklander32b31802023-10-06 16:59:46 +02002467 if (verbose != 0) {
2468 mbedtls_printf(" MPI test #4 (inv_mod): ");
2469 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002470
Jens Wiklander32b31802023-10-06 16:59:46 +02002471 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2472 if (verbose != 0) {
2473 mbedtls_printf("failed\n");
2474 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002475
2476 ret = 1;
2477 goto cleanup;
2478 }
2479
Jens Wiklander32b31802023-10-06 16:59:46 +02002480 if (verbose != 0) {
2481 mbedtls_printf("passed\n");
2482 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002483
Jens Wiklander32b31802023-10-06 16:59:46 +02002484 if (verbose != 0) {
2485 mbedtls_printf(" MPI test #5 (simple gcd): ");
2486 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002487
Jens Wiklander32b31802023-10-06 16:59:46 +02002488 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2489 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2490 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Jens Wiklander817466c2018-05-22 13:49:31 +02002491
Jens Wiklander32b31802023-10-06 16:59:46 +02002492 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02002493
Jens Wiklander32b31802023-10-06 16:59:46 +02002494 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2495 if (verbose != 0) {
2496 mbedtls_printf("failed at %d\n", i);
2497 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002498
2499 ret = 1;
2500 goto cleanup;
2501 }
2502 }
2503
Jens Wiklander32b31802023-10-06 16:59:46 +02002504 if (verbose != 0) {
2505 mbedtls_printf("passed\n");
2506 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002507
2508cleanup:
2509
Jens Wiklander32b31802023-10-06 16:59:46 +02002510 if (ret != 0 && verbose != 0) {
2511 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2512 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002513
Jens Wiklander32b31802023-10-06 16:59:46 +02002514 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2515 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002516
Jens Wiklander32b31802023-10-06 16:59:46 +02002517 if (verbose != 0) {
2518 mbedtls_printf("\n");
2519 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002520
Jens Wiklander32b31802023-10-06 16:59:46 +02002521 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002522}
2523
2524#endif /* MBEDTLS_SELF_TEST */
2525
2526#endif /* MBEDTLS_BIGNUM_C */