blob: 8b466cc867d3a2388af3252389224c2f98f2c0cc [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * Multi-precision integer library
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
Tom Van Eyckb0563632024-06-13 16:20:14 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7
8/*
9 * The following sources were referenced in the design of this Multi-precision
10 * Integer library:
11 *
12 * [1] Handbook of Applied Cryptography - 1997
13 * Menezes, van Oorschot and Vanstone
14 *
15 * [2] Multi-Precision Math
16 * Tom St Denis
17 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
18 *
19 * [3] GNU Multi-Precision Arithmetic Library
20 * https://gmplib.org/manual/index.html
21 *
22 */
23
Jerome Forissier79013242021-07-28 10:24:04 +020024#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020025
26#if defined(MBEDTLS_BIGNUM_C)
27
28#include "mbedtls/bignum.h"
Jens Wiklander32b31802023-10-06 16:59:46 +020029#include "bignum_core.h"
Sungbae Yoo4d211f32024-11-19 02:47:55 +000030#include "bignum_internal.h"
Jens Wiklander32b31802023-10-06 16:59:46 +020031#include "bn_mul.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010032#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020033#include "mbedtls/error.h"
Jerome Forissier039e02d2022-08-09 17:10:15 +020034#include "constant_time_internal.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020035
Jerome Forissier039e02d2022-08-09 17:10:15 +020036#include <limits.h>
Jens Wiklander817466c2018-05-22 13:49:31 +020037#include <string.h>
38
Jens Wiklander817466c2018-05-22 13:49:31 +020039#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020040
Jens Wiklander98bd5fe2018-11-08 11:18:22 +010041
Tom Van Eyckb0563632024-06-13 16:20:14 +020042
43/*
44 * Conditionally select an MPI sign in constant time.
45 * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid
46 * values.)
47 */
48static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,
49 signed short sign1, signed short sign2)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010050{
Tom Van Eyckb0563632024-06-13 16:20:14 +020051 return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;
Jens Wiklander3d3b0592019-03-20 15:30:29 +010052}
53
Jens Wiklander817466c2018-05-22 13:49:31 +020054/*
Tom Van Eyckb0563632024-06-13 16:20:14 +020055 * Compare signed values in constant time
56 */
57int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
58 const mbedtls_mpi *Y,
59 unsigned *ret)
60{
61 mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
62
63 if (X->n != Y->n) {
64 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
65 }
66
67 /*
68 * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.
69 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
70 */
71 X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
72 Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
73
74 /*
75 * If the signs are different, then the positive operand is the bigger.
76 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
77 * is false if X is positive (X_is_negative == 0).
78 */
79 different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
80 result = mbedtls_ct_bool_and(different_sign, X_is_negative);
81
82 /*
83 * Assuming signs are the same, compare X and Y. We switch the comparison
84 * order if they are negative so that we get the right result, regardles of
85 * sign.
86 */
87
88 /* This array is used to conditionally swap the pointers in const time */
89 void * const p[2] = { X->p, Y->p };
90 size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
91 mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
92
93 /*
94 * Store in result iff the signs are the same (i.e., iff different_sign == false). If
95 * the signs differ, result has already been set, so we don't change it.
96 */
97 result = mbedtls_ct_bool_or(result,
98 mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
99
100 *ret = mbedtls_ct_uint_if_else_0(result, 1);
101
102 return 0;
103}
104
105/*
106 * Conditionally assign X = Y, without leaking information
107 * about whether the assignment was made or not.
108 * (Leaking information about the respective sizes of X and Y is ok however.)
109 */
110#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
111 (_MSC_FULL_VER < 193131103)
112/*
113 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
114 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
115 */
116__declspec(noinline)
117#endif
118int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
119 const mbedtls_mpi *Y,
120 unsigned char assign)
121{
122 int ret = 0;
123
124 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
125
126 {
127 mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
128
129 X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);
130
131 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
132
133 mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
134 for (size_t i = Y->n; i < X->n; i++) {
135 X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
136 }
137 }
138
139cleanup:
140 return ret;
141}
142
143/*
144 * Conditionally swap X and Y, without leaking information
145 * about whether the swap was made or not.
146 * Here it is not ok to simply swap the pointers, which would lead to
147 * different memory access patterns when X and Y are used afterwards.
148 */
149int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
150 mbedtls_mpi *Y,
151 unsigned char swap)
152{
153 int ret = 0;
154 int s;
155
156 if (X == Y) {
157 return 0;
158 }
159
160 mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
161
162 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
163 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
164
165 s = X->s;
166 X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);
167 Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);
168
169 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
170
171cleanup:
172 return ret;
173}
174
175/* Implementation that should never be optimized out by the compiler */
176#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
177
178/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200179 * Initialize one MPI
180 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200181void mbedtls_mpi_init(mbedtls_mpi *X)
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100182{
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000183 X->s = 1;
184 X->n = 0;
185 X->p = NULL;
Jens Wiklander98bd5fe2018-11-08 11:18:22 +0100186}
187
Jens Wiklander817466c2018-05-22 13:49:31 +0200188/*
189 * Unallocate one MPI
190 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200191void mbedtls_mpi_free(mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200192{
Jens Wiklander32b31802023-10-06 16:59:46 +0200193 if (X == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200194 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200195 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200196
Jens Wiklander32b31802023-10-06 16:59:46 +0200197 if (X->p != NULL) {
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000198 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200199 }
200
201 X->s = 1;
202 X->n = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100203 X->p = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200204}
205
206/*
207 * Enlarge to the specified number of limbs
208 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200209int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Jens Wiklander817466c2018-05-22 13:49:31 +0200210{
211 mbedtls_mpi_uint *p;
212
Jens Wiklander32b31802023-10-06 16:59:46 +0200213 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
214 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
215 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200216
Jens Wiklander32b31802023-10-06 16:59:46 +0200217 if (X->n < nblimbs) {
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000218 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
219 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100220 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200221
Jens Wiklander32b31802023-10-06 16:59:46 +0200222 if (X->p != NULL) {
223 memcpy(p, X->p, X->n * ciL);
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000224 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100225 }
226
Tom Van Eyckb0563632024-06-13 16:20:14 +0200227 /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
228 * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
229 X->n = (unsigned short) nblimbs;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100230 X->p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +0200231 }
232
Jens Wiklander32b31802023-10-06 16:59:46 +0200233 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200234}
235
236/*
237 * Resize down as much as possible,
238 * while keeping at least the specified number of limbs
239 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200240int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Jens Wiklander817466c2018-05-22 13:49:31 +0200241{
242 mbedtls_mpi_uint *p;
243 size_t i;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100244
Jens Wiklander32b31802023-10-06 16:59:46 +0200245 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
246 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
247 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200248
Jerome Forissier5b25c762020-04-07 11:18:49 +0200249 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200250 if (X->n <= nblimbs) {
251 return mbedtls_mpi_grow(X, nblimbs);
252 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200253 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Jens Wiklander817466c2018-05-22 13:49:31 +0200254
Jens Wiklander32b31802023-10-06 16:59:46 +0200255 for (i = X->n - 1; i > 0; i--) {
256 if (X->p[i] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200257 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200258 }
259 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200260 i++;
261
Jens Wiklander32b31802023-10-06 16:59:46 +0200262 if (i < nblimbs) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200263 i = nblimbs;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100264 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200265
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000266 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
267 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200268 }
269
270 if (X->p != NULL) {
271 memcpy(p, X->p, i * ciL);
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000272 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200273 }
274
Tom Van Eyckb0563632024-06-13 16:20:14 +0200275 /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
276 * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
277 X->n = (unsigned short) i;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100278 X->p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +0200279
Jens Wiklander32b31802023-10-06 16:59:46 +0200280 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200281}
282
Jerome Forissier79013242021-07-28 10:24:04 +0200283/* Resize X to have exactly n limbs and set it to 0. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200284static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Jerome Forissier79013242021-07-28 10:24:04 +0200285{
Jens Wiklander32b31802023-10-06 16:59:46 +0200286 if (limbs == 0) {
287 mbedtls_mpi_free(X);
288 return 0;
289 } else if (X->n == limbs) {
290 memset(X->p, 0, limbs * ciL);
Jerome Forissier79013242021-07-28 10:24:04 +0200291 X->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200292 return 0;
293 } else {
294 mbedtls_mpi_free(X);
295 return mbedtls_mpi_grow(X, limbs);
Jerome Forissier79013242021-07-28 10:24:04 +0200296 }
297}
298
Jens Wiklander817466c2018-05-22 13:49:31 +0200299/*
Jerome Forissier79013242021-07-28 10:24:04 +0200300 * Copy the contents of Y into X.
301 *
302 * This function is not constant-time. Leading zeros in Y may be removed.
303 *
304 * Ensure that X does not shrink. This is not guaranteed by the public API,
Tom Van Eyckb0563632024-06-13 16:20:14 +0200305 * but some code in the bignum module might still rely on this property.
Jens Wiklander817466c2018-05-22 13:49:31 +0200306 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200307int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200308{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100309 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200310 size_t i;
311
Jens Wiklander32b31802023-10-06 16:59:46 +0200312 if (X == Y) {
313 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200314 }
315
Jens Wiklander32b31802023-10-06 16:59:46 +0200316 if (Y->n == 0) {
317 if (X->n != 0) {
318 X->s = 1;
319 memset(X->p, 0, X->n * ciL);
320 }
321 return 0;
322 }
323
324 for (i = Y->n - 1; i > 0; i--) {
325 if (Y->p[i] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200326 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200327 }
328 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200329 i++;
330
331 X->s = Y->s;
332
Jens Wiklander32b31802023-10-06 16:59:46 +0200333 if (X->n < i) {
334 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
335 } else {
336 memset(X->p + i, 0, (X->n - i) * ciL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100337 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200338
Jens Wiklander32b31802023-10-06 16:59:46 +0200339 memcpy(X->p, Y->p, i * ciL);
Jens Wiklander817466c2018-05-22 13:49:31 +0200340
341cleanup:
342
Jens Wiklander32b31802023-10-06 16:59:46 +0200343 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200344}
345
346/*
347 * Swap the contents of X and Y
348 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200349void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200350{
351 mbedtls_mpi T;
352
Jens Wiklander32b31802023-10-06 16:59:46 +0200353 memcpy(&T, X, sizeof(mbedtls_mpi));
354 memcpy(X, Y, sizeof(mbedtls_mpi));
355 memcpy(Y, &T, sizeof(mbedtls_mpi));
356}
357
358static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
359{
360 if (z >= 0) {
361 return z;
362 }
363 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
364 * A naive -z would have undefined behavior.
365 * Write this in a way that makes popular compilers happy (GCC, Clang,
366 * MSVC). */
367 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Jens Wiklander817466c2018-05-22 13:49:31 +0200368}
369
Tom Van Eyckb0563632024-06-13 16:20:14 +0200370/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
371 * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
372#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
373
Jens Wiklander817466c2018-05-22 13:49:31 +0200374/*
375 * Set value from integer
376 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200377int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Jens Wiklander817466c2018-05-22 13:49:31 +0200378{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200379 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200380
Jens Wiklander32b31802023-10-06 16:59:46 +0200381 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
382 memset(X->p, 0, X->n * ciL);
Jens Wiklander817466c2018-05-22 13:49:31 +0200383
Jens Wiklander32b31802023-10-06 16:59:46 +0200384 X->p[0] = mpi_sint_abs(z);
Tom Van Eyckb0563632024-06-13 16:20:14 +0200385 X->s = TO_SIGN(z);
Jens Wiklander817466c2018-05-22 13:49:31 +0200386
387cleanup:
388
Jens Wiklander32b31802023-10-06 16:59:46 +0200389 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200390}
391
392/*
393 * Get a specific bit
394 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200395int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Jens Wiklander817466c2018-05-22 13:49:31 +0200396{
Jens Wiklander32b31802023-10-06 16:59:46 +0200397 if (X->n * biL <= pos) {
398 return 0;
399 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200400
Jens Wiklander32b31802023-10-06 16:59:46 +0200401 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Jens Wiklander817466c2018-05-22 13:49:31 +0200402}
403
404/*
405 * Set a bit to a specific value of 0 or 1
406 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200407int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Jens Wiklander817466c2018-05-22 13:49:31 +0200408{
409 int ret = 0;
410 size_t off = pos / biL;
411 size_t idx = pos % biL;
412
Jens Wiklander32b31802023-10-06 16:59:46 +0200413 if (val != 0 && val != 1) {
414 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200415 }
416
Jens Wiklander32b31802023-10-06 16:59:46 +0200417 if (X->n * biL <= pos) {
418 if (val == 0) {
419 return 0;
420 }
421
422 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
423 }
424
425 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200426 X->p[off] |= (mbedtls_mpi_uint) val << idx;
427
428cleanup:
429
Jens Wiklander32b31802023-10-06 16:59:46 +0200430 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200431}
432
433/*
434 * Return the number of less significant zero-bits
435 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200436size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200437{
Tom Van Eyckb0563632024-06-13 16:20:14 +0200438 size_t i;
Jens Wiklander817466c2018-05-22 13:49:31 +0200439
Tom Van Eyckb0563632024-06-13 16:20:14 +0200440#if defined(__has_builtin)
441#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
442 #define mbedtls_mpi_uint_ctz __builtin_ctz
443#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
444 #define mbedtls_mpi_uint_ctz __builtin_ctzl
445#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
446 #define mbedtls_mpi_uint_ctz __builtin_ctzll
447#endif
448#endif
449
450#if defined(mbedtls_mpi_uint_ctz)
Jens Wiklander32b31802023-10-06 16:59:46 +0200451 for (i = 0; i < X->n; i++) {
Tom Van Eyckb0563632024-06-13 16:20:14 +0200452 if (X->p[i] != 0) {
453 return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
454 }
455 }
456#else
457 size_t count = 0;
458 for (i = 0; i < X->n; i++) {
459 for (size_t j = 0; j < biL; j++, count++) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200460 if (((X->p[i] >> j) & 1) != 0) {
461 return count;
462 }
463 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200464 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200465#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200466
Jens Wiklander32b31802023-10-06 16:59:46 +0200467 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200468}
469
470/*
471 * Return the number of bits
472 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200473size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200474{
Jens Wiklander32b31802023-10-06 16:59:46 +0200475 return mbedtls_mpi_core_bitlen(X->p, X->n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200476}
477
478/*
479 * Return the total size in bytes
480 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200481size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +0200482{
Jens Wiklander32b31802023-10-06 16:59:46 +0200483 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Jens Wiklander817466c2018-05-22 13:49:31 +0200484}
485
486/*
487 * Convert an ASCII character to digit value
488 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200489static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Jens Wiklander817466c2018-05-22 13:49:31 +0200490{
491 *d = 255;
492
Jens Wiklander32b31802023-10-06 16:59:46 +0200493 if (c >= 0x30 && c <= 0x39) {
494 *d = c - 0x30;
495 }
496 if (c >= 0x41 && c <= 0x46) {
497 *d = c - 0x37;
498 }
499 if (c >= 0x61 && c <= 0x66) {
500 *d = c - 0x57;
501 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200502
Jens Wiklander32b31802023-10-06 16:59:46 +0200503 if (*d >= (mbedtls_mpi_uint) radix) {
504 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
505 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200506
Jens Wiklander32b31802023-10-06 16:59:46 +0200507 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200508}
509
510/*
511 * Import from an ASCII string
512 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200513int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Jens Wiklander817466c2018-05-22 13:49:31 +0200514{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200515 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200516 size_t i, j, slen, n;
Jerome Forissier79013242021-07-28 10:24:04 +0200517 int sign = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +0200518 mbedtls_mpi_uint d;
519 mbedtls_mpi T;
520
Jens Wiklander32b31802023-10-06 16:59:46 +0200521 if (radix < 2 || radix > 16) {
522 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jerome Forissier79013242021-07-28 10:24:04 +0200523 }
524
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000525 mbedtls_mpi_init(&T);
Jens Wiklander32b31802023-10-06 16:59:46 +0200526
527 if (s[0] == 0) {
528 mbedtls_mpi_free(X);
529 return 0;
530 }
531
532 if (s[0] == '-') {
Jerome Forissier79013242021-07-28 10:24:04 +0200533 ++s;
534 sign = -1;
535 }
536
Jens Wiklander32b31802023-10-06 16:59:46 +0200537 slen = strlen(s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200538
Jens Wiklander32b31802023-10-06 16:59:46 +0200539 if (radix == 16) {
Tom Van Eyckb0563632024-06-13 16:20:14 +0200540 if (slen > SIZE_MAX >> 2) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200541 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200542 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200543
Jens Wiklander32b31802023-10-06 16:59:46 +0200544 n = BITS_TO_LIMBS(slen << 2);
545
546 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
547 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
548
549 for (i = slen, j = 0; i > 0; i--, j++) {
550 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
551 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
552 }
553 } else {
554 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
555
556 for (i = 0; i < slen; i++) {
557 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
558 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
559 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Jens Wiklander817466c2018-05-22 13:49:31 +0200560 }
561 }
562
Jens Wiklander32b31802023-10-06 16:59:46 +0200563 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200564 X->s = -1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200565 }
Jerome Forissier79013242021-07-28 10:24:04 +0200566
Jens Wiklander817466c2018-05-22 13:49:31 +0200567cleanup:
568
Jens Wiklander32b31802023-10-06 16:59:46 +0200569 mbedtls_mpi_free(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200570
Jens Wiklander32b31802023-10-06 16:59:46 +0200571 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200572}
573
574/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200575 * Helper to write the digits high-order first.
Jens Wiklander817466c2018-05-22 13:49:31 +0200576 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200577static int mpi_write_hlp(mbedtls_mpi *X, int radix,
578 char **p, const size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200579{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200580 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200581 mbedtls_mpi_uint r;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200582 size_t length = 0;
583 char *p_end = *p + buflen;
Jens Wiklander817466c2018-05-22 13:49:31 +0200584
Jens Wiklander32b31802023-10-06 16:59:46 +0200585 do {
586 if (length >= buflen) {
587 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200588 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200589
Jens Wiklander32b31802023-10-06 16:59:46 +0200590 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
591 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Jerome Forissier5b25c762020-04-07 11:18:49 +0200592 /*
593 * Write the residue in the current position, as an ASCII character.
594 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200595 if (r < 0xA) {
596 *(--p_end) = (char) ('0' + r);
597 } else {
598 *(--p_end) = (char) ('A' + (r - 0xA));
599 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200600
Jerome Forissier5b25c762020-04-07 11:18:49 +0200601 length++;
Jens Wiklander32b31802023-10-06 16:59:46 +0200602 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200603
Jens Wiklander32b31802023-10-06 16:59:46 +0200604 memmove(*p, p_end, length);
Jerome Forissier5b25c762020-04-07 11:18:49 +0200605 *p += length;
Jens Wiklander817466c2018-05-22 13:49:31 +0200606
607cleanup:
608
Jens Wiklander32b31802023-10-06 16:59:46 +0200609 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200610}
611
612/*
613 * Export into an ASCII string
614 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200615int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
616 char *buf, size_t buflen, size_t *olen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200617{
618 int ret = 0;
619 size_t n;
620 char *p;
621 mbedtls_mpi T;
622
Jens Wiklander32b31802023-10-06 16:59:46 +0200623 if (radix < 2 || radix > 16) {
624 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
625 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200626
Jens Wiklander32b31802023-10-06 16:59:46 +0200627 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
628 if (radix >= 4) {
629 n >>= 1; /* Number of 4-adic digits necessary to present
Jerome Forissier5b25c762020-04-07 11:18:49 +0200630 * `n`. If radix > 4, this might be a strict
631 * overapproximation of the number of
632 * radix-adic digits needed to present `n`. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200633 }
634 if (radix >= 16) {
635 n >>= 1; /* Number of hexadecimal digits necessary to
Jerome Forissier5b25c762020-04-07 11:18:49 +0200636 * present `n`. */
637
Jens Wiklander32b31802023-10-06 16:59:46 +0200638 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200639 n += 1; /* Terminating null byte */
640 n += 1; /* Compensate for the divisions above, which round down `n`
641 * in case it's not even. */
642 n += 1; /* Potential '-'-sign. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200643 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200644 * which always uses an even number of hex-digits. */
Jens Wiklander817466c2018-05-22 13:49:31 +0200645
Jens Wiklander32b31802023-10-06 16:59:46 +0200646 if (buflen < n) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200647 *olen = n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200648 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200649 }
650
651 p = buf;
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000652 mbedtls_mpi_init(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200653
Jens Wiklander32b31802023-10-06 16:59:46 +0200654 if (X->s == -1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200655 *p++ = '-';
Jerome Forissier5b25c762020-04-07 11:18:49 +0200656 buflen--;
657 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200658
Jens Wiklander32b31802023-10-06 16:59:46 +0200659 if (radix == 16) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200660 int c;
661 size_t i, j, k;
662
Jens Wiklander32b31802023-10-06 16:59:46 +0200663 for (i = X->n, k = 0; i > 0; i--) {
664 for (j = ciL; j > 0; j--) {
665 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Jens Wiklander817466c2018-05-22 13:49:31 +0200666
Jens Wiklander32b31802023-10-06 16:59:46 +0200667 if (c == 0 && k == 0 && (i + j) != 2) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200668 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +0200669 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200670
671 *(p++) = "0123456789ABCDEF" [c / 16];
672 *(p++) = "0123456789ABCDEF" [c % 16];
673 k = 1;
674 }
675 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200676 } else {
677 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +0200678
Jens Wiklander32b31802023-10-06 16:59:46 +0200679 if (T.s == -1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200680 T.s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200681 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200682
Jens Wiklander32b31802023-10-06 16:59:46 +0200683 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200684 }
685
686 *p++ = '\0';
Tom Van Eyckb0563632024-06-13 16:20:14 +0200687 *olen = (size_t) (p - buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200688
689cleanup:
690
Jens Wiklander32b31802023-10-06 16:59:46 +0200691 mbedtls_mpi_free(&T);
Jens Wiklander817466c2018-05-22 13:49:31 +0200692
Jens Wiklander32b31802023-10-06 16:59:46 +0200693 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200694}
695
696#if defined(MBEDTLS_FS_IO)
697/*
698 * Read X from an opened file
699 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200700int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Jens Wiklander817466c2018-05-22 13:49:31 +0200701{
702 mbedtls_mpi_uint d;
703 size_t slen;
704 char *p;
705 /*
706 * Buffer should have space for (short) label and decimal formatted MPI,
707 * newline characters and '\0'
708 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200709 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200710
Jens Wiklander32b31802023-10-06 16:59:46 +0200711 if (radix < 2 || radix > 16) {
712 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
713 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100714
Jens Wiklander32b31802023-10-06 16:59:46 +0200715 memset(s, 0, sizeof(s));
716 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
717 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
718 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200719
Jens Wiklander32b31802023-10-06 16:59:46 +0200720 slen = strlen(s);
721 if (slen == sizeof(s) - 2) {
722 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
723 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200724
Jens Wiklander32b31802023-10-06 16:59:46 +0200725 if (slen > 0 && s[slen - 1] == '\n') {
726 slen--; s[slen] = '\0';
727 }
728 if (slen > 0 && s[slen - 1] == '\r') {
729 slen--; s[slen] = '\0';
730 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200731
732 p = s + slen;
Jens Wiklander32b31802023-10-06 16:59:46 +0200733 while (p-- > s) {
734 if (mpi_get_digit(&d, radix, *p) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200735 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200736 }
737 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200738
Jens Wiklander32b31802023-10-06 16:59:46 +0200739 return mbedtls_mpi_read_string(X, radix, p + 1);
Jens Wiklander817466c2018-05-22 13:49:31 +0200740}
741
742/*
743 * Write X into an opened file (or stdout if fout == NULL)
744 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200745int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Jens Wiklander817466c2018-05-22 13:49:31 +0200746{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200747 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200748 size_t n, slen, plen;
749 /*
750 * Buffer should have space for (short) label and decimal formatted MPI,
751 * newline characters and '\0'
752 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200753 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100754
Jens Wiklander32b31802023-10-06 16:59:46 +0200755 if (radix < 2 || radix > 16) {
756 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
757 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200758
Jens Wiklander32b31802023-10-06 16:59:46 +0200759 memset(s, 0, sizeof(s));
Jens Wiklander817466c2018-05-22 13:49:31 +0200760
Jens Wiklander32b31802023-10-06 16:59:46 +0200761 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Jens Wiklander817466c2018-05-22 13:49:31 +0200762
Jens Wiklander32b31802023-10-06 16:59:46 +0200763 if (p == NULL) {
764 p = "";
765 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200766
Jens Wiklander32b31802023-10-06 16:59:46 +0200767 plen = strlen(p);
768 slen = strlen(s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200769 s[slen++] = '\r';
770 s[slen++] = '\n';
771
Jens Wiklander32b31802023-10-06 16:59:46 +0200772 if (fout != NULL) {
773 if (fwrite(p, 1, plen, fout) != plen ||
774 fwrite(s, 1, slen, fout) != slen) {
775 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
776 }
777 } else {
778 mbedtls_printf("%s%s", p, s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200779 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200780
781cleanup:
782
Jens Wiklander32b31802023-10-06 16:59:46 +0200783 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200784}
785#endif /* MBEDTLS_FS_IO */
786
787/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200788 * Import X from unsigned binary data, little endian
Jens Wiklander32b31802023-10-06 16:59:46 +0200789 *
790 * This function is guaranteed to return an MPI with exactly the necessary
791 * number of limbs (in particular, it does not skip 0s in the input).
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200792 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200793int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
794 const unsigned char *buf, size_t buflen)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200795{
796 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200797 const size_t limbs = CHARS_TO_LIMBS(buflen);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200798
799 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +0200800 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200801
Jens Wiklander32b31802023-10-06 16:59:46 +0200802 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200803
804cleanup:
805
806 /*
807 * This function is also used to import keys. However, wiping the buffers
808 * upon failure is not necessary because failure only can happen before any
809 * input is copied.
810 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200811 return ret;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200812}
813
814/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200815 * Import X from unsigned binary data, big endian
Jens Wiklander32b31802023-10-06 16:59:46 +0200816 *
817 * This function is guaranteed to return an MPI with exactly the necessary
818 * number of limbs (in particular, it does not skip 0s in the input).
Jens Wiklander817466c2018-05-22 13:49:31 +0200819 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200820int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200821{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200822 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200823 const size_t limbs = CHARS_TO_LIMBS(buflen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200824
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100825 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +0200826 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Jens Wiklander29762732019-04-17 12:28:43 +0200827
Jens Wiklander32b31802023-10-06 16:59:46 +0200828 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200829
830cleanup:
831
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200832 /*
833 * This function is also used to import keys. However, wiping the buffers
834 * upon failure is not necessary because failure only can happen before any
835 * input is copied.
836 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200837 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200838}
839
840/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200841 * Export X into unsigned binary data, little endian
842 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200843int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
844 unsigned char *buf, size_t buflen)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200845{
Jens Wiklander32b31802023-10-06 16:59:46 +0200846 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200847}
848
849/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200850 * Export X into unsigned binary data, big endian
851 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200852int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
853 unsigned char *buf, size_t buflen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200854{
Jens Wiklander32b31802023-10-06 16:59:46 +0200855 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200856}
857
858/*
859 * Left-shift: X <<= count
860 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200861int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Jens Wiklander817466c2018-05-22 13:49:31 +0200862{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200863 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Van Eyckb0563632024-06-13 16:20:14 +0200864 size_t i;
Jens Wiklander817466c2018-05-22 13:49:31 +0200865
Jens Wiklander32b31802023-10-06 16:59:46 +0200866 i = mbedtls_mpi_bitlen(X) + count;
Jens Wiklander817466c2018-05-22 13:49:31 +0200867
Jens Wiklander32b31802023-10-06 16:59:46 +0200868 if (X->n * biL < i) {
869 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
870 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200871
872 ret = 0;
873
Tom Van Eyckb0563632024-06-13 16:20:14 +0200874 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Jens Wiklander817466c2018-05-22 13:49:31 +0200875cleanup:
876
Jens Wiklander32b31802023-10-06 16:59:46 +0200877 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200878}
879
880/*
881 * Right-shift: X >>= count
882 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200883int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Jens Wiklander817466c2018-05-22 13:49:31 +0200884{
Jens Wiklander32b31802023-10-06 16:59:46 +0200885 if (X->n != 0) {
886 mbedtls_mpi_core_shift_r(X->p, X->n, count);
Jens Wiklander817466c2018-05-22 13:49:31 +0200887 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200888 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200889}
890
891/*
892 * Compare unsigned values
893 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200894int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200895{
896 size_t i, j;
897
Jens Wiklander32b31802023-10-06 16:59:46 +0200898 for (i = X->n; i > 0; i--) {
899 if (X->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200900 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200901 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200902 }
903
Jens Wiklander32b31802023-10-06 16:59:46 +0200904 for (j = Y->n; j > 0; j--) {
905 if (Y->p[j - 1] != 0) {
906 break;
907 }
908 }
909
Tom Van Eyckb0563632024-06-13 16:20:14 +0200910 /* If i == j == 0, i.e. abs(X) == abs(Y),
911 * we end up returning 0 at the end of the function. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200912
913 if (i > j) {
914 return 1;
915 }
916 if (j > i) {
917 return -1;
918 }
919
920 for (; i > 0; i--) {
921 if (X->p[i - 1] > Y->p[i - 1]) {
922 return 1;
923 }
924 if (X->p[i - 1] < Y->p[i - 1]) {
925 return -1;
926 }
927 }
928
929 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200930}
931
932/*
933 * Compare signed values
934 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200935int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Jens Wiklander817466c2018-05-22 13:49:31 +0200936{
937 size_t i, j;
938
Jens Wiklander32b31802023-10-06 16:59:46 +0200939 for (i = X->n; i > 0; i--) {
940 if (X->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200941 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200942 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200943 }
944
Jens Wiklander32b31802023-10-06 16:59:46 +0200945 for (j = Y->n; j > 0; j--) {
946 if (Y->p[j - 1] != 0) {
947 break;
948 }
949 }
950
951 if (i == 0 && j == 0) {
952 return 0;
953 }
954
955 if (i > j) {
956 return X->s;
957 }
958 if (j > i) {
959 return -Y->s;
960 }
961
962 if (X->s > 0 && Y->s < 0) {
963 return 1;
964 }
965 if (Y->s > 0 && X->s < 0) {
966 return -1;
967 }
968
969 for (; i > 0; i--) {
970 if (X->p[i - 1] > Y->p[i - 1]) {
971 return X->s;
972 }
973 if (X->p[i - 1] < Y->p[i - 1]) {
974 return -X->s;
975 }
976 }
977
978 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200979}
980
981/*
982 * Compare signed values
983 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200984int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Jens Wiklander817466c2018-05-22 13:49:31 +0200985{
986 mbedtls_mpi Y;
987 mbedtls_mpi_uint p[1];
988
Jens Wiklander32b31802023-10-06 16:59:46 +0200989 *p = mpi_sint_abs(z);
Tom Van Eyckb0563632024-06-13 16:20:14 +0200990 Y.s = TO_SIGN(z);
Jens Wiklander817466c2018-05-22 13:49:31 +0200991 Y.n = 1;
992 Y.p = p;
993
Jens Wiklander32b31802023-10-06 16:59:46 +0200994 return mbedtls_mpi_cmp_mpi(X, &Y);
Jens Wiklander817466c2018-05-22 13:49:31 +0200995}
996
997/*
998 * Unsigned addition: X = |A| + |B| (HAC 14.7)
999 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001000int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001001{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001002 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001003 size_t j;
Tom Van Eyckb0563632024-06-13 16:20:14 +02001004 mbedtls_mpi_uint *p;
1005 mbedtls_mpi_uint c;
Jens Wiklander817466c2018-05-22 13:49:31 +02001006
Jens Wiklander32b31802023-10-06 16:59:46 +02001007 if (X == B) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001008 const mbedtls_mpi *T = A; A = X; B = T;
1009 }
1010
Jens Wiklander32b31802023-10-06 16:59:46 +02001011 if (X != A) {
1012 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1013 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001014
1015 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02001016 * X must always be positive as a result of unsigned additions.
Jens Wiklander817466c2018-05-22 13:49:31 +02001017 */
1018 X->s = 1;
1019
Jens Wiklander32b31802023-10-06 16:59:46 +02001020 for (j = B->n; j > 0; j--) {
1021 if (B->p[j - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001022 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001023 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001024 }
1025
Jens Wiklander32b31802023-10-06 16:59:46 +02001026 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1027 * and B is 0 (of any size). */
1028 if (j == 0) {
1029 return 0;
1030 }
1031
1032 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
1033
1034 /* j is the number of non-zero limbs of B. Add those to X. */
1035
Tom Van Eyckb0563632024-06-13 16:20:14 +02001036 p = X->p;
Jens Wiklander32b31802023-10-06 16:59:46 +02001037
Tom Van Eyckb0563632024-06-13 16:20:14 +02001038 c = mbedtls_mpi_core_add(p, p, B->p, j);
Jens Wiklander32b31802023-10-06 16:59:46 +02001039
1040 p += j;
1041
1042 /* Now propagate any carry */
1043
1044 while (c != 0) {
1045 if (j >= X->n) {
1046 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
1047 p = X->p + j;
Jens Wiklander817466c2018-05-22 13:49:31 +02001048 }
1049
Jens Wiklander32b31802023-10-06 16:59:46 +02001050 *p += c; c = (*p < c); j++; p++;
Jens Wiklander817466c2018-05-22 13:49:31 +02001051 }
1052
1053cleanup:
1054
Jens Wiklander32b31802023-10-06 16:59:46 +02001055 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001056}
1057
1058/*
Jerome Forissier79013242021-07-28 10:24:04 +02001059 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Jens Wiklander817466c2018-05-22 13:49:31 +02001060 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001061int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001062{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001063 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001064 size_t n;
Jerome Forissier79013242021-07-28 10:24:04 +02001065 mbedtls_mpi_uint carry;
Jens Wiklander817466c2018-05-22 13:49:31 +02001066
Jens Wiklander32b31802023-10-06 16:59:46 +02001067 for (n = B->n; n > 0; n--) {
1068 if (B->p[n - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001069 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001070 }
1071 }
1072 if (n > A->n) {
Jerome Forissier79013242021-07-28 10:24:04 +02001073 /* B >= (2^ciL)^n > A */
1074 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1075 goto cleanup;
1076 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001077
Jens Wiklander32b31802023-10-06 16:59:46 +02001078 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Jerome Forissier79013242021-07-28 10:24:04 +02001079
1080 /* Set the high limbs of X to match A. Don't touch the lower limbs
1081 * because X might be aliased to B, and we must not overwrite the
1082 * significant digits of B. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001083 if (A->n > n && A != X) {
1084 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1085 }
1086 if (X->n > A->n) {
1087 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1088 }
Jerome Forissier79013242021-07-28 10:24:04 +02001089
Jens Wiklander32b31802023-10-06 16:59:46 +02001090 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1091 if (carry != 0) {
1092 /* Propagate the carry through the rest of X. */
1093 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
1094
1095 /* If we have further carry/borrow, the result is negative. */
1096 if (carry != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001097 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1098 goto cleanup;
1099 }
Jerome Forissier79013242021-07-28 10:24:04 +02001100 }
1101
1102 /* X should always be positive as a result of unsigned subtractions. */
1103 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001104
1105cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001106 return ret;
1107}
1108
1109/* Common function for signed addition and subtraction.
1110 * Calculate A + B * flip_B where flip_B is 1 or -1.
1111 */
1112static int add_sub_mpi(mbedtls_mpi *X,
1113 const mbedtls_mpi *A, const mbedtls_mpi *B,
1114 int flip_B)
1115{
1116 int ret, s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001117
1118 s = A->s;
1119 if (A->s * B->s * flip_B < 0) {
1120 int cmp = mbedtls_mpi_cmp_abs(A, B);
1121 if (cmp >= 0) {
1122 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
1123 /* If |A| = |B|, the result is 0 and we must set the sign bit
1124 * to +1 regardless of which of A or B was negative. Otherwise,
1125 * since |A| > |B|, the sign is the sign of A. */
1126 X->s = cmp == 0 ? 1 : s;
1127 } else {
1128 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
1129 /* Since |A| < |B|, the sign is the opposite of A. */
1130 X->s = -s;
1131 }
1132 } else {
1133 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
1134 X->s = s;
1135 }
1136
1137cleanup:
1138
1139 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001140}
1141
1142/*
1143 * Signed addition: X = A + B
1144 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001145int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001146{
Jens Wiklander32b31802023-10-06 16:59:46 +02001147 return add_sub_mpi(X, A, B, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001148}
1149
1150/*
1151 * Signed subtraction: X = A - B
1152 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001153int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001154{
Jens Wiklander32b31802023-10-06 16:59:46 +02001155 return add_sub_mpi(X, A, B, -1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001156}
1157
1158/*
1159 * Signed addition: X = A + b
1160 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001161int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001162{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001163 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001164 mbedtls_mpi_uint p[1];
1165
Jens Wiklander32b31802023-10-06 16:59:46 +02001166 p[0] = mpi_sint_abs(b);
Tom Van Eyckb0563632024-06-13 16:20:14 +02001167 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001168 B.n = 1;
1169 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001170
Jens Wiklander32b31802023-10-06 16:59:46 +02001171 return mbedtls_mpi_add_mpi(X, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001172}
1173
1174/*
1175 * Signed subtraction: X = A - b
1176 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001177int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001178{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001179 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001180 mbedtls_mpi_uint p[1];
1181
Jens Wiklander32b31802023-10-06 16:59:46 +02001182 p[0] = mpi_sint_abs(b);
Tom Van Eyckb0563632024-06-13 16:20:14 +02001183 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001184 B.n = 1;
1185 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001186
Jens Wiklander32b31802023-10-06 16:59:46 +02001187 return mbedtls_mpi_sub_mpi(X, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001188}
1189
1190/*
1191 * Baseline multiplication: X = A * B (HAC 14.12)
1192 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001193int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001194{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001195 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001196 size_t i, j;
1197 mbedtls_mpi TA, TB;
Jerome Forissier79013242021-07-28 10:24:04 +02001198 int result_is_zero = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001199
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001200 mbedtls_mpi_init(&TA);
1201 mbedtls_mpi_init(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001202
Jens Wiklander32b31802023-10-06 16:59:46 +02001203 if (X == A) {
1204 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1205 }
1206 if (X == B) {
1207 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1208 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001209
Jens Wiklander32b31802023-10-06 16:59:46 +02001210 for (i = A->n; i > 0; i--) {
1211 if (A->p[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001212 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001213 }
1214 }
1215 if (i == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001216 result_is_zero = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001217 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001218
Jens Wiklander32b31802023-10-06 16:59:46 +02001219 for (j = B->n; j > 0; j--) {
1220 if (B->p[j - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001221 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001222 }
1223 }
1224 if (j == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001225 result_is_zero = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001226 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001227
Jens Wiklander32b31802023-10-06 16:59:46 +02001228 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1229 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Jens Wiklander817466c2018-05-22 13:49:31 +02001230
Tom Van Eyckb0563632024-06-13 16:20:14 +02001231 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Jens Wiklander817466c2018-05-22 13:49:31 +02001232
Jerome Forissier79013242021-07-28 10:24:04 +02001233 /* If the result is 0, we don't shortcut the operation, which reduces
1234 * but does not eliminate side channels leaking the zero-ness. We do
1235 * need to take care to set the sign bit properly since the library does
1236 * not fully support an MPI object with a value of 0 and s == -1. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001237 if (result_is_zero) {
Jerome Forissier79013242021-07-28 10:24:04 +02001238 X->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001239 } else {
Jerome Forissier79013242021-07-28 10:24:04 +02001240 X->s = A->s * B->s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001241 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001242
1243cleanup:
1244
Jens Wiklander32b31802023-10-06 16:59:46 +02001245 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Jens Wiklander817466c2018-05-22 13:49:31 +02001246
Jens Wiklander32b31802023-10-06 16:59:46 +02001247 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001248}
1249
1250/*
1251 * Baseline multiplication: X = A * b
1252 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001253int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001254{
Jerome Forissier79013242021-07-28 10:24:04 +02001255 size_t n = A->n;
Jens Wiklander32b31802023-10-06 16:59:46 +02001256 while (n > 0 && A->p[n - 1] == 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001257 --n;
Jerome Forissier79013242021-07-28 10:24:04 +02001258 }
1259
Jens Wiklander32b31802023-10-06 16:59:46 +02001260 /* The general method below doesn't work if b==0. */
1261 if (b == 0 || n == 0) {
1262 return mbedtls_mpi_lset(X, 0);
1263 }
1264
1265 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Jerome Forissier79013242021-07-28 10:24:04 +02001266 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1267 /* In general, A * b requires 1 limb more than b. If
1268 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1269 * number of limbs as A and the call to grow() is not required since
1270 * copy() will take care of the growth if needed. However, experimentally,
1271 * making the call to grow() unconditional causes slightly fewer
1272 * calls to calloc() in ECP code, presumably because it reuses the
1273 * same mpi for a while and this way the mpi is more likely to directly
Jens Wiklander32b31802023-10-06 16:59:46 +02001274 * grow to its final size.
1275 *
1276 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1277 * A,X can be the same. */
1278 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1279 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1280 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Jerome Forissier79013242021-07-28 10:24:04 +02001281
1282cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001283 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001284}
1285
1286/*
1287 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1288 * mbedtls_mpi_uint divisor, d
1289 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001290static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1291 mbedtls_mpi_uint u0,
1292 mbedtls_mpi_uint d,
1293 mbedtls_mpi_uint *r)
Jens Wiklander817466c2018-05-22 13:49:31 +02001294{
1295#if defined(MBEDTLS_HAVE_UDBL)
1296 mbedtls_t_udbl dividend, quotient;
1297#else
1298 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Jens Wiklander32b31802023-10-06 16:59:46 +02001299 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001300 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1301 mbedtls_mpi_uint u0_msw, u0_lsw;
1302 size_t s;
1303#endif
1304
1305 /*
1306 * Check for overflow
1307 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001308 if (0 == d || u1 >= d) {
1309 if (r != NULL) {
1310 *r = ~(mbedtls_mpi_uint) 0u;
1311 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001312
Jens Wiklander32b31802023-10-06 16:59:46 +02001313 return ~(mbedtls_mpi_uint) 0u;
Jens Wiklander817466c2018-05-22 13:49:31 +02001314 }
1315
1316#if defined(MBEDTLS_HAVE_UDBL)
1317 dividend = (mbedtls_t_udbl) u1 << biL;
1318 dividend |= (mbedtls_t_udbl) u0;
1319 quotient = dividend / d;
Jens Wiklander32b31802023-10-06 16:59:46 +02001320 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1321 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1322 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001323
Jens Wiklander32b31802023-10-06 16:59:46 +02001324 if (r != NULL) {
1325 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1326 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001327
1328 return (mbedtls_mpi_uint) quotient;
1329#else
1330
1331 /*
1332 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1333 * Vol. 2 - Seminumerical Algorithms, Knuth
1334 */
1335
1336 /*
1337 * Normalize the divisor, d, and dividend, u0, u1
1338 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001339 s = mbedtls_mpi_core_clz(d);
Jens Wiklander817466c2018-05-22 13:49:31 +02001340 d = d << s;
1341
1342 u1 = u1 << s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001343 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001344 u0 = u0 << s;
1345
1346 d1 = d >> biH;
1347 d0 = d & uint_halfword_mask;
1348
1349 u0_msw = u0 >> biH;
1350 u0_lsw = u0 & uint_halfword_mask;
1351
1352 /*
1353 * Find the first quotient and remainder
1354 */
1355 q1 = u1 / d1;
1356 r0 = u1 - d1 * q1;
1357
Jens Wiklander32b31802023-10-06 16:59:46 +02001358 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001359 q1 -= 1;
1360 r0 += d1;
1361
Jens Wiklander32b31802023-10-06 16:59:46 +02001362 if (r0 >= radix) {
1363 break;
1364 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001365 }
1366
Jens Wiklander32b31802023-10-06 16:59:46 +02001367 rAX = (u1 * radix) + (u0_msw - q1 * d);
Jens Wiklander817466c2018-05-22 13:49:31 +02001368 q0 = rAX / d1;
1369 r0 = rAX - q0 * d1;
1370
Jens Wiklander32b31802023-10-06 16:59:46 +02001371 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001372 q0 -= 1;
1373 r0 += d1;
1374
Jens Wiklander32b31802023-10-06 16:59:46 +02001375 if (r0 >= radix) {
1376 break;
1377 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001378 }
1379
Jens Wiklander32b31802023-10-06 16:59:46 +02001380 if (r != NULL) {
1381 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1382 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001383
1384 quotient = q1 * radix + q0;
1385
1386 return quotient;
1387#endif
1388}
1389
1390/*
1391 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
1392 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001393int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1394 const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001395{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001396 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001397 size_t i, n, t, k;
1398 mbedtls_mpi X, Y, Z, T1, T2;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001399 mbedtls_mpi_uint TP2[3];
Jens Wiklander817466c2018-05-22 13:49:31 +02001400
Jens Wiklander32b31802023-10-06 16:59:46 +02001401 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1402 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1403 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001404
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001405 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1406 mbedtls_mpi_init(&T1);
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001407 /*
1408 * Avoid dynamic memory allocations for constant-size T2.
1409 *
1410 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1411 * so nobody increase the size of the MPI and we're safe to use an on-stack
1412 * buffer.
1413 */
1414 T2.s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001415 T2.n = sizeof(TP2) / sizeof(*TP2);
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001416 T2.p = TP2;
Jens Wiklander817466c2018-05-22 13:49:31 +02001417
Jens Wiklander32b31802023-10-06 16:59:46 +02001418 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1419 if (Q != NULL) {
1420 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1421 }
1422 if (R != NULL) {
1423 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1424 }
1425 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001426 }
1427
Jens Wiklander32b31802023-10-06 16:59:46 +02001428 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1429 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001430 X.s = Y.s = 1;
1431
Jens Wiklander32b31802023-10-06 16:59:46 +02001432 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1433 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1434 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Jens Wiklander817466c2018-05-22 13:49:31 +02001435
Jens Wiklander32b31802023-10-06 16:59:46 +02001436 k = mbedtls_mpi_bitlen(&Y) % biL;
1437 if (k < biL - 1) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001438 k = biL - 1 - k;
Jens Wiklander32b31802023-10-06 16:59:46 +02001439 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1440 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1441 } else {
1442 k = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001443 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001444
1445 n = X.n - 1;
1446 t = Y.n - 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001447 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001448
Jens Wiklander32b31802023-10-06 16:59:46 +02001449 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001450 Z.p[n - t]++;
Jens Wiklander32b31802023-10-06 16:59:46 +02001451 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02001452 }
Jens Wiklander32b31802023-10-06 16:59:46 +02001453 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001454
Jens Wiklander32b31802023-10-06 16:59:46 +02001455 for (i = n; i > t; i--) {
1456 if (X.p[i] >= Y.p[t]) {
1457 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1458 } else {
1459 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1460 Y.p[t], NULL);
Jens Wiklander817466c2018-05-22 13:49:31 +02001461 }
1462
Jens Wiklander32b31802023-10-06 16:59:46 +02001463 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1464 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001465 T2.p[2] = X.p[i];
1466
Jens Wiklander817466c2018-05-22 13:49:31 +02001467 Z.p[i - t - 1]++;
Jens Wiklander32b31802023-10-06 16:59:46 +02001468 do {
Jens Wiklander817466c2018-05-22 13:49:31 +02001469 Z.p[i - t - 1]--;
1470
Jens Wiklander32b31802023-10-06 16:59:46 +02001471 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1472 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Jens Wiklander817466c2018-05-22 13:49:31 +02001473 T1.p[1] = Y.p[t];
Jens Wiklander32b31802023-10-06 16:59:46 +02001474 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1475 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001476
Jens Wiklander32b31802023-10-06 16:59:46 +02001477 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1478 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1479 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001480
Jens Wiklander32b31802023-10-06 16:59:46 +02001481 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1482 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1483 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1484 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001485 Z.p[i - t - 1]--;
1486 }
1487 }
1488
Jens Wiklander32b31802023-10-06 16:59:46 +02001489 if (Q != NULL) {
1490 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Jens Wiklander817466c2018-05-22 13:49:31 +02001491 Q->s = A->s * B->s;
1492 }
1493
Jens Wiklander32b31802023-10-06 16:59:46 +02001494 if (R != NULL) {
1495 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Jens Wiklander817466c2018-05-22 13:49:31 +02001496 X.s = A->s;
Jens Wiklander32b31802023-10-06 16:59:46 +02001497 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001498
Jens Wiklander32b31802023-10-06 16:59:46 +02001499 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001500 R->s = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001501 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001502 }
1503
1504cleanup:
1505
Jens Wiklander32b31802023-10-06 16:59:46 +02001506 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1507 mbedtls_mpi_free(&T1);
1508 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Jens Wiklander817466c2018-05-22 13:49:31 +02001509
Jens Wiklander32b31802023-10-06 16:59:46 +02001510 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001511}
1512
1513/*
1514 * Division by int: A = Q * b + R
1515 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001516int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1517 const mbedtls_mpi *A,
1518 mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001519{
Jerome Forissier039e02d2022-08-09 17:10:15 +02001520 mbedtls_mpi B;
Jens Wiklander817466c2018-05-22 13:49:31 +02001521 mbedtls_mpi_uint p[1];
1522
Jens Wiklander32b31802023-10-06 16:59:46 +02001523 p[0] = mpi_sint_abs(b);
Tom Van Eyckb0563632024-06-13 16:20:14 +02001524 B.s = TO_SIGN(b);
Jerome Forissier039e02d2022-08-09 17:10:15 +02001525 B.n = 1;
1526 B.p = p;
Jens Wiklander817466c2018-05-22 13:49:31 +02001527
Jens Wiklander32b31802023-10-06 16:59:46 +02001528 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Jens Wiklander817466c2018-05-22 13:49:31 +02001529}
1530
1531/*
1532 * Modulo: R = A mod B
1533 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001534int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001535{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001536 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001537
Jens Wiklander32b31802023-10-06 16:59:46 +02001538 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1539 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1540 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001541
Jens Wiklander32b31802023-10-06 16:59:46 +02001542 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001543
Jens Wiklander32b31802023-10-06 16:59:46 +02001544 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1545 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1546 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001547
Jens Wiklander32b31802023-10-06 16:59:46 +02001548 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1549 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1550 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001551
1552cleanup:
1553
Jens Wiklander32b31802023-10-06 16:59:46 +02001554 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001555}
1556
1557/*
1558 * Modulo: r = A mod b
1559 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001560int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Jens Wiklander817466c2018-05-22 13:49:31 +02001561{
1562 size_t i;
1563 mbedtls_mpi_uint x, y, z;
1564
Jens Wiklander32b31802023-10-06 16:59:46 +02001565 if (b == 0) {
1566 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1567 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001568
Jens Wiklander32b31802023-10-06 16:59:46 +02001569 if (b < 0) {
1570 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1571 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001572
1573 /*
1574 * handle trivial cases
1575 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001576 if (b == 1 || A->n == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001577 *r = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +02001578 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001579 }
1580
Jens Wiklander32b31802023-10-06 16:59:46 +02001581 if (b == 2) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001582 *r = A->p[0] & 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02001583 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001584 }
1585
1586 /*
1587 * general case
1588 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001589 for (i = A->n, y = 0; i > 0; i--) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001590 x = A->p[i - 1];
Jens Wiklander32b31802023-10-06 16:59:46 +02001591 y = (y << biH) | (x >> biH);
Jens Wiklander817466c2018-05-22 13:49:31 +02001592 z = y / b;
1593 y -= z * b;
1594
1595 x <<= biH;
Jens Wiklander32b31802023-10-06 16:59:46 +02001596 y = (y << biH) | (x >> biH);
Jens Wiklander817466c2018-05-22 13:49:31 +02001597 z = y / b;
1598 y -= z * b;
1599 }
1600
1601 /*
1602 * If A is negative, then the current y represents a negative value.
1603 * Flipping it to the positive side.
1604 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001605 if (A->s < 0 && y != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001606 y = b - y;
Jens Wiklander32b31802023-10-06 16:59:46 +02001607 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001608
1609 *r = y;
1610
Jens Wiklander32b31802023-10-06 16:59:46 +02001611 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001612}
1613
Jens Wiklanderbf7ce252018-11-07 08:11:29 +01001614/**
1615 * \remark Replaced by our own because the original has been removed since
1616 * mbedtls v3.6.0.
1617*/
1618void mbedtls_mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
1619{
1620 *mm = mbedtls_mpi_core_montmul_init(N->p);
1621}
1622
1623/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1624 *
1625 * \param[in,out] A One of the numbers to multiply.
1626 * It must have at least as many limbs as N
1627 * (A->n >= N->n), and any limbs beyond n are ignored.
1628 * On successful completion, A contains the result of
1629 * the multiplication A * B * R^-1 mod N where
1630 * R = (2^ciL)^n.
1631 * \param[in] B One of the numbers to multiply.
1632 * It must be nonzero and must not have more limbs than N
1633 * (B->n <= N->n).
1634 * \param[in] N The modulus. \p N must be odd.
1635 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1636 * This is -N^-1 mod 2^ciL.
1637 * \param[in,out] T A bignum for temporary storage.
1638 * It must be at least twice the limb size of N plus 1
1639 * (T->n >= 2 * N->n + 1).
1640 * Its initial content is unused and
1641 * its final content is indeterminate.
1642 * It does not get reallocated.
1643 * \remark Replaced by our own because the original has been removed since
1644 * mbedtls v3.6.0.
1645 */
1646void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1647 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1648 mbedtls_mpi *T)
1649{
1650 mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
1651}
1652
1653/**
1654 * Montgomery reduction: A = A * R^-1 mod N
1655 *
1656 * See mbedtls_mpi_montmul() regarding constraints and guarantees on the parameters.
1657 *
1658 * \remark Replaced by our own because the original has been removed since
1659 * mbedtls v3.6.0.
1660 */
1661void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1662 mbedtls_mpi_uint mm, mbedtls_mpi *T)
1663{
1664 mbedtls_mpi_uint z = 1;
1665 mbedtls_mpi U;
1666
1667 U.n = U.s = (int) z;
1668 U.p = &z;
1669
1670 mbedtls_mpi_montmul(A, &U, N, mm, T);
1671}
1672
Jens Wiklander817466c2018-05-22 13:49:31 +02001673/*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001674 * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,
1675 * this function is not constant time with respect to the exponent (parameter E).
Jens Wiklander817466c2018-05-22 13:49:31 +02001676 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001677static int mbedtls_mpi_exp_mod_optionally_safe(mbedtls_mpi *X, const mbedtls_mpi *A,
1678 const mbedtls_mpi *E, int E_public,
1679 const mbedtls_mpi *N, mbedtls_mpi *prec_RR)
Jens Wiklander817466c2018-05-22 13:49:31 +02001680{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001681 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001682
Jens Wiklander32b31802023-10-06 16:59:46 +02001683 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1684 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1685 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001686
Jens Wiklander32b31802023-10-06 16:59:46 +02001687 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1688 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1689 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001690
Jens Wiklander32b31802023-10-06 16:59:46 +02001691 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1692 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1693 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1694 }
Jerome Forissier79013242021-07-28 10:24:04 +02001695
Jens Wiklander817466c2018-05-22 13:49:31 +02001696 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001697 * Ensure that the exponent that we are passing to the core is not NULL.
Jens Wiklander817466c2018-05-22 13:49:31 +02001698 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001699 if (E->n == 0) {
1700 ret = mbedtls_mpi_lset(X, 1);
1701 return ret;
Jens Wiklander32b31802023-10-06 16:59:46 +02001702 }
Jens Wiklander32b31802023-10-06 16:59:46 +02001703
Jens Wiklander32b31802023-10-06 16:59:46 +02001704 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001705 * Allocate working memory for mbedtls_mpi_core_exp_mod()
Jens Wiklander32b31802023-10-06 16:59:46 +02001706 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001707 size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);
1708 mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint));
1709 if (T == NULL) {
1710 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001711 }
1712
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001713 mbedtls_mpi RR;
1714 mbedtls_mpi_init(&RR);
1715
Jens Wiklander817466c2018-05-22 13:49:31 +02001716 /*
1717 * If 1st call, pre-compute R^2 mod N
1718 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001719 if (prec_RR == NULL || prec_RR->p == NULL) {
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001720 MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001721
Jens Wiklander32b31802023-10-06 16:59:46 +02001722 if (prec_RR != NULL) {
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001723 *prec_RR = RR;
Jens Wiklander32b31802023-10-06 16:59:46 +02001724 }
1725 } else {
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001726 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
1727 RR = *prec_RR;
Jens Wiklander817466c2018-05-22 13:49:31 +02001728 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001729
1730 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001731 * To preserve constness we need to make a copy of A. Using X for this to
1732 * save memory.
Jens Wiklander817466c2018-05-22 13:49:31 +02001733 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001734 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
Jens Wiklander817466c2018-05-22 13:49:31 +02001735
1736 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001737 * Compensate for negative A (and correct at the end).
Jens Wiklander817466c2018-05-22 13:49:31 +02001738 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001739 X->s = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02001740
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001741 /*
1742 * Make sure that X is in a form that is safe for consumption by
1743 * the core functions.
1744 *
1745 * - The core functions will not touch the limbs of X above N->n. The
1746 * result will be correct if those limbs are 0, which the mod call
1747 * ensures.
1748 * - Also, X must have at least as many limbs as N for the calls to the
1749 * core functions.
1750 */
1751 if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
1752 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001753 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001754 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
Jens Wiklander817466c2018-05-22 13:49:31 +02001755
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001756 /*
1757 * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
1758 */
1759 {
1760 mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
1761 mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
1762 if (E_public == MBEDTLS_MPI_IS_PUBLIC) {
1763 mbedtls_mpi_core_exp_mod_unsafe(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
1764 } else {
1765 mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
Jens Wiklander817466c2018-05-22 13:49:31 +02001766 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001767 mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
Jens Wiklander817466c2018-05-22 13:49:31 +02001768 }
1769
1770 /*
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001771 * Correct for negative A.
Jens Wiklander817466c2018-05-22 13:49:31 +02001772 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001773 if (A->s == -1 && (E->p[0] & 1) != 0) {
1774 mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
1775 X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
Jens Wiklander817466c2018-05-22 13:49:31 +02001776
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001777 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02001778 }
1779
Jens Wiklander817466c2018-05-22 13:49:31 +02001780cleanup:
1781
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001782 mbedtls_mpi_zeroize_and_free(T, T_limbs);
Jens Wiklander817466c2018-05-22 13:49:31 +02001783
Jens Wiklander32b31802023-10-06 16:59:46 +02001784 if (prec_RR == NULL || prec_RR->p == NULL) {
1785 mbedtls_mpi_free(&RR);
1786 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001787
Jens Wiklander32b31802023-10-06 16:59:46 +02001788 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001789}
1790
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001791int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1792 const mbedtls_mpi *E, const mbedtls_mpi *N,
1793 mbedtls_mpi *prec_RR)
1794{
1795 return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_SECRET, N, prec_RR);
1796}
1797
Jens Wiklanderbf7ce252018-11-07 08:11:29 +01001798
1799/*
1800 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1801 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001802int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,
1803 const mbedtls_mpi *E, const mbedtls_mpi *N,
1804 mbedtls_mpi *prec_RR)
1805{
1806 return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_PUBLIC, N, prec_RR);
1807}
1808
Jens Wiklander817466c2018-05-22 13:49:31 +02001809/*
1810 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1811 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001812int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Jens Wiklander817466c2018-05-22 13:49:31 +02001813{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001814 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001815 size_t lz, lzt;
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001816 mbedtls_mpi TA, TB;
Jens Wiklander817466c2018-05-22 13:49:31 +02001817
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001818 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001819
Jens Wiklander32b31802023-10-06 16:59:46 +02001820 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1821 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Jens Wiklander817466c2018-05-22 13:49:31 +02001822
Jens Wiklander32b31802023-10-06 16:59:46 +02001823 lz = mbedtls_mpi_lsb(&TA);
1824 lzt = mbedtls_mpi_lsb(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001825
Jerome Forissier79013242021-07-28 10:24:04 +02001826 /* The loop below gives the correct result when A==0 but not when B==0.
1827 * So have a special case for B==0. Leverage the fact that we just
1828 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1829 * slightly more efficient than cmp_int(). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001830 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1831 ret = mbedtls_mpi_copy(G, A);
Jerome Forissier79013242021-07-28 10:24:04 +02001832 goto cleanup;
1833 }
1834
Jens Wiklander32b31802023-10-06 16:59:46 +02001835 if (lzt < lz) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001836 lz = lzt;
Jens Wiklander32b31802023-10-06 16:59:46 +02001837 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001838
Jens Wiklander817466c2018-05-22 13:49:31 +02001839 TA.s = TB.s = 1;
1840
Jerome Forissier79013242021-07-28 10:24:04 +02001841 /* We mostly follow the procedure described in HAC 14.54, but with some
1842 * minor differences:
1843 * - Sequences of multiplications or divisions by 2 are grouped into a
1844 * single shift operation.
1845 * - The procedure in HAC assumes that 0 < TB <= TA.
1846 * - The condition TB <= TA is not actually necessary for correctness.
1847 * TA and TB have symmetric roles except for the loop termination
1848 * condition, and the shifts at the beginning of the loop body
1849 * remove any significance from the ordering of TA vs TB before
1850 * the shifts.
1851 * - If TA = 0, the loop goes through 0 iterations and the result is
1852 * correctly TB.
1853 * - The case TB = 0 was short-circuited above.
1854 *
1855 * For the correctness proof below, decompose the original values of
1856 * A and B as
1857 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1858 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1859 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1860 * and gcd(A',B') is odd or 0.
1861 *
1862 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1863 * The code maintains the following invariant:
1864 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
1865 */
1866
1867 /* Proof that the loop terminates:
1868 * At each iteration, either the right-shift by 1 is made on a nonzero
1869 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
1870 * by at least 1, or the right-shift by 1 is made on zero and then
1871 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
1872 * since in that case TB is calculated from TB-TA with the condition TB>TA).
1873 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001874 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +02001875 /* Divisions by 2 preserve the invariant (I). */
Jens Wiklander32b31802023-10-06 16:59:46 +02001876 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
1877 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001878
Jerome Forissier79013242021-07-28 10:24:04 +02001879 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
1880 * TA-TB is even so the division by 2 has an integer result.
1881 * Invariant (I) is preserved since any odd divisor of both TA and TB
1882 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Jerome Forissier039e02d2022-08-09 17:10:15 +02001883 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Jerome Forissier79013242021-07-28 10:24:04 +02001884 * divides TA.
1885 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001886 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
1887 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
1888 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
1889 } else {
1890 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
1891 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001892 }
Jerome Forissier79013242021-07-28 10:24:04 +02001893 /* Note that one of TA or TB is still odd. */
Jens Wiklander817466c2018-05-22 13:49:31 +02001894 }
1895
Jerome Forissier79013242021-07-28 10:24:04 +02001896 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
1897 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
1898 * - If there was at least one loop iteration, then one of TA or TB is odd,
1899 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
1900 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
1901 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
1902 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
1903 */
1904
Jens Wiklander32b31802023-10-06 16:59:46 +02001905 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
1906 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Jens Wiklander817466c2018-05-22 13:49:31 +02001907
1908cleanup:
1909
Jens Wiklander32b31802023-10-06 16:59:46 +02001910 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Jens Wiklander817466c2018-05-22 13:49:31 +02001911
Jens Wiklander32b31802023-10-06 16:59:46 +02001912 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001913}
1914
Jens Wiklander817466c2018-05-22 13:49:31 +02001915/*
1916 * Fill X with size bytes of random.
Jens Wiklander32b31802023-10-06 16:59:46 +02001917 * The bytes returned from the RNG are used in a specific order which
1918 * is suitable for deterministic ECDSA (see the specification of
1919 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Jens Wiklander817466c2018-05-22 13:49:31 +02001920 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001921int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
1922 int (*f_rng)(void *, unsigned char *, size_t),
1923 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02001924{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001925 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +02001926 const size_t limbs = CHARS_TO_LIMBS(size);
Jerome Forissier5b25c762020-04-07 11:18:49 +02001927
Jerome Forissier5b25c762020-04-07 11:18:49 +02001928 /* Ensure that target MPI has exactly the necessary number of limbs */
Jens Wiklander32b31802023-10-06 16:59:46 +02001929 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
1930 if (size == 0) {
1931 return 0;
1932 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001933
Jens Wiklander32b31802023-10-06 16:59:46 +02001934 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02001935
1936cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001937 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001938}
1939
Jens Wiklander32b31802023-10-06 16:59:46 +02001940int mbedtls_mpi_random(mbedtls_mpi *X,
1941 mbedtls_mpi_sint min,
1942 const mbedtls_mpi *N,
1943 int (*f_rng)(void *, unsigned char *, size_t),
1944 void *p_rng)
Jerome Forissier79013242021-07-28 10:24:04 +02001945{
Jens Wiklander32b31802023-10-06 16:59:46 +02001946 if (min < 0) {
1947 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1948 }
1949 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
1950 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1951 }
Jerome Forissier79013242021-07-28 10:24:04 +02001952
1953 /* Ensure that target MPI has exactly the same number of limbs
1954 * as the upper bound, even if the upper bound has leading zeros.
Jens Wiklander32b31802023-10-06 16:59:46 +02001955 * This is necessary for mbedtls_mpi_core_random. */
1956 int ret = mbedtls_mpi_resize_clear(X, N->n);
1957 if (ret != 0) {
1958 return ret;
Jerome Forissier79013242021-07-28 10:24:04 +02001959 }
Jerome Forissier79013242021-07-28 10:24:04 +02001960
Jens Wiklander32b31802023-10-06 16:59:46 +02001961 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Jerome Forissier79013242021-07-28 10:24:04 +02001962}
1963
Jens Wiklander817466c2018-05-22 13:49:31 +02001964/*
1965 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1966 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001967int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Jens Wiklander817466c2018-05-22 13:49:31 +02001968{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001969 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001970 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1971
Jens Wiklander32b31802023-10-06 16:59:46 +02001972 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
1973 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1974 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001975
Sungbae Yoo4d211f32024-11-19 02:47:55 +00001976 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
1977 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
1978 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02001979
Jens Wiklander32b31802023-10-06 16:59:46 +02001980 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001981
Jens Wiklander32b31802023-10-06 16:59:46 +02001982 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001983 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
1984 goto cleanup;
1985 }
1986
Jens Wiklander32b31802023-10-06 16:59:46 +02001987 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
1988 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
1989 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
1990 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02001991
Jens Wiklander32b31802023-10-06 16:59:46 +02001992 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
1993 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
1994 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
1995 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02001996
Jens Wiklander32b31802023-10-06 16:59:46 +02001997 do {
1998 while ((TU.p[0] & 1) == 0) {
1999 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002000
Jens Wiklander32b31802023-10-06 16:59:46 +02002001 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2002 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2003 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02002004 }
2005
Jens Wiklander32b31802023-10-06 16:59:46 +02002006 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2007 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002008 }
2009
Jens Wiklander32b31802023-10-06 16:59:46 +02002010 while ((TV.p[0] & 1) == 0) {
2011 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002012
Jens Wiklander32b31802023-10-06 16:59:46 +02002013 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2014 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2015 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Jens Wiklander817466c2018-05-22 13:49:31 +02002016 }
2017
Jens Wiklander32b31802023-10-06 16:59:46 +02002018 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2019 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002020 }
2021
Jens Wiklander32b31802023-10-06 16:59:46 +02002022 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2023 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2024 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2025 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2026 } else {
2027 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2028 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2029 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Jens Wiklander817466c2018-05-22 13:49:31 +02002030 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002031 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2032
2033 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2034 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002035 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002036
Jens Wiklander32b31802023-10-06 16:59:46 +02002037 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2038 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2039 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002040
Jens Wiklander32b31802023-10-06 16:59:46 +02002041 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Jens Wiklander817466c2018-05-22 13:49:31 +02002042
2043cleanup:
2044
Jens Wiklander32b31802023-10-06 16:59:46 +02002045 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2046 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2047 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Jens Wiklander817466c2018-05-22 13:49:31 +02002048
Jens Wiklander32b31802023-10-06 16:59:46 +02002049 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002050}
2051
2052#if defined(MBEDTLS_GENPRIME)
2053
Tom Van Eyckb0563632024-06-13 16:20:14 +02002054/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
2055static const unsigned char small_prime_gaps[] = {
2056 2, 2, 4, 2, 4, 2, 4, 6,
2057 2, 6, 4, 2, 4, 6, 6, 2,
2058 6, 4, 2, 6, 4, 6, 8, 4,
2059 2, 4, 2, 4, 14, 4, 6, 2,
2060 10, 2, 6, 6, 4, 6, 6, 2,
2061 10, 2, 4, 2, 12, 12, 4, 2,
2062 4, 6, 2, 10, 6, 6, 6, 2,
2063 6, 4, 2, 10, 14, 4, 2, 4,
2064 14, 6, 10, 2, 4, 6, 8, 6,
2065 6, 4, 6, 8, 4, 8, 10, 2,
2066 10, 2, 6, 4, 6, 8, 4, 2,
2067 4, 12, 8, 4, 8, 4, 6, 12,
2068 2, 18, 6, 10, 6, 6, 2, 6,
2069 10, 6, 6, 2, 6, 6, 4, 2,
2070 12, 10, 2, 4, 6, 6, 2, 12,
2071 4, 6, 8, 10, 8, 10, 8, 6,
2072 6, 4, 8, 6, 4, 8, 4, 14,
2073 10, 12, 2, 10, 2, 4, 2, 10,
2074 14, 4, 2, 4, 14, 4, 2, 4,
2075 20, 4, 8, 10, 8, 4, 6, 6,
2076 14, 4, 6, 6, 8, 6, /*reaches 997*/
2077 0 /* the last entry is effectively unused */
Jens Wiklander817466c2018-05-22 13:49:31 +02002078};
2079
2080/*
2081 * Small divisors test (X must be positive)
2082 *
2083 * Return values:
2084 * 0: no small factor (possible prime, more tests needed)
2085 * 1: certain prime
2086 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2087 * other negative: error
2088 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002089static int mpi_check_small_factors(const mbedtls_mpi *X)
Jens Wiklander817466c2018-05-22 13:49:31 +02002090{
2091 int ret = 0;
2092 size_t i;
2093 mbedtls_mpi_uint r;
Tom Van Eyckb0563632024-06-13 16:20:14 +02002094 unsigned p = 3; /* The first odd prime */
Jens Wiklander817466c2018-05-22 13:49:31 +02002095
Jens Wiklander32b31802023-10-06 16:59:46 +02002096 if ((X->p[0] & 1) == 0) {
2097 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2098 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002099
Tom Van Eyckb0563632024-06-13 16:20:14 +02002100 for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2101 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
Jens Wiklander32b31802023-10-06 16:59:46 +02002102 if (r == 0) {
Tom Van Eyckb0563632024-06-13 16:20:14 +02002103 if (mbedtls_mpi_cmp_int(X, p) == 0) {
2104 return 1;
2105 } else {
2106 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2107 }
Jens Wiklander32b31802023-10-06 16:59:46 +02002108 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002109 }
2110
2111cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002112 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002113}
2114
2115/*
2116 * Miller-Rabin pseudo-primality test (HAC 4.24)
2117 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002118static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2119 int (*f_rng)(void *, unsigned char *, size_t),
2120 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002121{
2122 int ret, count;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002123 size_t i, j, k, s;
Jens Wiklander817466c2018-05-22 13:49:31 +02002124 mbedtls_mpi W, R, T, A, RR;
2125
Sungbae Yoo4d211f32024-11-19 02:47:55 +00002126 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2127 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2128 mbedtls_mpi_init(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002129
2130 /*
2131 * W = |X| - 1
2132 * R = W >> lsb( W )
2133 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002134 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2135 s = mbedtls_mpi_lsb(&W);
2136 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2137 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Jens Wiklander817466c2018-05-22 13:49:31 +02002138
Jens Wiklander32b31802023-10-06 16:59:46 +02002139 for (i = 0; i < rounds; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002140 /*
2141 * pick a random A, 1 < A < |X| - 1
2142 */
Jens Wiklander817466c2018-05-22 13:49:31 +02002143 count = 0;
2144 do {
Jens Wiklander32b31802023-10-06 16:59:46 +02002145 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +02002146
Jens Wiklander32b31802023-10-06 16:59:46 +02002147 j = mbedtls_mpi_bitlen(&A);
2148 k = mbedtls_mpi_bitlen(&W);
Jens Wiklander817466c2018-05-22 13:49:31 +02002149 if (j > k) {
Jens Wiklander32b31802023-10-06 16:59:46 +02002150 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002151 }
2152
Sungbae Yoo4d211f32024-11-19 02:47:55 +00002153 if (count++ > 30) {
Jens Wiklander336e3292019-01-17 11:14:38 +01002154 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2155 goto cleanup;
Jens Wiklander817466c2018-05-22 13:49:31 +02002156 }
2157
Jens Wiklander32b31802023-10-06 16:59:46 +02002158 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2159 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02002160
2161 /*
2162 * A = A^R mod |X|
2163 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002164 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Jens Wiklander817466c2018-05-22 13:49:31 +02002165
Jens Wiklander32b31802023-10-06 16:59:46 +02002166 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2167 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002168 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +02002169 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002170
2171 j = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +02002172 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002173 /*
2174 * A = A * A mod |X|
2175 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002176 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2177 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Jens Wiklander817466c2018-05-22 13:49:31 +02002178
Jens Wiklander32b31802023-10-06 16:59:46 +02002179 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002180 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02002181 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002182
2183 j++;
2184 }
2185
2186 /*
2187 * not prime if A != |X| - 1 or A == 1
2188 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002189 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2190 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002191 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2192 break;
2193 }
2194 }
2195
2196cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02002197 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2198 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2199 mbedtls_mpi_free(&RR);
Jens Wiklander817466c2018-05-22 13:49:31 +02002200
Jens Wiklander32b31802023-10-06 16:59:46 +02002201 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002202}
2203
2204/*
2205 * Pseudo-primality test: small factors, then Miller-Rabin
2206 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002207int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2208 int (*f_rng)(void *, unsigned char *, size_t),
2209 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002210{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02002211 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02002212 mbedtls_mpi XX;
2213
2214 XX.s = 1;
2215 XX.n = X->n;
2216 XX.p = X->p;
2217
Jens Wiklander32b31802023-10-06 16:59:46 +02002218 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2219 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2220 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002221 }
2222
Jens Wiklander32b31802023-10-06 16:59:46 +02002223 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2224 return 0;
2225 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002226
Jens Wiklander32b31802023-10-06 16:59:46 +02002227 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2228 if (ret == 1) {
2229 return 0;
2230 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002231
Jens Wiklander32b31802023-10-06 16:59:46 +02002232 return ret;
2233 }
2234
2235 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002236}
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002237
Jens Wiklander817466c2018-05-22 13:49:31 +02002238/*
2239 * Prime number generation
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002240 *
2241 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2242 * be either 1024 bits or 1536 bits long, and flags must contain
2243 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Jens Wiklander817466c2018-05-22 13:49:31 +02002244 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002245int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2246 int (*f_rng)(void *, unsigned char *, size_t),
2247 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +02002248{
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002249#ifdef MBEDTLS_HAVE_INT64
2250// ceil(2^63.5)
2251#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2252#else
2253// ceil(2^31.5)
2254#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2255#endif
2256 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Jens Wiklander817466c2018-05-22 13:49:31 +02002257 size_t k, n;
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002258 int rounds;
Jens Wiklander817466c2018-05-22 13:49:31 +02002259 mbedtls_mpi_uint r;
2260 mbedtls_mpi Y;
2261
Jens Wiklander32b31802023-10-06 16:59:46 +02002262 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2263 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2264 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002265
Sungbae Yoo4d211f32024-11-19 02:47:55 +00002266 mbedtls_mpi_init(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002267
Jens Wiklander32b31802023-10-06 16:59:46 +02002268 n = BITS_TO_LIMBS(nbits);
Jens Wiklander817466c2018-05-22 13:49:31 +02002269
Jens Wiklander32b31802023-10-06 16:59:46 +02002270 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002271 /*
2272 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2273 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002274 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2275 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2276 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2277 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002278 /*
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002279 * 2^-100 error probability, number of rounds computed based on HAC,
2280 * fact 4.48
Jens Wiklander817466c2018-05-22 13:49:31 +02002281 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002282 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2283 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2284 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2285 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002286 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002287
Jens Wiklander32b31802023-10-06 16:59:46 +02002288 while (1) {
2289 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002290 /* 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 +02002291 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2292 continue;
2293 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002294
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002295 k = n * biL;
Jens Wiklander32b31802023-10-06 16:59:46 +02002296 if (k > nbits) {
2297 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2298 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002299 X->p[0] |= 1;
Jens Wiklander817466c2018-05-22 13:49:31 +02002300
Jens Wiklander32b31802023-10-06 16:59:46 +02002301 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2302 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +02002303
Jens Wiklander32b31802023-10-06 16:59:46 +02002304 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander817466c2018-05-22 13:49:31 +02002305 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002306 }
2307 } else {
Jens Wiklander817466c2018-05-22 13:49:31 +02002308 /*
Jens Wiklander32b31802023-10-06 16:59:46 +02002309 * A necessary condition for Y and X = 2Y + 1 to be prime
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002310 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2311 * Make sure it is satisfied, while keeping X = 3 mod 4
Jens Wiklander817466c2018-05-22 13:49:31 +02002312 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002313
2314 X->p[0] |= 2;
2315
Jens Wiklander32b31802023-10-06 16:59:46 +02002316 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2317 if (r == 0) {
2318 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2319 } else if (r == 1) {
2320 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2321 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002322
2323 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Jens Wiklander32b31802023-10-06 16:59:46 +02002324 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2325 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002326
Jens Wiklander32b31802023-10-06 16:59:46 +02002327 while (1) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002328 /*
2329 * First, check small factors for X and Y
2330 * before doing Miller-Rabin on any of them
2331 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002332 if ((ret = mpi_check_small_factors(X)) == 0 &&
2333 (ret = mpi_check_small_factors(&Y)) == 0 &&
2334 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2335 == 0 &&
2336 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2337 == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002338 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002339 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002340
Jens Wiklander32b31802023-10-06 16:59:46 +02002341 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002342 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +02002343 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002344
2345 /*
2346 * Next candidates. We want to preserve Y = (X-1) / 2 and
2347 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2348 * so up Y by 6 and X by 12.
2349 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002350 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2351 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Jens Wiklander3d3b0592019-03-20 15:30:29 +01002352 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002353 }
2354 }
2355
2356cleanup:
2357
Jens Wiklander32b31802023-10-06 16:59:46 +02002358 mbedtls_mpi_free(&Y);
Jens Wiklander817466c2018-05-22 13:49:31 +02002359
Jens Wiklander32b31802023-10-06 16:59:46 +02002360 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002361}
2362
2363#endif /* MBEDTLS_GENPRIME */
2364
2365#if defined(MBEDTLS_SELF_TEST)
2366
2367#define GCD_PAIR_COUNT 3
2368
2369static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2370{
2371 { 693, 609, 21 },
2372 { 1764, 868, 28 },
2373 { 768454923, 542167814, 1 }
2374};
2375
2376/*
2377 * Checkup routine
2378 */
Jens Wiklander32b31802023-10-06 16:59:46 +02002379int mbedtls_mpi_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +02002380{
2381 int ret, i;
2382 mbedtls_mpi A, E, N, X, Y, U, V;
2383
Sungbae Yoo4d211f32024-11-19 02:47:55 +00002384 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2385 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002386
Jens Wiklander32b31802023-10-06 16:59:46 +02002387 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2388 "EFE021C2645FD1DC586E69184AF4A31E" \
2389 "D5F53E93B5F123FA41680867BA110131" \
2390 "944FE7952E2517337780CB0DB80E61AA" \
2391 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002392
Jens Wiklander32b31802023-10-06 16:59:46 +02002393 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2394 "B2E7EFD37075B9F03FF989C7C5051C20" \
2395 "34D2A323810251127E7BF8625A4F49A5" \
2396 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2397 "5B5C25763222FEFCCFC38B832366C29E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002398
Jens Wiklander32b31802023-10-06 16:59:46 +02002399 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2400 "0066A198186C18C10B2F5ED9B522752A" \
2401 "9830B69916E535C8F047518A889A43A5" \
2402 "94B6BED27A168D31D4A52F88925AA8F5"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002403
Jens Wiklander32b31802023-10-06 16:59:46 +02002404 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002405
Jens Wiklander32b31802023-10-06 16:59:46 +02002406 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2407 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2408 "9E857EA95A03512E2BAE7391688D264A" \
2409 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2410 "8001B72E848A38CAE1C65F78E56ABDEF" \
2411 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2412 "ECF677152EF804370C1A305CAF3B5BF1" \
2413 "30879B56C61DE584A0F53A2447A51E"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002414
Jens Wiklander32b31802023-10-06 16:59:46 +02002415 if (verbose != 0) {
2416 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2417 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002418
Jens Wiklander32b31802023-10-06 16:59:46 +02002419 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2420 if (verbose != 0) {
2421 mbedtls_printf("failed\n");
2422 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002423
2424 ret = 1;
2425 goto cleanup;
2426 }
2427
Jens Wiklander32b31802023-10-06 16:59:46 +02002428 if (verbose != 0) {
2429 mbedtls_printf("passed\n");
2430 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002431
Jens Wiklander32b31802023-10-06 16:59:46 +02002432 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002433
Jens Wiklander32b31802023-10-06 16:59:46 +02002434 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2435 "256567336059E52CAE22925474705F39A94"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002436
Jens Wiklander32b31802023-10-06 16:59:46 +02002437 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2438 "6613F26162223DF488E9CD48CC132C7A" \
2439 "0AC93C701B001B092E4E5B9F73BCD27B" \
2440 "9EE50D0657C77F374E903CDFA4C642"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002441
Jens Wiklander32b31802023-10-06 16:59:46 +02002442 if (verbose != 0) {
2443 mbedtls_printf(" MPI test #2 (div_mpi): ");
2444 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002445
Jens Wiklander32b31802023-10-06 16:59:46 +02002446 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2447 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2448 if (verbose != 0) {
2449 mbedtls_printf("failed\n");
2450 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002451
2452 ret = 1;
2453 goto cleanup;
2454 }
2455
Jens Wiklander32b31802023-10-06 16:59:46 +02002456 if (verbose != 0) {
2457 mbedtls_printf("passed\n");
2458 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002459
Jens Wiklander32b31802023-10-06 16:59:46 +02002460 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Jens Wiklander817466c2018-05-22 13:49:31 +02002461
Jens Wiklander32b31802023-10-06 16:59:46 +02002462 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2463 "36E139AEA55215609D2816998ED020BB" \
2464 "BD96C37890F65171D948E9BC7CBAA4D9" \
2465 "325D24D6A3C12710F10A09FA08AB87"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002466
Jens Wiklander32b31802023-10-06 16:59:46 +02002467 if (verbose != 0) {
2468 mbedtls_printf(" MPI test #3 (exp_mod): ");
2469 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002470
Jens Wiklander32b31802023-10-06 16:59:46 +02002471 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2472 if (verbose != 0) {
2473 mbedtls_printf("failed\n");
2474 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002475
2476 ret = 1;
2477 goto cleanup;
2478 }
2479
Jens Wiklander32b31802023-10-06 16:59:46 +02002480 if (verbose != 0) {
2481 mbedtls_printf("passed\n");
2482 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002483
Jens Wiklander32b31802023-10-06 16:59:46 +02002484 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Jens Wiklander817466c2018-05-22 13:49:31 +02002485
Jens Wiklander32b31802023-10-06 16:59:46 +02002486 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2487 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2488 "C3DBA76456363A10869622EAC2DD84EC" \
2489 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Jens Wiklander817466c2018-05-22 13:49:31 +02002490
Jens Wiklander32b31802023-10-06 16:59:46 +02002491 if (verbose != 0) {
2492 mbedtls_printf(" MPI test #4 (inv_mod): ");
2493 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002494
Jens Wiklander32b31802023-10-06 16:59:46 +02002495 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2496 if (verbose != 0) {
2497 mbedtls_printf("failed\n");
2498 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002499
2500 ret = 1;
2501 goto cleanup;
2502 }
2503
Jens Wiklander32b31802023-10-06 16:59:46 +02002504 if (verbose != 0) {
2505 mbedtls_printf("passed\n");
2506 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002507
Jens Wiklander32b31802023-10-06 16:59:46 +02002508 if (verbose != 0) {
2509 mbedtls_printf(" MPI test #5 (simple gcd): ");
2510 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002511
Jens Wiklander32b31802023-10-06 16:59:46 +02002512 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2513 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2514 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Jens Wiklander817466c2018-05-22 13:49:31 +02002515
Jens Wiklander32b31802023-10-06 16:59:46 +02002516 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Jens Wiklander817466c2018-05-22 13:49:31 +02002517
Jens Wiklander32b31802023-10-06 16:59:46 +02002518 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2519 if (verbose != 0) {
2520 mbedtls_printf("failed at %d\n", i);
2521 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002522
2523 ret = 1;
2524 goto cleanup;
2525 }
2526 }
2527
Jens Wiklander32b31802023-10-06 16:59:46 +02002528 if (verbose != 0) {
2529 mbedtls_printf("passed\n");
2530 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002531
2532cleanup:
2533
Jens Wiklander32b31802023-10-06 16:59:46 +02002534 if (ret != 0 && verbose != 0) {
2535 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2536 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002537
Jens Wiklander32b31802023-10-06 16:59:46 +02002538 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2539 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Jens Wiklander817466c2018-05-22 13:49:31 +02002540
Jens Wiklander32b31802023-10-06 16:59:46 +02002541 if (verbose != 0) {
2542 mbedtls_printf("\n");
2543 }
Jens Wiklander817466c2018-05-22 13:49:31 +02002544
Jens Wiklander32b31802023-10-06 16:59:46 +02002545 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02002546}
2547
2548#endif /* MBEDTLS_SELF_TEST */
2549
2550#endif /* MBEDTLS_BIGNUM_C */