blob: c45fd5bf24873c5eb3083cc37e1030f82f89f1a1 [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 Wiklander32b31802023-10-06 16:59:46 +02001613int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1614 const mbedtls_mpi *E, const mbedtls_mpi *N,
1615 mbedtls_mpi *prec_RR)
Jens Wiklander817466c2018-05-22 13:49:31 +02001616{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001617 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001618
Jens Wiklander32b31802023-10-06 16:59:46 +02001619 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1620 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1621 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001622
Jens Wiklander32b31802023-10-06 16:59:46 +02001623 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1624 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1625 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001626
Jens Wiklander32b31802023-10-06 16:59:46 +02001627 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1628 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1629 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1630 }
Jerome Forissier79013242021-07-28 10:24:04 +02001631
Jens Wiklander817466c2018-05-22 13:49:31 +02001632 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001633 * Ensure that the exponent that we are passing to the core is not NULL.
Jens Wiklander817466c2018-05-22 13:49:31 +02001634 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001635 if (E->n == 0) {
1636 ret = mbedtls_mpi_lset(X, 1);
1637 return ret;
Jens Wiklander32b31802023-10-06 16:59:46 +02001638 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001639
1640 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001641 * Allocate working memory for mbedtls_mpi_core_exp_mod()
Jens Wiklander817466c2018-05-22 13:49:31 +02001642 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001643 size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);
1644 mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint));
1645 if (T == NULL) {
1646 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001647 }
1648
Tom Van Eyckc1633172024-04-09 18:44:13 +02001649 mbedtls_mpi RR;
1650 mbedtls_mpi_init(&RR);
1651
Jens Wiklander817466c2018-05-22 13:49:31 +02001652 /*
1653 * If 1st call, pre-compute R^2 mod N
1654 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001655 if (prec_RR == NULL || prec_RR->p == NULL) {
Tom Van Eyckc1633172024-04-09 18:44:13 +02001656 MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001657
Jens Wiklander32b31802023-10-06 16:59:46 +02001658 if (prec_RR != NULL) {
Tom Van Eyckc1633172024-04-09 18:44:13 +02001659 *prec_RR = RR;
Jens Wiklander32b31802023-10-06 16:59:46 +02001660 }
1661 } else {
Tom Van Eyckc1633172024-04-09 18:44:13 +02001662 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
1663 RR = *prec_RR;
Jens Wiklander817466c2018-05-22 13:49:31 +02001664 }
1665
1666 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001667 * To preserve constness we need to make a copy of A. Using X for this to
1668 * save memory.
Jens Wiklander817466c2018-05-22 13:49:31 +02001669 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001670 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
Jens Wiklander817466c2018-05-22 13:49:31 +02001671
Tom Van Eyckc1633172024-04-09 18:44:13 +02001672 /*
1673 * Compensate for negative A (and correct at the end).
1674 */
1675 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001676
Tom Van Eyckc1633172024-04-09 18:44:13 +02001677 /*
1678 * Make sure that X is in a form that is safe for consumption by
1679 * the core functions.
1680 *
1681 * - The core functions will not touch the limbs of X above N->n. The
1682 * result will be correct if those limbs are 0, which the mod call
1683 * ensures.
1684 * - Also, X must have at least as many limbs as N for the calls to the
1685 * core functions.
1686 */
1687 if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
1688 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
1689 }
1690 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
1691
1692 /*
1693 * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
1694 */
1695 {
1696 mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
1697 mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
1698 mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
1699 mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
Jens Wiklander817466c2018-05-22 13:49:31 +02001700 }
1701
1702 /*
Tom Van Eyckc1633172024-04-09 18:44:13 +02001703 * Correct for negative A.
Jens Wiklander817466c2018-05-22 13:49:31 +02001704 */
Tom Van Eyckc1633172024-04-09 18:44:13 +02001705 if (A->s == -1 && (E->p[0] & 1) != 0) {
1706 mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
1707 X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001708
Tom Van Eyckc1633172024-04-09 18:44:13 +02001709 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001710 }
1711
1712cleanup:
1713
Tom Van Eyckc1633172024-04-09 18:44:13 +02001714 mbedtls_mpi_zeroize_and_free(T, T_limbs);
Jens Wiklander817466c2018-05-22 13:49:31 +02001715
Jens Wiklander32b31802023-10-06 16:59:46 +02001716 if (prec_RR == NULL || prec_RR->p == NULL) {
1717 mbedtls_mpi_free(&RR);
1718 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001719
Jens Wiklander32b31802023-10-06 16:59:46 +02001720 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001721}
1722
1723/*
1724 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1725 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001726int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001727{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001728 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001729 size_t lz, lzt;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001730 mbedtls_mpi TA, TB;
Jens Wiklander817466c2018-05-22 13:49:31 +02001731
Tom Van Eyckc1633172024-04-09 18:44:13 +02001732 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001733
Jens Wiklander32b31802023-10-06 16:59:46 +02001734 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1735 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001736
Jens Wiklander32b31802023-10-06 16:59:46 +02001737 lz = mbedtls_mpi_lsb(&TA);
1738 lzt = mbedtls_mpi_lsb(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001739
Jerome Forissier79013242021-07-28 10:24:04 +02001740 /* The loop below gives the correct result when A==0 but not when B==0.
1741 * So have a special case for B==0. Leverage the fact that we just
1742 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1743 * slightly more efficient than cmp_int(). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001744 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1745 ret = mbedtls_mpi_copy(G, A);
Jerome Forissier79013242021-07-28 10:24:04 +02001746 goto cleanup;
1747 }
1748
Jens Wiklander32b31802023-10-06 16:59:46 +02001749 if (lzt < lz) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001750 lz = lzt;
Jens Wiklander32b31802023-10-06 16:59:46 +02001751 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001752
Jens Wiklander817466c2018-05-22 13:49:31 +02001753 TA.s = TB.s = 1;
1754
Jerome Forissier79013242021-07-28 10:24:04 +02001755 /* We mostly follow the procedure described in HAC 14.54, but with some
1756 * minor differences:
1757 * - Sequences of multiplications or divisions by 2 are grouped into a
1758 * single shift operation.
1759 * - The procedure in HAC assumes that 0 < TB <= TA.
1760 * - The condition TB <= TA is not actually necessary for correctness.
1761 * TA and TB have symmetric roles except for the loop termination
1762 * condition, and the shifts at the beginning of the loop body
1763 * remove any significance from the ordering of TA vs TB before
1764 * the shifts.
1765 * - If TA = 0, the loop goes through 0 iterations and the result is
1766 * correctly TB.
1767 * - The case TB = 0 was short-circuited above.
1768 *
1769 * For the correctness proof below, decompose the original values of
1770 * A and B as
1771 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1772 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1773 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1774 * and gcd(A',B') is odd or 0.
1775 *
1776 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1777 * The code maintains the following invariant:
1778 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
1779 */
1780
1781 /* Proof that the loop terminates:
1782 * At each iteration, either the right-shift by 1 is made on a nonzero
1783 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
1784 * by at least 1, or the right-shift by 1 is made on zero and then
1785 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
1786 * since in that case TB is calculated from TB-TA with the condition TB>TA).
1787 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001788 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001789 /* Divisions by 2 preserve the invariant (I). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001790 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
1791 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001792
Jerome Forissier79013242021-07-28 10:24:04 +02001793 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
1794 * TA-TB is even so the division by 2 has an integer result.
1795 * Invariant (I) is preserved since any odd divisor of both TA and TB
1796 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Jerome Forissier039e02d2022-08-09 17:10:15 +02001797 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Jerome Forissier79013242021-07-28 10:24:04 +02001798 * divides TA.
1799 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001800 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
1801 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
1802 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
1803 } else {
1804 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
1805 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001806 }
Jerome Forissier79013242021-07-28 10:24:04 +02001807 /* Note that one of TA or TB is still odd. */
Jens Wiklander817466c2018-05-22 13:49:31 +02001808 }
1809
Jerome Forissier79013242021-07-28 10:24:04 +02001810 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
1811 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
1812 * - If there was at least one loop iteration, then one of TA or TB is odd,
1813 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
1814 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
1815 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
1816 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
1817 */
1818
Jens Wiklander32b31802023-10-06 16:59:46 +02001819 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
1820 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Jens Wiklander817466c2018-05-22 13:49:31 +02001821
1822cleanup:
1823
Jens Wiklander32b31802023-10-06 16:59:46 +02001824 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001825
Jens Wiklander32b31802023-10-06 16:59:46 +02001826 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001827}
1828
Jens Wiklander817466c2018-05-22 13:49:31 +02001829/*
1830 * Fill X with size bytes of random.
Jens Wiklander32b31802023-10-06 16:59:46 +02001831 * The bytes returned from the RNG are used in a specific order which
1832 * is suitable for deterministic ECDSA (see the specification of
1833 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Jens Wiklander817466c2018-05-22 13:49:31 +02001834 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001835int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
1836 int (*f_rng)(void *, unsigned char *, size_t),
1837 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02001838{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001839 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001840 const size_t limbs = CHARS_TO_LIMBS(size);
Jerome Forissier5b25c762020-04-07 11:18:49 +02001841
Jerome Forissier5b25c762020-04-07 11:18:49 +02001842 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +02001843 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
1844 if (size == 0) {
1845 return 0;
1846 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001847
Jens Wiklander32b31802023-10-06 16:59:46 +02001848 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02001849
1850cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001851 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001852}
1853
Jens Wiklander32b31802023-10-06 16:59:46 +02001854int mbedtls_mpi_random(mbedtls_mpi *X,
1855 mbedtls_mpi_sint min,
1856 const mbedtls_mpi *N,
1857 int (*f_rng)(void *, unsigned char *, size_t),
1858 void *p_rng)
Jerome Forissier79013242021-07-28 10:24:04 +02001859{
Jens Wiklander32b31802023-10-06 16:59:46 +02001860 if (min < 0) {
1861 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1862 }
1863 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
1864 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1865 }
Jerome Forissier79013242021-07-28 10:24:04 +02001866
1867 /* Ensure that target MPI has exactly the same number of limbs
1868 * as the upper bound, even if the upper bound has leading zeros.
Jens Wiklander32b31802023-10-06 16:59:46 +02001869 * This is necessary for mbedtls_mpi_core_random. */
1870 int ret = mbedtls_mpi_resize_clear(X, N->n);
1871 if (ret != 0) {
1872 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001873 }
Jerome Forissier79013242021-07-28 10:24:04 +02001874
Jens Wiklander32b31802023-10-06 16:59:46 +02001875 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Jerome Forissier79013242021-07-28 10:24:04 +02001876}
1877
Jens Wiklander817466c2018-05-22 13:49:31 +02001878/*
1879 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1880 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001881int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Jens Wiklander817466c2018-05-22 13:49:31 +02001882{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001883 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001884 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1885
Jens Wiklander32b31802023-10-06 16:59:46 +02001886 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
1887 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1888 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001889
Tom Van Eyckc1633172024-04-09 18:44:13 +02001890 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
1891 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
1892 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02001893
Jens Wiklander32b31802023-10-06 16:59:46 +02001894 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001895
Jens Wiklander32b31802023-10-06 16:59:46 +02001896 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001897 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
1898 goto cleanup;
1899 }
1900
Jens Wiklander32b31802023-10-06 16:59:46 +02001901 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
1902 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
1903 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
1904 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001905
Jens Wiklander32b31802023-10-06 16:59:46 +02001906 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
1907 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
1908 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
1909 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001910
Jens Wiklander32b31802023-10-06 16:59:46 +02001911 do {
1912 while ((TU.p[0] & 1) == 0) {
1913 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001914
Jens Wiklander32b31802023-10-06 16:59:46 +02001915 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
1916 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
1917 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02001918 }
1919
Jens Wiklander32b31802023-10-06 16:59:46 +02001920 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
1921 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001922 }
1923
Jens Wiklander32b31802023-10-06 16:59:46 +02001924 while ((TV.p[0] & 1) == 0) {
1925 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001926
Jens Wiklander32b31802023-10-06 16:59:46 +02001927 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
1928 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
1929 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02001930 }
1931
Jens Wiklander32b31802023-10-06 16:59:46 +02001932 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
1933 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001934 }
1935
Jens Wiklander32b31802023-10-06 16:59:46 +02001936 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
1937 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
1938 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
1939 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
1940 } else {
1941 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
1942 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
1943 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Jens Wiklander817466c2018-05-22 13:49:31 +02001944 }
Jens Wiklander32b31802023-10-06 16:59:46 +02001945 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
1946
1947 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
1948 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001949 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001950
Jens Wiklander32b31802023-10-06 16:59:46 +02001951 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
1952 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
1953 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001954
Jens Wiklander32b31802023-10-06 16:59:46 +02001955 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001956
1957cleanup:
1958
Jens Wiklander32b31802023-10-06 16:59:46 +02001959 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
1960 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
1961 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02001962
Jens Wiklander32b31802023-10-06 16:59:46 +02001963 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001964}
1965
1966#if defined(MBEDTLS_GENPRIME)
1967
Tom Van Eyckc1633172024-04-09 18:44:13 +02001968/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
1969static const unsigned char small_prime_gaps[] = {
1970 2, 2, 4, 2, 4, 2, 4, 6,
1971 2, 6, 4, 2, 4, 6, 6, 2,
1972 6, 4, 2, 6, 4, 6, 8, 4,
1973 2, 4, 2, 4, 14, 4, 6, 2,
1974 10, 2, 6, 6, 4, 6, 6, 2,
1975 10, 2, 4, 2, 12, 12, 4, 2,
1976 4, 6, 2, 10, 6, 6, 6, 2,
1977 6, 4, 2, 10, 14, 4, 2, 4,
1978 14, 6, 10, 2, 4, 6, 8, 6,
1979 6, 4, 6, 8, 4, 8, 10, 2,
1980 10, 2, 6, 4, 6, 8, 4, 2,
1981 4, 12, 8, 4, 8, 4, 6, 12,
1982 2, 18, 6, 10, 6, 6, 2, 6,
1983 10, 6, 6, 2, 6, 6, 4, 2,
1984 12, 10, 2, 4, 6, 6, 2, 12,
1985 4, 6, 8, 10, 8, 10, 8, 6,
1986 6, 4, 8, 6, 4, 8, 4, 14,
1987 10, 12, 2, 10, 2, 4, 2, 10,
1988 14, 4, 2, 4, 14, 4, 2, 4,
1989 20, 4, 8, 10, 8, 4, 6, 6,
1990 14, 4, 6, 6, 8, 6, /*reaches 997*/
1991 0 /* the last entry is effectively unused */
Jens Wiklander817466c2018-05-22 13:49:31 +02001992};
1993
1994/*
1995 * Small divisors test (X must be positive)
1996 *
1997 * Return values:
1998 * 0: no small factor (possible prime, more tests needed)
1999 * 1: certain prime
2000 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2001 * other negative: error
2002 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002003static int mpi_check_small_factors(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +02002004{
2005 int ret = 0;
2006 size_t i;
2007 mbedtls_mpi_uint r;
Tom Van Eyckc1633172024-04-09 18:44:13 +02002008 unsigned p = 3; /* The first odd prime */
Jens Wiklander817466c2018-05-22 13:49:31 +02002009
Jens Wiklander32b31802023-10-06 16:59:46 +02002010 if ((X->p[0] & 1) == 0) {
2011 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2012 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002013
Tom Van Eyckc1633172024-04-09 18:44:13 +02002014 for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2015 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
Jens Wiklander32b31802023-10-06 16:59:46 +02002016 if (r == 0) {
Tom Van Eyckc1633172024-04-09 18:44:13 +02002017 if (mbedtls_mpi_cmp_int(X, p) == 0) {
2018 return 1;
2019 } else {
2020 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2021 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002022 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002023 }
2024
2025cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002026 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002027}
2028
2029/*
2030 * Miller-Rabin pseudo-primality test (HAC 4.24)
2031 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002032static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2033 int (*f_rng)(void *, unsigned char *, size_t),
2034 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002035{
2036 int ret, count;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002037 size_t i, j, k, s;
Jens Wiklander817466c2018-05-22 13:49:31 +02002038 mbedtls_mpi W, R, T, A, RR;
2039
Tom Van Eyckc1633172024-04-09 18:44:13 +02002040 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2041 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2042 mbedtls_mpi_init(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002043
2044 /*
2045 * W = |X| - 1
2046 * R = W >> lsb( W )
2047 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002048 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2049 s = mbedtls_mpi_lsb(&W);
2050 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2051 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Jens Wiklander817466c2018-05-22 13:49:31 +02002052
Jens Wiklander32b31802023-10-06 16:59:46 +02002053 for (i = 0; i < rounds; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002054 /*
2055 * pick a random A, 1 < A < |X| - 1
2056 */
Jens Wiklander817466c2018-05-22 13:49:31 +02002057 count = 0;
2058 do {
Jens Wiklander32b31802023-10-06 16:59:46 +02002059 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +02002060
Jens Wiklander32b31802023-10-06 16:59:46 +02002061 j = mbedtls_mpi_bitlen(&A);
2062 k = mbedtls_mpi_bitlen(&W);
Jens Wiklander817466c2018-05-22 13:49:31 +02002063 if (j > k) {
Jens Wiklander32b31802023-10-06 16:59:46 +02002064 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002065 }
2066
Tom Van Eyckc1633172024-04-09 18:44:13 +02002067 if (count++ > 30) {
Jens Wiklander336e3292019-01-17 11:14:38 +01002068 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2069 goto cleanup;
Jens Wiklander817466c2018-05-22 13:49:31 +02002070 }
2071
Jens Wiklander32b31802023-10-06 16:59:46 +02002072 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2073 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02002074
2075 /*
2076 * A = A^R mod |X|
2077 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002078 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Jens Wiklander817466c2018-05-22 13:49:31 +02002079
Jens Wiklander32b31802023-10-06 16:59:46 +02002080 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2081 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002082 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +02002083 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002084
2085 j = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02002086 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002087 /*
2088 * A = A * A mod |X|
2089 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002090 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2091 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02002092
Jens Wiklander32b31802023-10-06 16:59:46 +02002093 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002094 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02002095 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002096
2097 j++;
2098 }
2099
2100 /*
2101 * not prime if A != |X| - 1 or A == 1
2102 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002103 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2104 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002105 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2106 break;
2107 }
2108 }
2109
2110cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002111 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2112 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2113 mbedtls_mpi_free(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002114
Jens Wiklander32b31802023-10-06 16:59:46 +02002115 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002116}
2117
2118/*
2119 * Pseudo-primality test: small factors, then Miller-Rabin
2120 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002121int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2122 int (*f_rng)(void *, unsigned char *, size_t),
2123 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002124{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02002125 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02002126 mbedtls_mpi XX;
2127
2128 XX.s = 1;
2129 XX.n = X->n;
2130 XX.p = X->p;
2131
Jens Wiklander32b31802023-10-06 16:59:46 +02002132 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2133 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2134 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002135 }
2136
Jens Wiklander32b31802023-10-06 16:59:46 +02002137 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2138 return 0;
2139 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002140
Jens Wiklander32b31802023-10-06 16:59:46 +02002141 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2142 if (ret == 1) {
2143 return 0;
2144 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002145
Jens Wiklander32b31802023-10-06 16:59:46 +02002146 return ret;
2147 }
2148
2149 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002150}
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002151
Jens Wiklander817466c2018-05-22 13:49:31 +02002152/*
2153 * Prime number generation
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002154 *
2155 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2156 * be either 1024 bits or 1536 bits long, and flags must contain
2157 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Jens Wiklander817466c2018-05-22 13:49:31 +02002158 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002159int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2160 int (*f_rng)(void *, unsigned char *, size_t),
2161 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002162{
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002163#ifdef MBEDTLS_HAVE_INT64
2164// ceil(2^63.5)
2165#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2166#else
2167// ceil(2^31.5)
2168#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2169#endif
2170 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002171 size_t k, n;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002172 int rounds;
Jens Wiklander817466c2018-05-22 13:49:31 +02002173 mbedtls_mpi_uint r;
2174 mbedtls_mpi Y;
2175
Jens Wiklander32b31802023-10-06 16:59:46 +02002176 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2177 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2178 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002179
Tom Van Eyckc1633172024-04-09 18:44:13 +02002180 mbedtls_mpi_init(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002181
Jens Wiklander32b31802023-10-06 16:59:46 +02002182 n = BITS_TO_LIMBS(nbits);
Jens Wiklander817466c2018-05-22 13:49:31 +02002183
Jens Wiklander32b31802023-10-06 16:59:46 +02002184 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002185 /*
2186 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2187 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002188 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2189 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2190 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2191 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002192 /*
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002193 * 2^-100 error probability, number of rounds computed based on HAC,
2194 * fact 4.48
Jens Wiklander817466c2018-05-22 13:49:31 +02002195 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002196 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2197 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2198 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2199 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002200 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002201
Jens Wiklander32b31802023-10-06 16:59:46 +02002202 while (1) {
2203 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002204 /* 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 +02002205 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2206 continue;
2207 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002208
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002209 k = n * biL;
Jens Wiklander32b31802023-10-06 16:59:46 +02002210 if (k > nbits) {
2211 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2212 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002213 X->p[0] |= 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002214
Jens Wiklander32b31802023-10-06 16:59:46 +02002215 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2216 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02002217
Jens Wiklander32b31802023-10-06 16:59:46 +02002218 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002219 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002220 }
2221 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002222 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02002223 * A necessary condition for Y and X = 2Y + 1 to be prime
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002224 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2225 * Make sure it is satisfied, while keeping X = 3 mod 4
Jens Wiklander817466c2018-05-22 13:49:31 +02002226 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002227
2228 X->p[0] |= 2;
2229
Jens Wiklander32b31802023-10-06 16:59:46 +02002230 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2231 if (r == 0) {
2232 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2233 } else if (r == 1) {
2234 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2235 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002236
2237 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Jens Wiklander32b31802023-10-06 16:59:46 +02002238 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2239 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002240
Jens Wiklander32b31802023-10-06 16:59:46 +02002241 while (1) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002242 /*
2243 * First, check small factors for X and Y
2244 * before doing Miller-Rabin on any of them
2245 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002246 if ((ret = mpi_check_small_factors(X)) == 0 &&
2247 (ret = mpi_check_small_factors(&Y)) == 0 &&
2248 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2249 == 0 &&
2250 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2251 == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002252 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002253 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002254
Jens Wiklander32b31802023-10-06 16:59:46 +02002255 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002256 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002257 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002258
2259 /*
2260 * Next candidates. We want to preserve Y = (X-1) / 2 and
2261 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2262 * so up Y by 6 and X by 12.
2263 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002264 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2265 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002266 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002267 }
2268 }
2269
2270cleanup:
2271
Jens Wiklander32b31802023-10-06 16:59:46 +02002272 mbedtls_mpi_free(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002273
Jens Wiklander32b31802023-10-06 16:59:46 +02002274 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002275}
2276
2277#endif /* MBEDTLS_GENPRIME */
2278
2279#if defined(MBEDTLS_SELF_TEST)
2280
2281#define GCD_PAIR_COUNT 3
2282
2283static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2284{
2285 { 693, 609, 21 },
2286 { 1764, 868, 28 },
2287 { 768454923, 542167814, 1 }
2288};
2289
2290/*
2291 * Checkup routine
2292 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002293int mbedtls_mpi_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +02002294{
2295 int ret, i;
2296 mbedtls_mpi A, E, N, X, Y, U, V;
2297
Tom Van Eyckc1633172024-04-09 18:44:13 +02002298 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2299 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002300
Jens Wiklander32b31802023-10-06 16:59:46 +02002301 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2302 "EFE021C2645FD1DC586E69184AF4A31E" \
2303 "D5F53E93B5F123FA41680867BA110131" \
2304 "944FE7952E2517337780CB0DB80E61AA" \
2305 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002306
Jens Wiklander32b31802023-10-06 16:59:46 +02002307 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2308 "B2E7EFD37075B9F03FF989C7C5051C20" \
2309 "34D2A323810251127E7BF8625A4F49A5" \
2310 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2311 "5B5C25763222FEFCCFC38B832366C29E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002312
Jens Wiklander32b31802023-10-06 16:59:46 +02002313 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2314 "0066A198186C18C10B2F5ED9B522752A" \
2315 "9830B69916E535C8F047518A889A43A5" \
2316 "94B6BED27A168D31D4A52F88925AA8F5"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002317
Jens Wiklander32b31802023-10-06 16:59:46 +02002318 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002319
Jens Wiklander32b31802023-10-06 16:59:46 +02002320 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2321 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2322 "9E857EA95A03512E2BAE7391688D264A" \
2323 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2324 "8001B72E848A38CAE1C65F78E56ABDEF" \
2325 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2326 "ECF677152EF804370C1A305CAF3B5BF1" \
2327 "30879B56C61DE584A0F53A2447A51E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002328
Jens Wiklander32b31802023-10-06 16:59:46 +02002329 if (verbose != 0) {
2330 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2331 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002332
Jens Wiklander32b31802023-10-06 16:59:46 +02002333 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2334 if (verbose != 0) {
2335 mbedtls_printf("failed\n");
2336 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002337
2338 ret = 1;
2339 goto cleanup;
2340 }
2341
Jens Wiklander32b31802023-10-06 16:59:46 +02002342 if (verbose != 0) {
2343 mbedtls_printf("passed\n");
2344 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002345
Jens Wiklander32b31802023-10-06 16:59:46 +02002346 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002347
Jens Wiklander32b31802023-10-06 16:59:46 +02002348 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2349 "256567336059E52CAE22925474705F39A94"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002350
Jens Wiklander32b31802023-10-06 16:59:46 +02002351 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2352 "6613F26162223DF488E9CD48CC132C7A" \
2353 "0AC93C701B001B092E4E5B9F73BCD27B" \
2354 "9EE50D0657C77F374E903CDFA4C642"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002355
Jens Wiklander32b31802023-10-06 16:59:46 +02002356 if (verbose != 0) {
2357 mbedtls_printf(" MPI test #2 (div_mpi): ");
2358 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002359
Jens Wiklander32b31802023-10-06 16:59:46 +02002360 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2361 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2362 if (verbose != 0) {
2363 mbedtls_printf("failed\n");
2364 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002365
2366 ret = 1;
2367 goto cleanup;
2368 }
2369
Jens Wiklander32b31802023-10-06 16:59:46 +02002370 if (verbose != 0) {
2371 mbedtls_printf("passed\n");
2372 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002373
Jens Wiklander32b31802023-10-06 16:59:46 +02002374 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Jens Wiklander817466c2018-05-22 13:49:31 +02002375
Jens Wiklander32b31802023-10-06 16:59:46 +02002376 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2377 "36E139AEA55215609D2816998ED020BB" \
2378 "BD96C37890F65171D948E9BC7CBAA4D9" \
2379 "325D24D6A3C12710F10A09FA08AB87"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002380
Jens Wiklander32b31802023-10-06 16:59:46 +02002381 if (verbose != 0) {
2382 mbedtls_printf(" MPI test #3 (exp_mod): ");
2383 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002384
Jens Wiklander32b31802023-10-06 16:59:46 +02002385 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2386 if (verbose != 0) {
2387 mbedtls_printf("failed\n");
2388 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002389
2390 ret = 1;
2391 goto cleanup;
2392 }
2393
Jens Wiklander32b31802023-10-06 16:59:46 +02002394 if (verbose != 0) {
2395 mbedtls_printf("passed\n");
2396 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002397
Jens Wiklander32b31802023-10-06 16:59:46 +02002398 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002399
Jens Wiklander32b31802023-10-06 16:59:46 +02002400 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2401 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2402 "C3DBA76456363A10869622EAC2DD84EC" \
2403 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002404
Jens Wiklander32b31802023-10-06 16:59:46 +02002405 if (verbose != 0) {
2406 mbedtls_printf(" MPI test #4 (inv_mod): ");
2407 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002408
Jens Wiklander32b31802023-10-06 16:59:46 +02002409 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2410 if (verbose != 0) {
2411 mbedtls_printf("failed\n");
2412 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002413
2414 ret = 1;
2415 goto cleanup;
2416 }
2417
Jens Wiklander32b31802023-10-06 16:59:46 +02002418 if (verbose != 0) {
2419 mbedtls_printf("passed\n");
2420 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002421
Jens Wiklander32b31802023-10-06 16:59:46 +02002422 if (verbose != 0) {
2423 mbedtls_printf(" MPI test #5 (simple gcd): ");
2424 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002425
Jens Wiklander32b31802023-10-06 16:59:46 +02002426 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2427 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2428 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Jens Wiklander817466c2018-05-22 13:49:31 +02002429
Jens Wiklander32b31802023-10-06 16:59:46 +02002430 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02002431
Jens Wiklander32b31802023-10-06 16:59:46 +02002432 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2433 if (verbose != 0) {
2434 mbedtls_printf("failed at %d\n", i);
2435 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002436
2437 ret = 1;
2438 goto cleanup;
2439 }
2440 }
2441
Jens Wiklander32b31802023-10-06 16:59:46 +02002442 if (verbose != 0) {
2443 mbedtls_printf("passed\n");
2444 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002445
2446cleanup:
2447
Jens Wiklander32b31802023-10-06 16:59:46 +02002448 if (ret != 0 && verbose != 0) {
2449 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2450 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002451
Jens Wiklander32b31802023-10-06 16:59:46 +02002452 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2453 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002454
Jens Wiklander32b31802023-10-06 16:59:46 +02002455 if (verbose != 0) {
2456 mbedtls_printf("\n");
2457 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002458
Jens Wiklander32b31802023-10-06 16:59:46 +02002459 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002460}
2461
2462#endif /* MBEDTLS_SELF_TEST */
2463
2464#endif /* MBEDTLS_BIGNUM_C */