blob: b1f9c1bf0f385126f4146c355a4cd4809bbbcfb3 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker5121ce52009-01-03 21:22:43 +00006 */
Simon Butcher15b15d12015-11-26 19:35:03 +00007
Paul Bakker5121ce52009-01-03 21:22:43 +00008/*
Simon Butcher15b15d12015-11-26 19:35:03 +00009 * The following sources were referenced in the design of this Multi-precision
10 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000011 *
Simon Butcher15b15d12015-11-26 19:35:03 +000012 * [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 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000022 */
Paul Bakker5121ce52009-01-03 21:22:43 +000023
Gilles Peskinedb09ef62020-06-03 01:43:33 +020024#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000025
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020026#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000027
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000028#include "mbedtls/bignum.h"
Janos Follath4614b9a2022-07-21 15:34:47 +010029#include "bignum_core.h"
Chris Jones4c5819c2021-03-03 17:45:34 +000030#include "bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050031#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000032#include "mbedtls/error.h"
Gabor Mezei22c9a6f2021-10-20 12:09:35 +020033#include "constant_time_internal.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Dave Rodgman351c71b2021-12-06 17:50:53 +000035#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000036#include <string.h>
37
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000038#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020039
Janos Follath4ec0fb52024-03-08 17:22:40 +000040
41
42/*
43 * Conditionally select an MPI sign in constant time.
44 * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid
45 * values.)
46 */
Janos Follathb888bc02024-03-11 09:29:53 +000047static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,
48 signed short sign1, signed short sign2)
Janos Follath4ec0fb52024-03-08 17:22:40 +000049{
Janos Follathb888bc02024-03-11 09:29:53 +000050 return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;
Janos Follath4ec0fb52024-03-08 17:22:40 +000051}
52
Dave Rodgman7d4f0192023-05-09 14:01:05 +010053/*
54 * Compare signed values in constant time
55 */
56int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
57 const mbedtls_mpi *Y,
58 unsigned *ret)
59{
Dave Rodgman1f39f032023-08-01 09:19:16 +010060 mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
Dave Rodgman7d4f0192023-05-09 14:01:05 +010061
Dave Rodgman7d4f0192023-05-09 14:01:05 +010062 if (X->n != Y->n) {
63 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
64 }
65
66 /*
Dave Rodgmanb69239c2023-08-09 14:53:18 +010067 * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.
Dave Rodgman7d4f0192023-05-09 14:01:05 +010068 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
69 */
Dave Rodgman1a7a5622023-05-17 13:47:56 +010070 X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
71 Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010072
73 /*
74 * If the signs are different, then the positive operand is the bigger.
75 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
76 * is false if X is positive (X_is_negative == 0).
77 */
Dave Rodgman1cfc43c2023-09-19 16:18:59 +010078 different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
Dave Rodgman1f39f032023-08-01 09:19:16 +010079 result = mbedtls_ct_bool_and(different_sign, X_is_negative);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010080
Dave Rodgman32d72602023-07-31 12:28:05 +010081 /*
82 * Assuming signs are the same, compare X and Y. We switch the comparison
Dave Rodgman1a7a5622023-05-17 13:47:56 +010083 * order if they are negative so that we get the right result, regardles of
84 * sign.
Dave Rodgman7d4f0192023-05-09 14:01:05 +010085 */
Dave Rodgman7d4f0192023-05-09 14:01:05 +010086
Dave Rodgman32d72602023-07-31 12:28:05 +010087 /* This array is used to conditionally swap the pointers in const time */
Dave Rodgman1a7a5622023-05-17 13:47:56 +010088 void * const p[2] = { X->p, Y->p };
Dave Rodgman98ddc012023-08-10 12:11:31 +010089 size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
Dave Rodgman2c764842023-05-18 13:28:21 +010090 mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010091
Dave Rodgman32d72602023-07-31 12:28:05 +010092 /*
Dave Rodgman1f39f032023-08-01 09:19:16 +010093 * Store in result iff the signs are the same (i.e., iff different_sign == false). If
Dave Rodgman32d72602023-07-31 12:28:05 +010094 * the signs differ, result has already been set, so we don't change it.
95 */
Dave Rodgman1f39f032023-08-01 09:19:16 +010096 result = mbedtls_ct_bool_or(result,
97 mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
Dave Rodgman1a7a5622023-05-17 13:47:56 +010098
Dave Rodgman98ddc012023-08-10 12:11:31 +010099 *ret = mbedtls_ct_uint_if_else_0(result, 1);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100100
101 return 0;
102}
103
104/*
105 * Conditionally assign X = Y, without leaking information
106 * about whether the assignment was made or not.
107 * (Leaking information about the respective sizes of X and Y is ok however.)
108 */
Dave Rodgman0a487172023-09-15 11:52:06 +0100109#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
110 (_MSC_FULL_VER < 193131103)
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100111/*
112 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
113 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
114 */
115__declspec(noinline)
116#endif
117int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
118 const mbedtls_mpi *Y,
119 unsigned char assign)
120{
121 int ret = 0;
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100122
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100123 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
124
Dave Rodgman7e9af052023-09-28 17:08:16 +0100125 {
126 mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
Dave Rodgman589ccb82023-05-17 13:55:01 +0100127
Janos Follath4ec0fb52024-03-08 17:22:40 +0000128 X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100129
Dave Rodgman7e9af052023-09-28 17:08:16 +0100130 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100131
Dave Rodgman7e9af052023-09-28 17:08:16 +0100132 mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
133 for (size_t i = Y->n; i < X->n; i++) {
134 X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
135 }
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100136 }
137
138cleanup:
139 return ret;
140}
141
142/*
143 * Conditionally swap X and Y, without leaking information
144 * about whether the swap was made or not.
145 * Here it is not ok to simply swap the pointers, which would lead to
146 * different memory access patterns when X and Y are used afterwards.
147 */
148int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
149 mbedtls_mpi *Y,
150 unsigned char swap)
151{
152 int ret = 0;
153 int s;
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100154
155 if (X == Y) {
156 return 0;
157 }
158
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100159 mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
160
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100161 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
162 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
163
164 s = X->s;
Janos Follath4ec0fb52024-03-08 17:22:40 +0000165 X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);
166 Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100167
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100168 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100169
170cleanup:
171 return ret;
172}
173
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500174/* Implementation that should never be optimized out by the compiler */
Tom Cosgrovebc345e82023-07-25 15:17:39 +0100175#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500176
Paul Bakker5121ce52009-01-03 21:22:43 +0000177/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000178 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000179 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100180void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000182 X->s = 1;
183 X->n = 0;
184 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000185}
186
187/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000188 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100190void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000191{
Gilles Peskine449bd832023-01-11 14:50:10 +0100192 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +0000193 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000195
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 if (X->p != NULL) {
Tom Cosgrove46259f62023-07-18 16:44:14 +0100197 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000198 }
199
Paul Bakker6c591fa2011-05-05 11:49:20 +0000200 X->s = 1;
201 X->n = 0;
202 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000203}
204
205/*
206 * Enlarge to the specified number of limbs
207 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100208int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +0000209{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
213 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
214 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000215
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 if (X->n < nblimbs) {
217 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
218 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
219 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000220
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 if (X->p != NULL) {
222 memcpy(p, X->p, X->n * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100223 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 }
225
Gilles Peskine053022f2023-06-29 19:26:48 +0200226 /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
227 * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
228 X->n = (unsigned short) nblimbs;
Paul Bakker5121ce52009-01-03 21:22:43 +0000229 X->p = p;
230 }
231
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000233}
234
235/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100236 * Resize down as much as possible,
237 * while keeping at least the specified number of limbs
238 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100239int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100240{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100242 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000243
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
245 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
246 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100247
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100248 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 if (X->n <= nblimbs) {
250 return mbedtls_mpi_grow(X, nblimbs);
251 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100252 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100253
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 for (i = X->n - 1; i > 0; i--) {
255 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100256 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 }
258 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100259 i++;
260
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100262 i = nblimbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100263 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100264
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
266 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
267 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 if (X->p != NULL) {
270 memcpy(p, X->p, i * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100271 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100272 }
273
Gilles Peskine053022f2023-06-29 19:26:48 +0200274 /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
275 * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
276 X->n = (unsigned short) i;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100277 X->p = p;
278
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100280}
281
Gilles Peskineed32b572021-06-02 22:17:52 +0200282/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100283static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200284{
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 if (limbs == 0) {
286 mbedtls_mpi_free(X);
287 return 0;
288 } else if (X->n == limbs) {
289 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200290 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 return 0;
292 } else {
293 mbedtls_mpi_free(X);
294 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200295 }
296}
297
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100298/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200299 * Copy the contents of Y into X.
300 *
301 * This function is not constant-time. Leading zeros in Y may be removed.
302 *
303 * Ensure that X does not shrink. This is not guaranteed by the public API,
Janos Follathc9faea02024-02-19 10:49:18 +0000304 * but some code in the bignum module might still rely on this property.
Paul Bakker5121ce52009-01-03 21:22:43 +0000305 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100306int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000307{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100308 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000309 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000310
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 if (X == Y) {
312 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200313 }
314
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 if (Y->n == 0) {
316 if (X->n != 0) {
317 X->s = 1;
318 memset(X->p, 0, X->n * ciL);
319 }
320 return 0;
321 }
322
323 for (i = Y->n - 1; i > 0; i--) {
324 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000325 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 }
327 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000328 i++;
329
330 X->s = Y->s;
331
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 if (X->n < i) {
333 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
334 } else {
335 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100336 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000337
Gilles Peskine449bd832023-01-11 14:50:10 +0100338 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000339
340cleanup:
341
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000343}
344
345/*
346 * Swap the contents of X and Y
347 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100348void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000349{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000351
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 memcpy(&T, X, sizeof(mbedtls_mpi));
353 memcpy(X, Y, sizeof(mbedtls_mpi));
354 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000355}
356
Gilles Peskine449bd832023-01-11 14:50:10 +0100357static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100358{
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 if (z >= 0) {
360 return z;
361 }
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100362 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
363 * A naive -z would have undefined behavior.
364 * Write this in a way that makes popular compilers happy (GCC, Clang,
365 * MSVC). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100367}
368
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100369/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
370 * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
Dave Rodgman73d85912023-09-28 17:00:50 +0100371#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100372
Paul Bakker5121ce52009-01-03 21:22:43 +0000373/*
374 * Set value from integer
375 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100376int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000377{
Janos Follath24eed8d2019-11-22 13:21:35 +0000378 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5121ce52009-01-03 21:22:43 +0000379
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
381 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000382
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 X->p[0] = mpi_sint_abs(z);
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100384 X->s = TO_SIGN(z);
Paul Bakker5121ce52009-01-03 21:22:43 +0000385
386cleanup:
387
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000389}
390
391/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000392 * Get a specific bit
393 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100394int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000395{
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 if (X->n * biL <= pos) {
397 return 0;
398 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000399
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000401}
402
403/*
404 * Set a bit to a specific value of 0 or 1
405 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100406int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000407{
408 int ret = 0;
409 size_t off = pos / biL;
410 size_t idx = pos % biL;
411
Gilles Peskine449bd832023-01-11 14:50:10 +0100412 if (val != 0 && val != 1) {
413 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000414 }
415
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 if (X->n * biL <= pos) {
417 if (val == 0) {
418 return 0;
419 }
420
421 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
422 }
423
424 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000426
427cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000430}
431
432/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200433 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100435size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000436{
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100437 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100439#if defined(__has_builtin)
440#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
441 #define mbedtls_mpi_uint_ctz __builtin_ctz
442#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
443 #define mbedtls_mpi_uint_ctz __builtin_ctzl
444#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
445 #define mbedtls_mpi_uint_ctz __builtin_ctzll
446#endif
447#endif
448
449#if defined(mbedtls_mpi_uint_ctz)
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 for (i = 0; i < X->n; i++) {
Dave Rodgman960eca92023-08-09 20:43:18 +0100451 if (X->p[i] != 0) {
452 return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
453 }
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100454 }
455#else
456 size_t count = 0;
457 for (i = 0; i < X->n; i++) {
458 for (size_t j = 0; j < biL; j++, count++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 if (((X->p[i] >> j) & 1) != 0) {
460 return count;
461 }
462 }
463 }
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100464#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000465
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000467}
468
469/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200470 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000471 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100472size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000473{
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 return mbedtls_mpi_core_bitlen(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000475}
476
477/*
478 * Return the total size in bytes
479 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100480size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000481{
Gilles Peskine449bd832023-01-11 14:50:10 +0100482 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000483}
484
485/*
486 * Convert an ASCII character to digit value
487 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100488static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000489{
490 *d = 255;
491
Gilles Peskine449bd832023-01-11 14:50:10 +0100492 if (c >= 0x30 && c <= 0x39) {
493 *d = c - 0x30;
494 }
495 if (c >= 0x41 && c <= 0x46) {
496 *d = c - 0x37;
497 }
498 if (c >= 0x61 && c <= 0x66) {
499 *d = c - 0x57;
500 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 if (*d >= (mbedtls_mpi_uint) radix) {
503 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
504 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
Gilles Peskine449bd832023-01-11 14:50:10 +0100506 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000507}
508
509/*
510 * Import from an ASCII string
511 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100512int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000513{
Janos Follath24eed8d2019-11-22 13:21:35 +0000514 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000515 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200516 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 mbedtls_mpi_uint d;
518 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 if (radix < 2 || radix > 16) {
521 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200522 }
523
Gilles Peskine449bd832023-01-11 14:50:10 +0100524 mbedtls_mpi_init(&T);
525
526 if (s[0] == 0) {
527 mbedtls_mpi_free(X);
528 return 0;
529 }
530
531 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200532 ++s;
533 sign = -1;
534 }
535
Gilles Peskine449bd832023-01-11 14:50:10 +0100536 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000537
Gilles Peskine449bd832023-01-11 14:50:10 +0100538 if (radix == 16) {
Dave Rodgman68ef1d62023-05-18 20:49:03 +0100539 if (slen > SIZE_MAX >> 2) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100540 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000541 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
Gilles Peskine449bd832023-01-11 14:50:10 +0100543 n = BITS_TO_LIMBS(slen << 2);
544
545 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
546 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
547
548 for (i = slen, j = 0; i > 0; i--, j++) {
549 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
550 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
551 }
552 } else {
553 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
554
555 for (i = 0; i < slen; i++) {
556 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
557 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
558 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000559 }
560 }
561
Gilles Peskine449bd832023-01-11 14:50:10 +0100562 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200563 X->s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200565
Paul Bakker5121ce52009-01-03 21:22:43 +0000566cleanup:
567
Gilles Peskine449bd832023-01-11 14:50:10 +0100568 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000571}
572
573/*
Ron Eldora16fa292018-11-20 14:07:01 +0200574 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000575 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100576static int mpi_write_hlp(mbedtls_mpi *X, int radix,
577 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000578{
Janos Follath24eed8d2019-11-22 13:21:35 +0000579 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200581 size_t length = 0;
582 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 do {
585 if (length >= buflen) {
586 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200587 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000588
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
590 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200591 /*
592 * Write the residue in the current position, as an ASCII character.
593 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100594 if (r < 0xA) {
595 *(--p_end) = (char) ('0' + r);
596 } else {
597 *(--p_end) = (char) ('A' + (r - 0xA));
598 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Ron Eldora16fa292018-11-20 14:07:01 +0200600 length++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100601 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000602
Gilles Peskine449bd832023-01-11 14:50:10 +0100603 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200604 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
606cleanup:
607
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000609}
610
611/*
612 * Export into an ASCII string
613 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100614int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
615 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000616{
Paul Bakker23986e52011-04-24 08:57:21 +0000617 int ret = 0;
618 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
Gilles Peskine449bd832023-01-11 14:50:10 +0100622 if (radix < 2 || radix > 16) {
623 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
624 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
627 if (radix >= 4) {
628 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000629 * `n`. If radix > 4, this might be a strict
630 * overapproximation of the number of
631 * radix-adic digits needed to present `n`. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100632 }
633 if (radix >= 16) {
634 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000635 * present `n`. */
636
Gilles Peskine449bd832023-01-11 14:50:10 +0100637 }
Janos Follath80470622019-03-06 13:43:02 +0000638 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000639 n += 1; /* Compensate for the divisions above, which round down `n`
640 * in case it's not even. */
641 n += 1; /* Potential '-'-sign. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100642 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000643 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
Gilles Peskine449bd832023-01-11 14:50:10 +0100645 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100646 *olen = n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100647 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000648 }
649
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100650 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100651 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000655 buflen--;
656 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000659 int c;
660 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Gilles Peskine449bd832023-01-11 14:50:10 +0100662 for (i = X->n, k = 0; i > 0; i--) {
663 for (j = ciL; j > 0; j--) {
664 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
Gilles Peskine449bd832023-01-11 14:50:10 +0100666 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000667 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000670 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000671 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000672 k = 1;
673 }
674 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100675 } else {
676 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000677
Gilles Peskine449bd832023-01-11 14:50:10 +0100678 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000679 T.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100680 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000681
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000683 }
684
685 *p++ = '\0';
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000686 *olen = (size_t) (p - buf);
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
688cleanup:
689
Gilles Peskine449bd832023-01-11 14:50:10 +0100690 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
Gilles Peskine449bd832023-01-11 14:50:10 +0100692 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000693}
694
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000696/*
697 * Read X from an opened file
698 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100699int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000700{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000702 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000703 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000704 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000705 * Buffer should have space for (short) label and decimal formatted MPI,
706 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000707 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000709
Gilles Peskine449bd832023-01-11 14:50:10 +0100710 if (radix < 2 || radix > 16) {
711 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
712 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000713
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 memset(s, 0, sizeof(s));
715 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
716 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
717 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000718
Gilles Peskine449bd832023-01-11 14:50:10 +0100719 slen = strlen(s);
720 if (slen == sizeof(s) - 2) {
721 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
722 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000723
Gilles Peskine449bd832023-01-11 14:50:10 +0100724 if (slen > 0 && s[slen - 1] == '\n') {
725 slen--; s[slen] = '\0';
726 }
727 if (slen > 0 && s[slen - 1] == '\r') {
728 slen--; s[slen] = '\0';
729 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
731 p = s + slen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100732 while (p-- > s) {
733 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100735 }
736 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
Gilles Peskine449bd832023-01-11 14:50:10 +0100738 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000739}
740
741/*
742 * Write X into an opened file (or stdout if fout == NULL)
743 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100744int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000745{
Janos Follath24eed8d2019-11-22 13:21:35 +0000746 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000747 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000748 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000749 * Buffer should have space for (short) label and decimal formatted MPI,
750 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000751 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100752 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Hanno Becker73d7d792018-12-11 10:35:51 +0000753
Gilles Peskine449bd832023-01-11 14:50:10 +0100754 if (radix < 2 || radix > 16) {
755 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
756 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
Gilles Peskine449bd832023-01-11 14:50:10 +0100758 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
Gilles Peskine449bd832023-01-11 14:50:10 +0100760 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000761
Gilles Peskine449bd832023-01-11 14:50:10 +0100762 if (p == NULL) {
763 p = "";
764 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000765
Gilles Peskine449bd832023-01-11 14:50:10 +0100766 plen = strlen(p);
767 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000768 s[slen++] = '\r';
769 s[slen++] = '\n';
770
Gilles Peskine449bd832023-01-11 14:50:10 +0100771 if (fout != NULL) {
772 if (fwrite(p, 1, plen, fout) != plen ||
773 fwrite(s, 1, slen, fout) != slen) {
774 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
775 }
776 } else {
777 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000778 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000779
780cleanup:
781
Gilles Peskine449bd832023-01-11 14:50:10 +0100782 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000783}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200784#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000785
786/*
Janos Follatha778a942019-02-13 10:28:28 +0000787 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100788 *
789 * This function is guaranteed to return an MPI with exactly the necessary
790 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000791 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100792int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
793 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000794{
Janos Follath24eed8d2019-11-22 13:21:35 +0000795 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100796 const size_t limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000797
798 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100799 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000800
Gilles Peskine449bd832023-01-11 14:50:10 +0100801 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Janos Follatha778a942019-02-13 10:28:28 +0000802
803cleanup:
804
Janos Follath171a7ef2019-02-15 16:17:45 +0000805 /*
806 * This function is also used to import keys. However, wiping the buffers
807 * upon failure is not necessary because failure only can happen before any
808 * input is copied.
809 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100810 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000811}
812
813/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000814 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100815 *
816 * This function is guaranteed to return an MPI with exactly the necessary
817 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100819int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000820{
Janos Follath24eed8d2019-11-22 13:21:35 +0000821 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100822 const size_t limbs = CHARS_TO_LIMBS(buflen);
Hanno Becker73d7d792018-12-11 10:35:51 +0000823
Hanno Becker073c1992017-10-17 15:17:27 +0100824 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100825 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000826
Gilles Peskine449bd832023-01-11 14:50:10 +0100827 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000828
829cleanup:
830
Janos Follath171a7ef2019-02-15 16:17:45 +0000831 /*
832 * This function is also used to import keys. However, wiping the buffers
833 * upon failure is not necessary because failure only can happen before any
834 * input is copied.
835 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100836 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000837}
838
839/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000840 * Export X into unsigned binary data, little endian
841 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100842int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
843 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000844{
Gilles Peskine449bd832023-01-11 14:50:10 +0100845 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Janos Follathe344d0f2019-02-19 16:17:40 +0000846}
847
848/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000849 * Export X into unsigned binary data, big endian
850 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100851int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
852 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000853{
Gilles Peskine449bd832023-01-11 14:50:10 +0100854 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000855}
856
857/*
858 * Left-shift: X <<= count
859 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100860int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000861{
Janos Follath24eed8d2019-11-22 13:21:35 +0000862 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Minos Galanakis0144b352023-05-02 14:02:32 +0100863 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000864
Gilles Peskine449bd832023-01-11 14:50:10 +0100865 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000866
Gilles Peskine449bd832023-01-11 14:50:10 +0100867 if (X->n * biL < i) {
868 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
869 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
871 ret = 0;
872
Minos Galanakis0144b352023-05-02 14:02:32 +0100873 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Paul Bakker5121ce52009-01-03 21:22:43 +0000874cleanup:
875
Gilles Peskine449bd832023-01-11 14:50:10 +0100876 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000877}
878
879/*
880 * Right-shift: X >>= count
881 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100882int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000883{
Gilles Peskine449bd832023-01-11 14:50:10 +0100884 if (X->n != 0) {
885 mbedtls_mpi_core_shift_r(X->p, X->n, count);
886 }
887 return 0;
Gilles Peskine66414202022-09-21 15:36:16 +0200888}
889
Paul Bakker5121ce52009-01-03 21:22:43 +0000890/*
891 * Compare unsigned values
892 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100893int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000894{
Paul Bakker23986e52011-04-24 08:57:21 +0000895 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896
Gilles Peskine449bd832023-01-11 14:50:10 +0100897 for (i = X->n; i > 0; i--) {
898 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000899 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100900 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000901 }
902
Gilles Peskine449bd832023-01-11 14:50:10 +0100903 for (j = Y->n; j > 0; j--) {
904 if (Y->p[j - 1] != 0) {
905 break;
906 }
907 }
908
Dave Rodgmanebcd7852023-08-09 18:56:42 +0100909 /* If i == j == 0, i.e. abs(X) == abs(Y),
910 * we end up returning 0 at the end of the function. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100911
912 if (i > j) {
913 return 1;
914 }
915 if (j > i) {
916 return -1;
917 }
918
919 for (; i > 0; i--) {
920 if (X->p[i - 1] > Y->p[i - 1]) {
921 return 1;
922 }
923 if (X->p[i - 1] < Y->p[i - 1]) {
924 return -1;
925 }
926 }
927
928 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000929}
930
931/*
932 * Compare signed values
933 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100934int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000935{
Paul Bakker23986e52011-04-24 08:57:21 +0000936 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000937
Gilles Peskine449bd832023-01-11 14:50:10 +0100938 for (i = X->n; i > 0; i--) {
939 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000940 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100941 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 }
943
Gilles Peskine449bd832023-01-11 14:50:10 +0100944 for (j = Y->n; j > 0; j--) {
945 if (Y->p[j - 1] != 0) {
946 break;
947 }
948 }
949
950 if (i == 0 && j == 0) {
951 return 0;
952 }
953
954 if (i > j) {
955 return X->s;
956 }
957 if (j > i) {
958 return -Y->s;
959 }
960
961 if (X->s > 0 && Y->s < 0) {
962 return 1;
963 }
964 if (Y->s > 0 && X->s < 0) {
965 return -1;
966 }
967
968 for (; i > 0; i--) {
969 if (X->p[i - 1] > Y->p[i - 1]) {
970 return X->s;
971 }
972 if (X->p[i - 1] < Y->p[i - 1]) {
973 return -X->s;
974 }
975 }
976
977 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000978}
979
Janos Follathee6abce2019-09-05 14:47:19 +0100980/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000981 * Compare signed values
982 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100983int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000984{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985 mbedtls_mpi Y;
986 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000987
Gilles Peskine449bd832023-01-11 14:50:10 +0100988 *p = mpi_sint_abs(z);
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100989 Y.s = TO_SIGN(z);
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 Y.n = 1;
991 Y.p = p;
992
Gilles Peskine449bd832023-01-11 14:50:10 +0100993 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +0000994}
995
996/*
997 * Unsigned addition: X = |A| + |B| (HAC 14.7)
998 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100999int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001000{
Janos Follath24eed8d2019-11-22 13:21:35 +00001001 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001002 size_t j;
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +01001003 mbedtls_mpi_uint *p;
1004 mbedtls_mpi_uint c;
Paul Bakker5121ce52009-01-03 21:22:43 +00001005
Gilles Peskine449bd832023-01-11 14:50:10 +01001006 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001008 }
1009
Gilles Peskine449bd832023-01-11 14:50:10 +01001010 if (X != A) {
1011 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1012 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001013
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001014 /*
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001015 * X must always be positive as a result of unsigned additions.
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001016 */
1017 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001018
Gilles Peskine449bd832023-01-11 14:50:10 +01001019 for (j = B->n; j > 0; j--) {
1020 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001022 }
1023 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001024
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001025 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1026 * and B is 0 (of any size). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001027 if (j == 0) {
1028 return 0;
1029 }
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001030
Gilles Peskine449bd832023-01-11 14:50:10 +01001031 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001032
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001033 /* j is the number of non-zero limbs of B. Add those to X. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001034
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +01001035 p = X->p;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001036
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +01001037 c = mbedtls_mpi_core_add(p, p, B->p, j);
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001038
1039 p += j;
1040
1041 /* Now propagate any carry */
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 while (c != 0) {
1044 if (j >= X->n) {
1045 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001046 p = X->p + j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 }
1048
Gilles Peskine449bd832023-01-11 14:50:10 +01001049 *p += c; c = (*p < c); j++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 }
1051
1052cleanup:
1053
Gilles Peskine449bd832023-01-11 14:50:10 +01001054 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001055}
1056
Paul Bakker5121ce52009-01-03 21:22:43 +00001057/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001058 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001059 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001060int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001061{
Janos Follath24eed8d2019-11-22 13:21:35 +00001062 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001063 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001064 mbedtls_mpi_uint carry;
Paul Bakker5121ce52009-01-03 21:22:43 +00001065
Gilles Peskine449bd832023-01-11 14:50:10 +01001066 for (n = B->n; n > 0; n--) {
1067 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001068 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001069 }
1070 }
1071 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001072 /* B >= (2^ciL)^n > A */
1073 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1074 goto cleanup;
1075 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001076
Gilles Peskine449bd832023-01-11 14:50:10 +01001077 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001078
1079 /* Set the high limbs of X to match A. Don't touch the lower limbs
1080 * because X might be aliased to B, and we must not overwrite the
1081 * significant digits of B. */
Aaron M. Uckoaf67d2c2023-01-17 11:52:22 -05001082 if (A->n > n && A != X) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001083 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1084 }
1085 if (X->n > A->n) {
1086 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1087 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001088
Gilles Peskine449bd832023-01-11 14:50:10 +01001089 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1090 if (carry != 0) {
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001091 /* Propagate the carry through the rest of X. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001092 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001093
1094 /* If we have further carry/borrow, the result is negative. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001095 if (carry != 0) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001096 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1097 goto cleanup;
1098 }
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001099 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001100
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001101 /* X should always be positive as a result of unsigned subtractions. */
1102 X->s = 1;
1103
Paul Bakker5121ce52009-01-03 21:22:43 +00001104cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001105 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001106}
1107
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001108/* Common function for signed addition and subtraction.
1109 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001111static int add_sub_mpi(mbedtls_mpi *X,
1112 const mbedtls_mpi *A, const mbedtls_mpi *B,
1113 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001114{
Hanno Becker73d7d792018-12-11 10:35:51 +00001115 int ret, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001116
Hanno Becker73d7d792018-12-11 10:35:51 +00001117 s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001118 if (A->s * B->s * flip_B < 0) {
1119 int cmp = mbedtls_mpi_cmp_abs(A, B);
1120 if (cmp >= 0) {
1121 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001122 /* If |A| = |B|, the result is 0 and we must set the sign bit
1123 * to +1 regardless of which of A or B was negative. Otherwise,
1124 * since |A| > |B|, the sign is the sign of A. */
1125 X->s = cmp == 0 ? 1 : s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001126 } else {
1127 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001128 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001129 X->s = -s;
1130 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001131 } else {
1132 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 X->s = s;
1134 }
1135
1136cleanup:
1137
Gilles Peskine449bd832023-01-11 14:50:10 +01001138 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001139}
1140
1141/*
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001142 * Signed addition: X = A + B
1143 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001144int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001145{
Gilles Peskine449bd832023-01-11 14:50:10 +01001146 return add_sub_mpi(X, A, B, 1);
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001147}
1148
1149/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001150 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001151 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001152int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001153{
Gilles Peskine449bd832023-01-11 14:50:10 +01001154 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001155}
1156
1157/*
1158 * Signed addition: X = A + b
1159 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001160int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001161{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001162 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001163 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001164
Gilles Peskine449bd832023-01-11 14:50:10 +01001165 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001166 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001167 B.n = 1;
1168 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001169
Gilles Peskine449bd832023-01-11 14:50:10 +01001170 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001171}
1172
1173/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001174 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001175 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001176int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001177{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001178 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001180
Gilles Peskine449bd832023-01-11 14:50:10 +01001181 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001182 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001183 B.n = 1;
1184 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
Gilles Peskine449bd832023-01-11 14:50:10 +01001186 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001187}
1188
Paul Bakker5121ce52009-01-03 21:22:43 +00001189/*
1190 * Baseline multiplication: X = A * B (HAC 14.12)
1191 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001192int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001193{
Janos Follath24eed8d2019-11-22 13:21:35 +00001194 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001195 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001197 int result_is_zero = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001199 mbedtls_mpi_init(&TA);
1200 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001201
Gilles Peskine449bd832023-01-11 14:50:10 +01001202 if (X == A) {
1203 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1204 }
1205 if (X == B) {
1206 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1207 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001208
Gilles Peskine449bd832023-01-11 14:50:10 +01001209 for (i = A->n; i > 0; i--) {
1210 if (A->p[i - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001211 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001212 }
1213 }
1214 if (i == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001215 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001216 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001217
Gilles Peskine449bd832023-01-11 14:50:10 +01001218 for (j = B->n; j > 0; j--) {
1219 if (B->p[j - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001220 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001221 }
1222 }
1223 if (j == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001224 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001225 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001226
Gilles Peskine449bd832023-01-11 14:50:10 +01001227 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1228 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001230 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Paul Bakker5121ce52009-01-03 21:22:43 +00001231
Hanno Beckerda763de2022-04-13 06:50:02 +01001232 /* If the result is 0, we don't shortcut the operation, which reduces
1233 * but does not eliminate side channels leaking the zero-ness. We do
1234 * need to take care to set the sign bit properly since the library does
1235 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001236 if (result_is_zero) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001237 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001238 } else {
Hanno Beckerda763de2022-04-13 06:50:02 +01001239 X->s = A->s * B->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001240 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001241
1242cleanup:
1243
Gilles Peskine449bd832023-01-11 14:50:10 +01001244 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001245
Gilles Peskine449bd832023-01-11 14:50:10 +01001246 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001247}
1248
1249/*
1250 * Baseline multiplication: X = A * b
1251 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001252int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001253{
Hanno Becker35771312022-04-14 11:52:11 +01001254 size_t n = A->n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001255 while (n > 0 && A->p[n - 1] == 0) {
Hanno Becker35771312022-04-14 11:52:11 +01001256 --n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001257 }
Hanno Becker35771312022-04-14 11:52:11 +01001258
Hanno Becker74a11a32022-04-06 06:27:00 +01001259 /* The general method below doesn't work if b==0. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001260 if (b == 0 || n == 0) {
1261 return mbedtls_mpi_lset(X, 0);
1262 }
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001263
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001264 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001266 /* In general, A * b requires 1 limb more than b. If
1267 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1268 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001269 * copy() will take care of the growth if needed. However, experimentally,
1270 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001271 * calls to calloc() in ECP code, presumably because it reuses the
1272 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001273 * grow to its final size.
1274 *
1275 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1276 * A,X can be the same. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001277 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1278 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1279 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001280
1281cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001282 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001283}
1284
1285/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001286 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1287 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001288 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001289static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1290 mbedtls_mpi_uint u0,
1291 mbedtls_mpi_uint d,
1292 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001293{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001294#if defined(MBEDTLS_HAVE_UDBL)
1295 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001296#else
Simon Butcher9803d072016-01-03 00:24:34 +00001297 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001298 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001299 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1300 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001301 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001302#endif
1303
Simon Butcher15b15d12015-11-26 19:35:03 +00001304 /*
1305 * Check for overflow
1306 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001307 if (0 == d || u1 >= d) {
1308 if (r != NULL) {
1309 *r = ~(mbedtls_mpi_uint) 0u;
1310 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001311
Gilles Peskine449bd832023-01-11 14:50:10 +01001312 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001313 }
1314
1315#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001316 dividend = (mbedtls_t_udbl) u1 << biL;
1317 dividend |= (mbedtls_t_udbl) u0;
1318 quotient = dividend / d;
Gilles Peskine449bd832023-01-11 14:50:10 +01001319 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1320 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1321 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001322
Gilles Peskine449bd832023-01-11 14:50:10 +01001323 if (r != NULL) {
1324 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1325 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001326
1327 return (mbedtls_mpi_uint) quotient;
1328#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001329
1330 /*
1331 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1332 * Vol. 2 - Seminumerical Algorithms, Knuth
1333 */
1334
1335 /*
1336 * Normalize the divisor, d, and dividend, u0, u1
1337 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001338 s = mbedtls_mpi_core_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001339 d = d << s;
1340
1341 u1 = u1 << s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001342 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001343 u0 = u0 << s;
1344
1345 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001346 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001347
1348 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001349 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001350
1351 /*
1352 * Find the first quotient and remainder
1353 */
1354 q1 = u1 / d1;
1355 r0 = u1 - d1 * q1;
1356
Gilles Peskine449bd832023-01-11 14:50:10 +01001357 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001358 q1 -= 1;
1359 r0 += d1;
1360
Gilles Peskine449bd832023-01-11 14:50:10 +01001361 if (r0 >= radix) {
1362 break;
1363 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001364 }
1365
Gilles Peskine449bd832023-01-11 14:50:10 +01001366 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001367 q0 = rAX / d1;
1368 r0 = rAX - q0 * d1;
1369
Gilles Peskine449bd832023-01-11 14:50:10 +01001370 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001371 q0 -= 1;
1372 r0 += d1;
1373
Gilles Peskine449bd832023-01-11 14:50:10 +01001374 if (r0 >= radix) {
1375 break;
1376 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001377 }
1378
Gilles Peskine449bd832023-01-11 14:50:10 +01001379 if (r != NULL) {
1380 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1381 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001382
1383 quotient = q1 * radix + q0;
1384
1385 return quotient;
1386#endif
1387}
1388
1389/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001392int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1393 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001394{
Janos Follath24eed8d2019-11-22 13:21:35 +00001395 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001396 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001398 mbedtls_mpi_uint TP2[3];
Paul Bakker5121ce52009-01-03 21:22:43 +00001399
Gilles Peskine449bd832023-01-11 14:50:10 +01001400 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1401 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1402 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001403
Gilles Peskine449bd832023-01-11 14:50:10 +01001404 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1405 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001406 /*
1407 * Avoid dynamic memory allocations for constant-size T2.
1408 *
1409 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1410 * so nobody increase the size of the MPI and we're safe to use an on-stack
1411 * buffer.
1412 */
Alexander K35d6d462019-10-31 14:46:45 +03001413 T2.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001414 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001415 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001416
Gilles Peskine449bd832023-01-11 14:50:10 +01001417 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1418 if (Q != NULL) {
1419 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1420 }
1421 if (R != NULL) {
1422 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1423 }
1424 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 }
1426
Gilles Peskine449bd832023-01-11 14:50:10 +01001427 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1428 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001429 X.s = Y.s = 1;
1430
Gilles Peskine449bd832023-01-11 14:50:10 +01001431 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1432 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1433 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
Gilles Peskine449bd832023-01-11 14:50:10 +01001435 k = mbedtls_mpi_bitlen(&Y) % biL;
1436 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001437 k = biL - 1 - k;
Gilles Peskine449bd832023-01-11 14:50:10 +01001438 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1439 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1440 } else {
1441 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001442 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001443
1444 n = X.n - 1;
1445 t = Y.n - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001446 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001447
Gilles Peskine449bd832023-01-11 14:50:10 +01001448 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001449 Z.p[n - t]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001450 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001451 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001452 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001453
Gilles Peskine449bd832023-01-11 14:50:10 +01001454 for (i = n; i > t; i--) {
1455 if (X.p[i] >= Y.p[t]) {
1456 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1457 } else {
1458 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1459 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001460 }
1461
Gilles Peskine449bd832023-01-11 14:50:10 +01001462 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1463 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001464 T2.p[2] = X.p[i];
1465
Paul Bakker5121ce52009-01-03 21:22:43 +00001466 Z.p[i - t - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001467 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001468 Z.p[i - t - 1]--;
1469
Gilles Peskine449bd832023-01-11 14:50:10 +01001470 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1471 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001472 T1.p[1] = Y.p[t];
Gilles Peskine449bd832023-01-11 14:50:10 +01001473 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1474 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
Gilles Peskine449bd832023-01-11 14:50:10 +01001476 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1477 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1478 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001479
Gilles Peskine449bd832023-01-11 14:50:10 +01001480 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1481 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1482 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1483 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001484 Z.p[i - t - 1]--;
1485 }
1486 }
1487
Gilles Peskine449bd832023-01-11 14:50:10 +01001488 if (Q != NULL) {
1489 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001490 Q->s = A->s * B->s;
1491 }
1492
Gilles Peskine449bd832023-01-11 14:50:10 +01001493 if (R != NULL) {
1494 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001495 X.s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001496 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001497
Gilles Peskine449bd832023-01-11 14:50:10 +01001498 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001499 R->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001500 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001501 }
1502
1503cleanup:
1504
Gilles Peskine449bd832023-01-11 14:50:10 +01001505 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1506 mbedtls_mpi_free(&T1);
1507 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
Gilles Peskine449bd832023-01-11 14:50:10 +01001509 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001510}
1511
1512/*
1513 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001515int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1516 const mbedtls_mpi *A,
1517 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001518{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001519 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001521
Gilles Peskine449bd832023-01-11 14:50:10 +01001522 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001523 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001524 B.n = 1;
1525 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
Gilles Peskine449bd832023-01-11 14:50:10 +01001527 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001528}
1529
1530/*
1531 * Modulo: R = A mod B
1532 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001533int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001534{
Janos Follath24eed8d2019-11-22 13:21:35 +00001535 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5121ce52009-01-03 21:22:43 +00001536
Gilles Peskine449bd832023-01-11 14:50:10 +01001537 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1538 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1539 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001540
Gilles Peskine449bd832023-01-11 14:50:10 +01001541 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001542
Gilles Peskine449bd832023-01-11 14:50:10 +01001543 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1544 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1545 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
Gilles Peskine449bd832023-01-11 14:50:10 +01001547 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1548 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1549 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
1551cleanup:
1552
Gilles Peskine449bd832023-01-11 14:50:10 +01001553 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001554}
1555
1556/*
1557 * Modulo: r = A mod b
1558 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001559int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001560{
Paul Bakker23986e52011-04-24 08:57:21 +00001561 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001563
Gilles Peskine449bd832023-01-11 14:50:10 +01001564 if (b == 0) {
1565 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1566 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001567
Gilles Peskine449bd832023-01-11 14:50:10 +01001568 if (b < 0) {
1569 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1570 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
1572 /*
1573 * handle trivial cases
1574 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001575 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 *r = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001577 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001578 }
1579
Gilles Peskine449bd832023-01-11 14:50:10 +01001580 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001581 *r = A->p[0] & 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001582 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 }
1584
1585 /*
1586 * general case
1587 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001588 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001589 x = A->p[i - 1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001590 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001591 z = y / b;
1592 y -= z * b;
1593
1594 x <<= biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001595 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001596 z = y / b;
1597 y -= z * b;
1598 }
1599
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001600 /*
1601 * If A is negative, then the current y represents a negative value.
1602 * Flipping it to the positive side.
1603 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001604 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001605 y = b - y;
Gilles Peskine449bd832023-01-11 14:50:10 +01001606 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001607
Paul Bakker5121ce52009-01-03 21:22:43 +00001608 *r = y;
1609
Gilles Peskine449bd832023-01-11 14:50:10 +01001610 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001611}
1612
Janos Follath38ff70e2024-08-12 18:20:59 +01001613/*
1614 * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,
1615 * this function is not constant time with respect to the exponent (parameter E).
1616 */
1617static int mbedtls_mpi_exp_mod_optionally_safe(mbedtls_mpi *X, const mbedtls_mpi *A,
Janos Follatha5fc8f32024-08-12 20:11:06 +01001618 const mbedtls_mpi *E, int E_public,
1619 const mbedtls_mpi *N, mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00001620{
Janos Follath24eed8d2019-11-22 13:21:35 +00001621 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5121ce52009-01-03 21:22:43 +00001622
Gilles Peskine449bd832023-01-11 14:50:10 +01001623 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1624 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1625 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001626
Gilles Peskine449bd832023-01-11 14:50:10 +01001627 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1628 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1629 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00001630
Gilles Peskine449bd832023-01-11 14:50:10 +01001631 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1632 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1633 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1634 }
Chris Jones9246d042020-11-25 15:12:39 +00001635
Janos Follath583f0472024-02-19 11:16:44 +00001636 /*
1637 * Ensure that the exponent that we are passing to the core is not NULL.
1638 */
1639 if (E->n == 0) {
1640 ret = mbedtls_mpi_lset(X, 1);
1641 return ret;
1642 }
1643
Janos Follath424c2652024-02-21 09:26:36 +00001644 /*
1645 * Allocate working memory for mbedtls_mpi_core_exp_mod()
1646 */
1647 size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);
Janos Follath09025722024-02-21 11:50:25 +00001648 mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint));
Janos Follath424c2652024-02-21 09:26:36 +00001649 if (T == NULL) {
1650 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
1651 }
1652
Janos Follath701ae1d2024-02-19 10:56:54 +00001653 mbedtls_mpi RR;
Janos Follath1ba40582024-02-13 12:36:13 +00001654 mbedtls_mpi_init(&RR);
Paul Bakker50546922012-05-19 08:40:49 +00001655
1656 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001657 * If 1st call, pre-compute R^2 mod N
1658 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001659 if (prec_RR == NULL || prec_RR->p == NULL) {
Janos Follath1ba40582024-02-13 12:36:13 +00001660 MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001661
Gilles Peskine449bd832023-01-11 14:50:10 +01001662 if (prec_RR != NULL) {
Janos Follath576087d2024-02-19 11:05:01 +00001663 *prec_RR = RR;
Gilles Peskine449bd832023-01-11 14:50:10 +01001664 }
1665 } else {
Janos Follath0512d172024-02-20 14:30:46 +00001666 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
Janos Follath576087d2024-02-19 11:05:01 +00001667 RR = *prec_RR;
Paul Bakker5121ce52009-01-03 21:22:43 +00001668 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001669
1670 /*
Janos Follath1ba40582024-02-13 12:36:13 +00001671 * To preserve constness we need to make a copy of A. Using X for this to
1672 * save memory.
Paul Bakker5121ce52009-01-03 21:22:43 +00001673 */
Janos Follath1ba40582024-02-13 12:36:13 +00001674 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
1676 /*
Janos Follath1ba40582024-02-13 12:36:13 +00001677 * Compensate for negative A (and correct at the end).
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 */
Janos Follath1ba40582024-02-13 12:36:13 +00001679 X->s = 1;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001680
Janos Follath8e7d6a02022-10-04 13:27:40 +01001681 /*
Janos Follath467a5492024-02-19 11:27:38 +00001682 * Make sure that X is in a form that is safe for consumption by
1683 * the core functions.
1684 *
1685 * - The core functions will not touch the limbs of X above N->n. The
1686 * result will be correct if those limbs are 0, which the mod call
1687 * ensures.
1688 * - Also, X must have at least as many limbs as N for the calls to the
1689 * core functions.
Janos Follath8e7d6a02022-10-04 13:27:40 +01001690 */
Janos Follath1ba40582024-02-13 12:36:13 +00001691 if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
1692 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
1693 }
1694 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
1695
1696 /*
Janos Follath1ba40582024-02-13 12:36:13 +00001697 * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
1698 */
Dave Rodgmand282e262024-03-11 15:28:48 +00001699 {
1700 mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
1701 mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
Janos Follath38ff70e2024-08-12 18:20:59 +01001702 if (E_public == MBEDTLS_MPI_IS_PUBLIC) {
1703 mbedtls_mpi_core_exp_mod_unsafe(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
1704 } else {
1705 mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
1706 }
Dave Rodgmand282e262024-03-11 15:28:48 +00001707 mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
1708 }
Janos Follath1ba40582024-02-13 12:36:13 +00001709
1710 /*
1711 * Correct for negative A.
1712 */
Janos Follath583f0472024-02-19 11:16:44 +00001713 if (A->s == -1 && (E->p[0] & 1) != 0) {
Janos Follath86258f52024-02-21 11:25:41 +00001714 mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
Janos Follath4ec0fb52024-03-08 17:22:40 +00001715 X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
Janos Follath86258f52024-02-21 11:25:41 +00001716
Janos Follath1ba40582024-02-13 12:36:13 +00001717 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
1718 }
Janos Follath8e7d6a02022-10-04 13:27:40 +01001719
Paul Bakker5121ce52009-01-03 21:22:43 +00001720cleanup:
1721
Janos Follath424c2652024-02-21 09:26:36 +00001722 mbedtls_mpi_zeroize_and_free(T, T_limbs);
Paul Bakker6c591fa2011-05-05 11:49:20 +00001723
Gilles Peskine449bd832023-01-11 14:50:10 +01001724 if (prec_RR == NULL || prec_RR->p == NULL) {
1725 mbedtls_mpi_free(&RR);
1726 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001727
Gilles Peskine449bd832023-01-11 14:50:10 +01001728 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001729}
1730
Manuel Pégourié-Gonnard75ed5872024-06-18 12:52:45 +02001731int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1732 const mbedtls_mpi *E, const mbedtls_mpi *N,
1733 mbedtls_mpi *prec_RR)
1734{
Janos Follatha5fc8f32024-08-12 20:11:06 +01001735 return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_SECRET, N, prec_RR);
Manuel Pégourié-Gonnard75ed5872024-06-18 12:52:45 +02001736}
1737
Janos Follath38ff70e2024-08-12 18:20:59 +01001738int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,
1739 const mbedtls_mpi *E, const mbedtls_mpi *N,
1740 mbedtls_mpi *prec_RR)
1741{
Janos Follatha5fc8f32024-08-12 20:11:06 +01001742 return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_PUBLIC, N, prec_RR);
Janos Follath38ff70e2024-08-12 18:20:59 +01001743}
1744
Paul Bakker5121ce52009-01-03 21:22:43 +00001745/*
1746 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1747 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001748int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001749{
Janos Follath24eed8d2019-11-22 13:21:35 +00001750 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001751 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03001752 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
Gilles Peskine449bd832023-01-11 14:50:10 +01001754 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001755
Gilles Peskine449bd832023-01-11 14:50:10 +01001756 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1757 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001758
Gilles Peskine449bd832023-01-11 14:50:10 +01001759 lz = mbedtls_mpi_lsb(&TA);
1760 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001761
Gilles Peskine27253bc2021-06-09 13:26:43 +02001762 /* The loop below gives the correct result when A==0 but not when B==0.
1763 * So have a special case for B==0. Leverage the fact that we just
1764 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1765 * slightly more efficient than cmp_int(). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001766 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1767 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02001768 goto cleanup;
1769 }
1770
Gilles Peskine449bd832023-01-11 14:50:10 +01001771 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001772 lz = lzt;
Gilles Peskine449bd832023-01-11 14:50:10 +01001773 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001774
Paul Bakker5121ce52009-01-03 21:22:43 +00001775 TA.s = TB.s = 1;
1776
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001777 /* We mostly follow the procedure described in HAC 14.54, but with some
1778 * minor differences:
1779 * - Sequences of multiplications or divisions by 2 are grouped into a
1780 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02001781 * - The procedure in HAC assumes that 0 < TB <= TA.
1782 * - The condition TB <= TA is not actually necessary for correctness.
1783 * TA and TB have symmetric roles except for the loop termination
1784 * condition, and the shifts at the beginning of the loop body
1785 * remove any significance from the ordering of TA vs TB before
1786 * the shifts.
1787 * - If TA = 0, the loop goes through 0 iterations and the result is
1788 * correctly TB.
1789 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001790 *
1791 * For the correctness proof below, decompose the original values of
1792 * A and B as
1793 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1794 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1795 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1796 * and gcd(A',B') is odd or 0.
1797 *
1798 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1799 * The code maintains the following invariant:
1800 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02001801 */
1802
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001803 /* Proof that the loop terminates:
1804 * At each iteration, either the right-shift by 1 is made on a nonzero
1805 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
1806 * by at least 1, or the right-shift by 1 is made on zero and then
1807 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
1808 * since in that case TB is calculated from TB-TA with the condition TB>TA).
1809 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001810 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001811 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001812 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
1813 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001815 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
1816 * TA-TB is even so the division by 2 has an integer result.
1817 * Invariant (I) is preserved since any odd divisor of both TA and TB
1818 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08001819 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001820 * divides TA.
1821 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001822 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
1823 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
1824 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
1825 } else {
1826 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
1827 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001828 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001829 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 }
1831
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001832 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
1833 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
1834 * - If there was at least one loop iteration, then one of TA or TB is odd,
1835 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
1836 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
1837 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02001838 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001839 */
1840
Gilles Peskine449bd832023-01-11 14:50:10 +01001841 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
1842 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
1844cleanup:
1845
Gilles Peskine449bd832023-01-11 14:50:10 +01001846 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001847
Gilles Peskine449bd832023-01-11 14:50:10 +01001848 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001849}
1850
Paul Bakker33dc46b2014-04-30 16:11:39 +02001851/*
1852 * Fill X with size bytes of random.
Gilles Peskine22cdd0c2022-10-27 20:15:13 +02001853 * The bytes returned from the RNG are used in a specific order which
1854 * is suitable for deterministic ECDSA (see the specification of
1855 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Paul Bakker33dc46b2014-04-30 16:11:39 +02001856 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001857int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
1858 int (*f_rng)(void *, unsigned char *, size_t),
1859 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00001860{
Janos Follath24eed8d2019-11-22 13:21:35 +00001861 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01001862 const size_t limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01001863
Hanno Beckerda1655a2017-10-18 14:21:44 +01001864 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +01001865 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
1866 if (size == 0) {
1867 return 0;
1868 }
Paul Bakker287781a2011-03-26 13:18:49 +00001869
Gilles Peskine449bd832023-01-11 14:50:10 +01001870 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00001871
1872cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001873 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00001874}
1875
Gilles Peskine449bd832023-01-11 14:50:10 +01001876int mbedtls_mpi_random(mbedtls_mpi *X,
1877 mbedtls_mpi_sint min,
1878 const mbedtls_mpi *N,
1879 int (*f_rng)(void *, unsigned char *, size_t),
1880 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02001881{
Gilles Peskine449bd832023-01-11 14:50:10 +01001882 if (min < 0) {
1883 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1884 }
1885 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
1886 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1887 }
Gilles Peskine1e918f42021-03-29 22:14:51 +02001888
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02001889 /* Ensure that target MPI has exactly the same number of limbs
1890 * as the upper bound, even if the upper bound has leading zeros.
Gilles Peskine6b7ce962022-12-15 15:04:33 +01001891 * This is necessary for mbedtls_mpi_core_random. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001892 int ret = mbedtls_mpi_resize_clear(X, N->n);
1893 if (ret != 0) {
1894 return ret;
1895 }
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02001896
Gilles Peskine449bd832023-01-11 14:50:10 +01001897 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02001898}
1899
Paul Bakker5121ce52009-01-03 21:22:43 +00001900/*
1901 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1902 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001903int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001904{
Janos Follath24eed8d2019-11-22 13:21:35 +00001905 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
Gilles Peskine449bd832023-01-11 14:50:10 +01001908 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
1909 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1910 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
Gilles Peskine449bd832023-01-11 14:50:10 +01001912 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
1913 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
1914 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
Gilles Peskine449bd832023-01-11 14:50:10 +01001916 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001917
Gilles Peskine449bd832023-01-11 14:50:10 +01001918 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 goto cleanup;
1921 }
1922
Gilles Peskine449bd832023-01-11 14:50:10 +01001923 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
1924 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
1925 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
1926 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
Gilles Peskine449bd832023-01-11 14:50:10 +01001928 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
1929 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
1930 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
1931 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
Gilles Peskine449bd832023-01-11 14:50:10 +01001933 do {
1934 while ((TU.p[0] & 1) == 0) {
1935 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001936
Gilles Peskine449bd832023-01-11 14:50:10 +01001937 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
1938 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
1939 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 }
1941
Gilles Peskine449bd832023-01-11 14:50:10 +01001942 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
1943 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 }
1945
Gilles Peskine449bd832023-01-11 14:50:10 +01001946 while ((TV.p[0] & 1) == 0) {
1947 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
Gilles Peskine449bd832023-01-11 14:50:10 +01001949 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
1950 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
1951 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00001952 }
1953
Gilles Peskine449bd832023-01-11 14:50:10 +01001954 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
1955 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001956 }
1957
Gilles Peskine449bd832023-01-11 14:50:10 +01001958 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
1959 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
1960 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
1961 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
1962 } else {
1963 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
1964 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
1965 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001966 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001967 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
1968
1969 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
1970 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001971 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
Gilles Peskine449bd832023-01-11 14:50:10 +01001973 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
1974 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
1975 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
Gilles Peskine449bd832023-01-11 14:50:10 +01001977 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
1979cleanup:
1980
Gilles Peskine449bd832023-01-11 14:50:10 +01001981 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
1982 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
1983 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
Gilles Peskine449bd832023-01-11 14:50:10 +01001985 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001986}
1987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00001989
Gilles Peskineb2bc1712019-02-08 17:27:11 +01001990/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
1991static const unsigned char small_prime_gaps[] = {
1992 2, 2, 4, 2, 4, 2, 4, 6,
1993 2, 6, 4, 2, 4, 6, 6, 2,
1994 6, 4, 2, 6, 4, 6, 8, 4,
1995 2, 4, 2, 4, 14, 4, 6, 2,
1996 10, 2, 6, 6, 4, 6, 6, 2,
1997 10, 2, 4, 2, 12, 12, 4, 2,
1998 4, 6, 2, 10, 6, 6, 6, 2,
1999 6, 4, 2, 10, 14, 4, 2, 4,
2000 14, 6, 10, 2, 4, 6, 8, 6,
2001 6, 4, 6, 8, 4, 8, 10, 2,
2002 10, 2, 6, 4, 6, 8, 4, 2,
2003 4, 12, 8, 4, 8, 4, 6, 12,
2004 2, 18, 6, 10, 6, 6, 2, 6,
2005 10, 6, 6, 2, 6, 6, 4, 2,
2006 12, 10, 2, 4, 6, 6, 2, 12,
2007 4, 6, 8, 10, 8, 10, 8, 6,
2008 6, 4, 8, 6, 4, 8, 4, 14,
2009 10, 12, 2, 10, 2, 4, 2, 10,
2010 14, 4, 2, 4, 14, 4, 2, 4,
2011 20, 4, 8, 10, 8, 4, 6, 6,
2012 14, 4, 6, 6, 8, 6, /*reaches 997*/
Gilles Peskine30b03782023-08-22 11:06:47 +02002013 0 /* the last entry is effectively unused */
Paul Bakker5121ce52009-01-03 21:22:43 +00002014};
2015
2016/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002017 * Small divisors test (X must be positive)
2018 *
2019 * Return values:
2020 * 0: no small factor (possible prime, more tests needed)
2021 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002023 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002025static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002026{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002027 int ret = 0;
2028 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 mbedtls_mpi_uint r;
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002030 unsigned p = 3; /* The first odd prime */
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
Gilles Peskine449bd832023-01-11 14:50:10 +01002032 if ((X->p[0] & 1) == 0) {
2033 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2034 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002035
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002036 for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2037 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
Gilles Peskine449bd832023-01-11 14:50:10 +01002038 if (r == 0) {
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002039 if (mbedtls_mpi_cmp_int(X, p) == 0) {
2040 return 1;
2041 } else {
2042 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2043 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002044 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002045 }
2046
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002047cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002048 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002049}
2050
2051/*
2052 * Miller-Rabin pseudo-primality test (HAC 4.24)
2053 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002054static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2055 int (*f_rng)(void *, unsigned char *, size_t),
2056 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002057{
Pascal Junodb99183d2015-03-11 16:49:45 +01002058 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002059 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002061
Gilles Peskine449bd832023-01-11 14:50:10 +01002062 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2063 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2064 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002065
Paul Bakker5121ce52009-01-03 21:22:43 +00002066 /*
2067 * W = |X| - 1
2068 * R = W >> lsb( W )
2069 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002070 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2071 s = mbedtls_mpi_lsb(&W);
2072 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2073 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
Gilles Peskine449bd832023-01-11 14:50:10 +01002075 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002076 /*
2077 * pick a random A, 1 < A < |X| - 1
2078 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002079 count = 0;
2080 do {
Gilles Peskine449bd832023-01-11 14:50:10 +01002081 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002082
Gilles Peskine449bd832023-01-11 14:50:10 +01002083 j = mbedtls_mpi_bitlen(&A);
2084 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002085 if (j > k) {
Gilles Peskine449bd832023-01-11 14:50:10 +01002086 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002087 }
2088
2089 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002090 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2091 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002092 }
2093
Gilles Peskine449bd832023-01-11 14:50:10 +01002094 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2095 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
2097 /*
2098 * A = A^R mod |X|
2099 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002100 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
Gilles Peskine449bd832023-01-11 14:50:10 +01002102 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2103 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002104 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01002105 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
2107 j = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002108 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 /*
2110 * A = A * A mod |X|
2111 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002112 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2113 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
Gilles Peskine449bd832023-01-11 14:50:10 +01002115 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002116 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01002117 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002118
2119 j++;
2120 }
2121
2122 /*
2123 * not prime if A != |X| - 1 or A == 1
2124 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002125 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2126 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 break;
2129 }
2130 }
2131
2132cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002133 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2134 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2135 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002136
Gilles Peskine449bd832023-01-11 14:50:10 +01002137 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002138}
2139
2140/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002141 * Pseudo-primality test: small factors, then Miller-Rabin
2142 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002143int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2144 int (*f_rng)(void *, unsigned char *, size_t),
2145 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002146{
Janos Follath24eed8d2019-11-22 13:21:35 +00002147 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002149
2150 XX.s = 1;
2151 XX.n = X->n;
2152 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002153
Gilles Peskine449bd832023-01-11 14:50:10 +01002154 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2155 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2156 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002157 }
2158
Gilles Peskine449bd832023-01-11 14:50:10 +01002159 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2160 return 0;
2161 }
2162
2163 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2164 if (ret == 1) {
2165 return 0;
2166 }
2167
2168 return ret;
2169 }
2170
2171 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002172}
2173
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002174/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002175 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002176 *
Janos Follathf301d232018-08-14 13:34:01 +01002177 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2178 * be either 1024 bits or 1536 bits long, and flags must contain
2179 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002181int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2182 int (*f_rng)(void *, unsigned char *, size_t),
2183 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002184{
Jethro Beekman66689272018-02-14 19:24:10 -08002185#ifdef MBEDTLS_HAVE_INT64
2186// ceil(2^63.5)
2187#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2188#else
2189// ceil(2^31.5)
2190#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2191#endif
2192 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002193 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002194 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 mbedtls_mpi_uint r;
2196 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
Gilles Peskine449bd832023-01-11 14:50:10 +01002198 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2199 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2200 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
Gilles Peskine449bd832023-01-11 14:50:10 +01002202 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
Gilles Peskine449bd832023-01-11 14:50:10 +01002204 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
Gilles Peskine449bd832023-01-11 14:50:10 +01002206 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002207 /*
2208 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2209 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002210 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2211 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2212 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2213 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002214 /*
2215 * 2^-100 error probability, number of rounds computed based on HAC,
2216 * fact 4.48
2217 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002218 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2219 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2220 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2221 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002222 }
2223
Gilles Peskine449bd832023-01-11 14:50:10 +01002224 while (1) {
2225 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002226 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
Gilles Peskine449bd832023-01-11 14:50:10 +01002227 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2228 continue;
2229 }
Jethro Beekman66689272018-02-14 19:24:10 -08002230
2231 k = n * biL;
Gilles Peskine449bd832023-01-11 14:50:10 +01002232 if (k > nbits) {
2233 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2234 }
Jethro Beekman66689272018-02-14 19:24:10 -08002235 X->p[0] |= 1;
2236
Gilles Peskine449bd832023-01-11 14:50:10 +01002237 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2238 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002239
Gilles Peskine449bd832023-01-11 14:50:10 +01002240 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002241 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002242 }
2243 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002244 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002245 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002246 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2247 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002248 */
Jethro Beekman66689272018-02-14 19:24:10 -08002249
2250 X->p[0] |= 2;
2251
Gilles Peskine449bd832023-01-11 14:50:10 +01002252 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2253 if (r == 0) {
2254 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2255 } else if (r == 1) {
2256 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2257 }
Jethro Beekman66689272018-02-14 19:24:10 -08002258
2259 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine449bd832023-01-11 14:50:10 +01002260 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2261 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002262
Gilles Peskine449bd832023-01-11 14:50:10 +01002263 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002264 /*
2265 * First, check small factors for X and Y
2266 * before doing Miller-Rabin on any of them
2267 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002268 if ((ret = mpi_check_small_factors(X)) == 0 &&
2269 (ret = mpi_check_small_factors(&Y)) == 0 &&
2270 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2271 == 0 &&
2272 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2273 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002274 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002275 }
Jethro Beekman66689272018-02-14 19:24:10 -08002276
Gilles Peskine449bd832023-01-11 14:50:10 +01002277 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002278 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002279 }
Jethro Beekman66689272018-02-14 19:24:10 -08002280
2281 /*
2282 * Next candidates. We want to preserve Y = (X-1) / 2 and
2283 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2284 * so up Y by 6 and X by 12.
2285 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002286 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2287 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002288 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 }
2290 }
2291
2292cleanup:
2293
Gilles Peskine449bd832023-01-11 14:50:10 +01002294 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002295
Gilles Peskine449bd832023-01-11 14:50:10 +01002296 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002297}
2298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
Paul Bakker23986e52011-04-24 08:57:21 +00002303#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002304
2305static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2306{
2307 { 693, 609, 21 },
2308 { 1764, 868, 28 },
2309 { 768454923, 542167814, 1 }
2310};
2311
Paul Bakker5121ce52009-01-03 21:22:43 +00002312/*
2313 * Checkup routine
2314 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002315int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00002316{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002317 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002319
Gilles Peskine449bd832023-01-11 14:50:10 +01002320 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2321 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002322
Gilles Peskine449bd832023-01-11 14:50:10 +01002323 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2324 "EFE021C2645FD1DC586E69184AF4A31E" \
2325 "D5F53E93B5F123FA41680867BA110131" \
2326 "944FE7952E2517337780CB0DB80E61AA" \
2327 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002328
Gilles Peskine449bd832023-01-11 14:50:10 +01002329 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2330 "B2E7EFD37075B9F03FF989C7C5051C20" \
2331 "34D2A323810251127E7BF8625A4F49A5" \
2332 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2333 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Gilles Peskine449bd832023-01-11 14:50:10 +01002335 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2336 "0066A198186C18C10B2F5ED9B522752A" \
2337 "9830B69916E535C8F047518A889A43A5" \
2338 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
Gilles Peskine449bd832023-01-11 14:50:10 +01002340 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Gilles Peskine449bd832023-01-11 14:50:10 +01002342 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2343 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2344 "9E857EA95A03512E2BAE7391688D264A" \
2345 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2346 "8001B72E848A38CAE1C65F78E56ABDEF" \
2347 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2348 "ECF677152EF804370C1A305CAF3B5BF1" \
2349 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
Gilles Peskine449bd832023-01-11 14:50:10 +01002351 if (verbose != 0) {
2352 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2353 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
Gilles Peskine449bd832023-01-11 14:50:10 +01002355 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2356 if (verbose != 0) {
2357 mbedtls_printf("failed\n");
2358 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002359
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002360 ret = 1;
2361 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 }
2363
Gilles Peskine449bd832023-01-11 14:50:10 +01002364 if (verbose != 0) {
2365 mbedtls_printf("passed\n");
2366 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
Gilles Peskine449bd832023-01-11 14:50:10 +01002368 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
Gilles Peskine449bd832023-01-11 14:50:10 +01002370 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2371 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
Gilles Peskine449bd832023-01-11 14:50:10 +01002373 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2374 "6613F26162223DF488E9CD48CC132C7A" \
2375 "0AC93C701B001B092E4E5B9F73BCD27B" \
2376 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Gilles Peskine449bd832023-01-11 14:50:10 +01002378 if (verbose != 0) {
2379 mbedtls_printf(" MPI test #2 (div_mpi): ");
2380 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002381
Gilles Peskine449bd832023-01-11 14:50:10 +01002382 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2383 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2384 if (verbose != 0) {
2385 mbedtls_printf("failed\n");
2386 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002388 ret = 1;
2389 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002390 }
2391
Gilles Peskine449bd832023-01-11 14:50:10 +01002392 if (verbose != 0) {
2393 mbedtls_printf("passed\n");
2394 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Gilles Peskine449bd832023-01-11 14:50:10 +01002396 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Gilles Peskine449bd832023-01-11 14:50:10 +01002398 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2399 "36E139AEA55215609D2816998ED020BB" \
2400 "BD96C37890F65171D948E9BC7CBAA4D9" \
2401 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
Gilles Peskine449bd832023-01-11 14:50:10 +01002403 if (verbose != 0) {
2404 mbedtls_printf(" MPI test #3 (exp_mod): ");
2405 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002406
Gilles Peskine449bd832023-01-11 14:50:10 +01002407 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2408 if (verbose != 0) {
2409 mbedtls_printf("failed\n");
2410 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002411
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002412 ret = 1;
2413 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002414 }
2415
Gilles Peskine449bd832023-01-11 14:50:10 +01002416 if (verbose != 0) {
2417 mbedtls_printf("passed\n");
2418 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002419
Gilles Peskine449bd832023-01-11 14:50:10 +01002420 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002421
Gilles Peskine449bd832023-01-11 14:50:10 +01002422 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2423 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2424 "C3DBA76456363A10869622EAC2DD84EC" \
2425 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002426
Gilles Peskine449bd832023-01-11 14:50:10 +01002427 if (verbose != 0) {
2428 mbedtls_printf(" MPI test #4 (inv_mod): ");
2429 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
Gilles Peskine449bd832023-01-11 14:50:10 +01002431 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2432 if (verbose != 0) {
2433 mbedtls_printf("failed\n");
2434 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002436 ret = 1;
2437 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002438 }
2439
Gilles Peskine449bd832023-01-11 14:50:10 +01002440 if (verbose != 0) {
2441 mbedtls_printf("passed\n");
2442 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002443
Gilles Peskine449bd832023-01-11 14:50:10 +01002444 if (verbose != 0) {
2445 mbedtls_printf(" MPI test #5 (simple gcd): ");
2446 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002447
Gilles Peskine449bd832023-01-11 14:50:10 +01002448 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2449 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2450 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002451
Gilles Peskine449bd832023-01-11 14:50:10 +01002452 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002453
Gilles Peskine449bd832023-01-11 14:50:10 +01002454 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2455 if (verbose != 0) {
2456 mbedtls_printf("failed at %d\n", i);
2457 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002458
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002459 ret = 1;
2460 goto cleanup;
2461 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002462 }
2463
Gilles Peskine449bd832023-01-11 14:50:10 +01002464 if (verbose != 0) {
2465 mbedtls_printf("passed\n");
2466 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002467
Paul Bakker5121ce52009-01-03 21:22:43 +00002468cleanup:
2469
Gilles Peskine449bd832023-01-11 14:50:10 +01002470 if (ret != 0 && verbose != 0) {
2471 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2472 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002473
Gilles Peskine449bd832023-01-11 14:50:10 +01002474 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2475 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002476
Gilles Peskine449bd832023-01-11 14:50:10 +01002477 if (verbose != 0) {
2478 mbedtls_printf("\n");
2479 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002480
Gilles Peskine449bd832023-01-11 14:50:10 +01002481 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002482}
2483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486#endif /* MBEDTLS_BIGNUM_C */