blob: 6a80720ced2db4481527dc2678b4071525163f44 [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
Dave Rodgman7d4f0192023-05-09 14:01:05 +010040/*
41 * Compare signed values in constant time
42 */
43int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
44 const mbedtls_mpi *Y,
45 unsigned *ret)
46{
Dave Rodgman1f39f032023-08-01 09:19:16 +010047 mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
Dave Rodgman7d4f0192023-05-09 14:01:05 +010048
Dave Rodgman7d4f0192023-05-09 14:01:05 +010049 if (X->n != Y->n) {
50 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
51 }
52
53 /*
Dave Rodgmanb69239c2023-08-09 14:53:18 +010054 * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.
Dave Rodgman7d4f0192023-05-09 14:01:05 +010055 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
56 */
Dave Rodgman1a7a5622023-05-17 13:47:56 +010057 X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
58 Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010059
60 /*
61 * If the signs are different, then the positive operand is the bigger.
62 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
63 * is false if X is positive (X_is_negative == 0).
64 */
Dave Rodgman1cfc43c2023-09-19 16:18:59 +010065 different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
Dave Rodgman1f39f032023-08-01 09:19:16 +010066 result = mbedtls_ct_bool_and(different_sign, X_is_negative);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010067
Dave Rodgman32d72602023-07-31 12:28:05 +010068 /*
69 * Assuming signs are the same, compare X and Y. We switch the comparison
Dave Rodgman1a7a5622023-05-17 13:47:56 +010070 * order if they are negative so that we get the right result, regardles of
71 * sign.
Dave Rodgman7d4f0192023-05-09 14:01:05 +010072 */
Dave Rodgman7d4f0192023-05-09 14:01:05 +010073
Dave Rodgman32d72602023-07-31 12:28:05 +010074 /* This array is used to conditionally swap the pointers in const time */
Dave Rodgman1a7a5622023-05-17 13:47:56 +010075 void * const p[2] = { X->p, Y->p };
Dave Rodgman98ddc012023-08-10 12:11:31 +010076 size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
Dave Rodgman2c764842023-05-18 13:28:21 +010077 mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010078
Dave Rodgman32d72602023-07-31 12:28:05 +010079 /*
Dave Rodgman1f39f032023-08-01 09:19:16 +010080 * Store in result iff the signs are the same (i.e., iff different_sign == false). If
Dave Rodgman32d72602023-07-31 12:28:05 +010081 * the signs differ, result has already been set, so we don't change it.
82 */
Dave Rodgman1f39f032023-08-01 09:19:16 +010083 result = mbedtls_ct_bool_or(result,
84 mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
Dave Rodgman1a7a5622023-05-17 13:47:56 +010085
Dave Rodgman98ddc012023-08-10 12:11:31 +010086 *ret = mbedtls_ct_uint_if_else_0(result, 1);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010087
88 return 0;
89}
90
91/*
92 * Conditionally assign X = Y, without leaking information
93 * about whether the assignment was made or not.
94 * (Leaking information about the respective sizes of X and Y is ok however.)
95 */
Dave Rodgman0a487172023-09-15 11:52:06 +010096#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
97 (_MSC_FULL_VER < 193131103)
Dave Rodgman7d4f0192023-05-09 14:01:05 +010098/*
99 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
100 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
101 */
102__declspec(noinline)
103#endif
104int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
105 const mbedtls_mpi *Y,
106 unsigned char assign)
107{
108 int ret = 0;
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100109
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100110 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
111
Dave Rodgman7e9af052023-09-28 17:08:16 +0100112 {
113 mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
Dave Rodgman589ccb82023-05-17 13:55:01 +0100114
Dave Rodgman7e9af052023-09-28 17:08:16 +0100115 X->s = (int) mbedtls_ct_uint_if(do_assign, Y->s, X->s);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100116
Dave Rodgman7e9af052023-09-28 17:08:16 +0100117 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100118
Dave Rodgman7e9af052023-09-28 17:08:16 +0100119 mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
120 for (size_t i = Y->n; i < X->n; i++) {
121 X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
122 }
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100123 }
124
125cleanup:
126 return ret;
127}
128
129/*
130 * Conditionally swap X and Y, without leaking information
131 * about whether the swap was made or not.
132 * Here it is not ok to simply swap the pointers, which would lead to
133 * different memory access patterns when X and Y are used afterwards.
134 */
135int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
136 mbedtls_mpi *Y,
137 unsigned char swap)
138{
139 int ret = 0;
140 int s;
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100141
142 if (X == Y) {
143 return 0;
144 }
145
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100146 mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
147
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100148 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
149 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
150
151 s = X->s;
Dave Rodgman2b4486a2023-05-17 15:51:59 +0100152 X->s = (int) mbedtls_ct_uint_if(do_swap, Y->s, X->s);
153 Y->s = (int) mbedtls_ct_uint_if(do_swap, s, Y->s);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100154
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100155 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100156
157cleanup:
158 return ret;
159}
160
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500161/* Implementation that should never be optimized out by the compiler */
Tom Cosgrovebc345e82023-07-25 15:17:39 +0100162#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500163
Paul Bakker5121ce52009-01-03 21:22:43 +0000164/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000165 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000166 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100167void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000168{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000169 X->s = 1;
170 X->n = 0;
171 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000172}
173
174/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000175 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000176 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100177void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000178{
Gilles Peskine449bd832023-01-11 14:50:10 +0100179 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +0000180 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100181 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000182
Gilles Peskine449bd832023-01-11 14:50:10 +0100183 if (X->p != NULL) {
Tom Cosgrove46259f62023-07-18 16:44:14 +0100184 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000185 }
186
Paul Bakker6c591fa2011-05-05 11:49:20 +0000187 X->s = 1;
188 X->n = 0;
189 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000190}
191
192/*
193 * Enlarge to the specified number of limbs
194 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100195int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +0000196{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 mbedtls_mpi_uint *p;
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
200 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
201 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000202
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 if (X->n < nblimbs) {
204 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
205 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
206 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 if (X->p != NULL) {
209 memcpy(p, X->p, X->n * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100210 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000211 }
212
Gilles Peskine053022f2023-06-29 19:26:48 +0200213 /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
214 * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
215 X->n = (unsigned short) nblimbs;
Paul Bakker5121ce52009-01-03 21:22:43 +0000216 X->p = p;
217 }
218
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000220}
221
222/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100223 * Resize down as much as possible,
224 * while keeping at least the specified number of limbs
225 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100226int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100227{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100229 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000230
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
232 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
233 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100234
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100235 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 if (X->n <= nblimbs) {
237 return mbedtls_mpi_grow(X, nblimbs);
238 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100239 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100240
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 for (i = X->n - 1; i > 0; i--) {
242 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100243 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 }
245 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100246 i++;
247
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100249 i = nblimbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100251
Gilles Peskine449bd832023-01-11 14:50:10 +0100252 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
253 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
254 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100255
Gilles Peskine449bd832023-01-11 14:50:10 +0100256 if (X->p != NULL) {
257 memcpy(p, X->p, i * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100258 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100259 }
260
Gilles Peskine053022f2023-06-29 19:26:48 +0200261 /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
262 * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
263 X->n = (unsigned short) i;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100264 X->p = p;
265
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100267}
268
Gilles Peskineed32b572021-06-02 22:17:52 +0200269/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100270static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200271{
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 if (limbs == 0) {
273 mbedtls_mpi_free(X);
274 return 0;
275 } else if (X->n == limbs) {
276 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200277 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 return 0;
279 } else {
280 mbedtls_mpi_free(X);
281 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200282 }
283}
284
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100285/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200286 * Copy the contents of Y into X.
287 *
288 * This function is not constant-time. Leading zeros in Y may be removed.
289 *
290 * Ensure that X does not shrink. This is not guaranteed by the public API,
291 * but some code in the bignum module relies on this property, for example
292 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000293 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100294int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000295{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100296 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000297 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000298
Gilles Peskine449bd832023-01-11 14:50:10 +0100299 if (X == Y) {
300 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200301 }
302
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 if (Y->n == 0) {
304 if (X->n != 0) {
305 X->s = 1;
306 memset(X->p, 0, X->n * ciL);
307 }
308 return 0;
309 }
310
311 for (i = Y->n - 1; i > 0; i--) {
312 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 }
315 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000316 i++;
317
318 X->s = Y->s;
319
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 if (X->n < i) {
321 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
322 } else {
323 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100324 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000325
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000327
328cleanup:
329
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000331}
332
333/*
334 * Swap the contents of X and Y
335 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100336void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000337{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000339
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 memcpy(&T, X, sizeof(mbedtls_mpi));
341 memcpy(X, Y, sizeof(mbedtls_mpi));
342 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000343}
344
Gilles Peskine449bd832023-01-11 14:50:10 +0100345static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100346{
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 if (z >= 0) {
348 return z;
349 }
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100350 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
351 * A naive -z would have undefined behavior.
352 * Write this in a way that makes popular compilers happy (GCC, Clang,
353 * MSVC). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100355}
356
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100357/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
358 * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
Dave Rodgman73d85912023-09-28 17:00:50 +0100359#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100360
Paul Bakker5121ce52009-01-03 21:22:43 +0000361/*
362 * Set value from integer
363 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100364int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000365{
Janos Follath24eed8d2019-11-22 13:21:35 +0000366 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5121ce52009-01-03 21:22:43 +0000367
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
369 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000370
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 X->p[0] = mpi_sint_abs(z);
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100372 X->s = TO_SIGN(z);
Paul Bakker5121ce52009-01-03 21:22:43 +0000373
374cleanup:
375
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000377}
378
379/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000380 * Get a specific bit
381 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100382int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000383{
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 if (X->n * biL <= pos) {
385 return 0;
386 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000387
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000389}
390
391/*
392 * Set a bit to a specific value of 0 or 1
393 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100394int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000395{
396 int ret = 0;
397 size_t off = pos / biL;
398 size_t idx = pos % biL;
399
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 if (val != 0 && val != 1) {
401 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000402 }
403
Gilles Peskine449bd832023-01-11 14:50:10 +0100404 if (X->n * biL <= pos) {
405 if (val == 0) {
406 return 0;
407 }
408
409 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
410 }
411
412 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000414
415cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200416
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000418}
419
420/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200421 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000422 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100423size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000424{
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100425 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100427#if defined(__has_builtin)
428#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
429 #define mbedtls_mpi_uint_ctz __builtin_ctz
430#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
431 #define mbedtls_mpi_uint_ctz __builtin_ctzl
432#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
433 #define mbedtls_mpi_uint_ctz __builtin_ctzll
434#endif
435#endif
436
437#if defined(mbedtls_mpi_uint_ctz)
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 for (i = 0; i < X->n; i++) {
Dave Rodgman960eca92023-08-09 20:43:18 +0100439 if (X->p[i] != 0) {
440 return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
441 }
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100442 }
443#else
444 size_t count = 0;
445 for (i = 0; i < X->n; i++) {
446 for (size_t j = 0; j < biL; j++, count++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 if (((X->p[i] >> j) & 1) != 0) {
448 return count;
449 }
450 }
451 }
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100452#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000455}
456
457/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200458 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000459 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100460size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000461{
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 return mbedtls_mpi_core_bitlen(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000463}
464
465/*
466 * Return the total size in bytes
467 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100468size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000469{
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000471}
472
473/*
474 * Convert an ASCII character to digit value
475 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100476static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000477{
478 *d = 255;
479
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 if (c >= 0x30 && c <= 0x39) {
481 *d = c - 0x30;
482 }
483 if (c >= 0x41 && c <= 0x46) {
484 *d = c - 0x37;
485 }
486 if (c >= 0x61 && c <= 0x66) {
487 *d = c - 0x57;
488 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 if (*d >= (mbedtls_mpi_uint) radix) {
491 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
492 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000493
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000495}
496
497/*
498 * Import from an ASCII string
499 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100500int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000501{
Janos Follath24eed8d2019-11-22 13:21:35 +0000502 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000503 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200504 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 mbedtls_mpi_uint d;
506 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000507
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 if (radix < 2 || radix > 16) {
509 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200510 }
511
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 mbedtls_mpi_init(&T);
513
514 if (s[0] == 0) {
515 mbedtls_mpi_free(X);
516 return 0;
517 }
518
519 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200520 ++s;
521 sign = -1;
522 }
523
Gilles Peskine449bd832023-01-11 14:50:10 +0100524 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000525
Gilles Peskine449bd832023-01-11 14:50:10 +0100526 if (radix == 16) {
Dave Rodgman68ef1d62023-05-18 20:49:03 +0100527 if (slen > SIZE_MAX >> 2) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000529 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
Gilles Peskine449bd832023-01-11 14:50:10 +0100531 n = BITS_TO_LIMBS(slen << 2);
532
533 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
534 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
535
536 for (i = slen, j = 0; i > 0; i--, j++) {
537 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
538 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
539 }
540 } else {
541 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
542
543 for (i = 0; i < slen; i++) {
544 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
545 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
546 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000547 }
548 }
549
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200551 X->s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100552 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200553
Paul Bakker5121ce52009-01-03 21:22:43 +0000554cleanup:
555
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
Gilles Peskine449bd832023-01-11 14:50:10 +0100558 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000559}
560
561/*
Ron Eldora16fa292018-11-20 14:07:01 +0200562 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000563 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100564static int mpi_write_hlp(mbedtls_mpi *X, int radix,
565 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000566{
Janos Follath24eed8d2019-11-22 13:21:35 +0000567 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200569 size_t length = 0;
570 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000571
Gilles Peskine449bd832023-01-11 14:50:10 +0100572 do {
573 if (length >= buflen) {
574 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200575 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000576
Gilles Peskine449bd832023-01-11 14:50:10 +0100577 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
578 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200579 /*
580 * Write the residue in the current position, as an ASCII character.
581 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 if (r < 0xA) {
583 *(--p_end) = (char) ('0' + r);
584 } else {
585 *(--p_end) = (char) ('A' + (r - 0xA));
586 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
Ron Eldora16fa292018-11-20 14:07:01 +0200588 length++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000590
Gilles Peskine449bd832023-01-11 14:50:10 +0100591 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200592 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000593
594cleanup:
595
Gilles Peskine449bd832023-01-11 14:50:10 +0100596 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000597}
598
599/*
600 * Export into an ASCII string
601 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100602int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
603 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000604{
Paul Bakker23986e52011-04-24 08:57:21 +0000605 int ret = 0;
606 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000607 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100609 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
Gilles Peskine449bd832023-01-11 14:50:10 +0100611 if (radix < 2 || radix > 16) {
612 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
613 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
616 if (radix >= 4) {
617 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000618 * `n`. If radix > 4, this might be a strict
619 * overapproximation of the number of
620 * radix-adic digits needed to present `n`. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100621 }
622 if (radix >= 16) {
623 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000624 * present `n`. */
625
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 }
Janos Follath80470622019-03-06 13:43:02 +0000627 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000628 n += 1; /* Compensate for the divisions above, which round down `n`
629 * in case it's not even. */
630 n += 1; /* Potential '-'-sign. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100631 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000632 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000633
Gilles Peskine449bd832023-01-11 14:50:10 +0100634 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100635 *olen = n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100636 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000637 }
638
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100639 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100640 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
Gilles Peskine449bd832023-01-11 14:50:10 +0100642 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000644 buflen--;
645 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
Gilles Peskine449bd832023-01-11 14:50:10 +0100647 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000648 int c;
649 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
Gilles Peskine449bd832023-01-11 14:50:10 +0100651 for (i = X->n, k = 0; i > 0; i--) {
652 for (j = ciL; j > 0; j--) {
653 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000654
Gilles Peskine449bd832023-01-11 14:50:10 +0100655 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000656 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100657 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000659 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000660 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000661 k = 1;
662 }
663 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100664 } else {
665 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000666
Gilles Peskine449bd832023-01-11 14:50:10 +0100667 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000668 T.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100669 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000670
Gilles Peskine449bd832023-01-11 14:50:10 +0100671 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000672 }
673
674 *p++ = '\0';
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000675 *olen = (size_t) (p - buf);
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
677cleanup:
678
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
Gilles Peskine449bd832023-01-11 14:50:10 +0100681 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000682}
683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000685/*
686 * Read X from an opened file
687 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100688int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000689{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000691 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000692 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000693 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000694 * Buffer should have space for (short) label and decimal formatted MPI,
695 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000696 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
Gilles Peskine449bd832023-01-11 14:50:10 +0100699 if (radix < 2 || radix > 16) {
700 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
701 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000702
Gilles Peskine449bd832023-01-11 14:50:10 +0100703 memset(s, 0, sizeof(s));
704 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
705 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
706 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 slen = strlen(s);
709 if (slen == sizeof(s) - 2) {
710 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
711 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000712
Gilles Peskine449bd832023-01-11 14:50:10 +0100713 if (slen > 0 && s[slen - 1] == '\n') {
714 slen--; s[slen] = '\0';
715 }
716 if (slen > 0 && s[slen - 1] == '\r') {
717 slen--; s[slen] = '\0';
718 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
720 p = s + slen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100721 while (p-- > s) {
722 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000723 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100724 }
725 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000726
Gilles Peskine449bd832023-01-11 14:50:10 +0100727 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000728}
729
730/*
731 * Write X into an opened file (or stdout if fout == NULL)
732 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100733int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000734{
Janos Follath24eed8d2019-11-22 13:21:35 +0000735 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000736 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000737 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000738 * Buffer should have space for (short) label and decimal formatted MPI,
739 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000740 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100741 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Hanno Becker73d7d792018-12-11 10:35:51 +0000742
Gilles Peskine449bd832023-01-11 14:50:10 +0100743 if (radix < 2 || radix > 16) {
744 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
745 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000746
Gilles Peskine449bd832023-01-11 14:50:10 +0100747 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000748
Gilles Peskine449bd832023-01-11 14:50:10 +0100749 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000750
Gilles Peskine449bd832023-01-11 14:50:10 +0100751 if (p == NULL) {
752 p = "";
753 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
Gilles Peskine449bd832023-01-11 14:50:10 +0100755 plen = strlen(p);
756 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000757 s[slen++] = '\r';
758 s[slen++] = '\n';
759
Gilles Peskine449bd832023-01-11 14:50:10 +0100760 if (fout != NULL) {
761 if (fwrite(p, 1, plen, fout) != plen ||
762 fwrite(s, 1, slen, fout) != slen) {
763 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
764 }
765 } else {
766 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000767 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000768
769cleanup:
770
Gilles Peskine449bd832023-01-11 14:50:10 +0100771 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000772}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
775/*
Janos Follatha778a942019-02-13 10:28:28 +0000776 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100777 *
778 * This function is guaranteed to return an MPI with exactly the necessary
779 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000780 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100781int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
782 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000783{
Janos Follath24eed8d2019-11-22 13:21:35 +0000784 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100785 const size_t limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000786
787 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100788 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000789
Gilles Peskine449bd832023-01-11 14:50:10 +0100790 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Janos Follatha778a942019-02-13 10:28:28 +0000791
792cleanup:
793
Janos Follath171a7ef2019-02-15 16:17:45 +0000794 /*
795 * This function is also used to import keys. However, wiping the buffers
796 * upon failure is not necessary because failure only can happen before any
797 * input is copied.
798 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100799 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000800}
801
802/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000803 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100804 *
805 * This function is guaranteed to return an MPI with exactly the necessary
806 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000807 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100808int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
Janos Follath24eed8d2019-11-22 13:21:35 +0000810 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100811 const size_t limbs = CHARS_TO_LIMBS(buflen);
Gilles Peskine449bd832023-01-11 14:50:10 +0100812 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000813
Hanno Becker073c1992017-10-17 15:17:27 +0100814 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100815 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000816
Gilles Peskine449bd832023-01-11 14:50:10 +0100817 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000818
819cleanup:
820
Janos Follath171a7ef2019-02-15 16:17:45 +0000821 /*
822 * This function is also used to import keys. However, wiping the buffers
823 * upon failure is not necessary because failure only can happen before any
824 * input is copied.
825 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100826 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000827}
828
829/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000830 * Export X into unsigned binary data, little endian
831 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100832int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
833 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000834{
Gilles Peskine449bd832023-01-11 14:50:10 +0100835 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Janos Follathe344d0f2019-02-19 16:17:40 +0000836}
837
838/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 * Export X into unsigned binary data, big endian
840 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100841int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
842 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000843{
Gilles Peskine449bd832023-01-11 14:50:10 +0100844 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000845}
846
847/*
848 * Left-shift: X <<= count
849 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100850int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000851{
Janos Follath24eed8d2019-11-22 13:21:35 +0000852 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Minos Galanakis0144b352023-05-02 14:02:32 +0100853 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000854
Gilles Peskine449bd832023-01-11 14:50:10 +0100855 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000856
Gilles Peskine449bd832023-01-11 14:50:10 +0100857 if (X->n * biL < i) {
858 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
859 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000860
861 ret = 0;
862
Minos Galanakis0144b352023-05-02 14:02:32 +0100863 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Paul Bakker5121ce52009-01-03 21:22:43 +0000864cleanup:
865
Gilles Peskine449bd832023-01-11 14:50:10 +0100866 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000867}
868
869/*
870 * Right-shift: X >>= count
871 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100872int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000873{
Gilles Peskine449bd832023-01-11 14:50:10 +0100874 if (X->n != 0) {
875 mbedtls_mpi_core_shift_r(X->p, X->n, count);
876 }
877 return 0;
Gilles Peskine66414202022-09-21 15:36:16 +0200878}
879
Paul Bakker5121ce52009-01-03 21:22:43 +0000880/*
881 * Compare unsigned values
882 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100883int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000884{
Paul Bakker23986e52011-04-24 08:57:21 +0000885 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000886
Gilles Peskine449bd832023-01-11 14:50:10 +0100887 for (i = X->n; i > 0; i--) {
888 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000889 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100890 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000891 }
892
Gilles Peskine449bd832023-01-11 14:50:10 +0100893 for (j = Y->n; j > 0; j--) {
894 if (Y->p[j - 1] != 0) {
895 break;
896 }
897 }
898
Dave Rodgmanebcd7852023-08-09 18:56:42 +0100899 /* If i == j == 0, i.e. abs(X) == abs(Y),
900 * we end up returning 0 at the end of the function. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100901
902 if (i > j) {
903 return 1;
904 }
905 if (j > i) {
906 return -1;
907 }
908
909 for (; i > 0; i--) {
910 if (X->p[i - 1] > Y->p[i - 1]) {
911 return 1;
912 }
913 if (X->p[i - 1] < Y->p[i - 1]) {
914 return -1;
915 }
916 }
917
918 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000919}
920
921/*
922 * Compare signed values
923 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100924int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000925{
Paul Bakker23986e52011-04-24 08:57:21 +0000926 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000927
Gilles Peskine449bd832023-01-11 14:50:10 +0100928 for (i = X->n; i > 0; i--) {
929 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000930 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100931 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000932 }
933
Gilles Peskine449bd832023-01-11 14:50:10 +0100934 for (j = Y->n; j > 0; j--) {
935 if (Y->p[j - 1] != 0) {
936 break;
937 }
938 }
939
940 if (i == 0 && j == 0) {
941 return 0;
942 }
943
944 if (i > j) {
945 return X->s;
946 }
947 if (j > i) {
948 return -Y->s;
949 }
950
951 if (X->s > 0 && Y->s < 0) {
952 return 1;
953 }
954 if (Y->s > 0 && X->s < 0) {
955 return -1;
956 }
957
958 for (; i > 0; i--) {
959 if (X->p[i - 1] > Y->p[i - 1]) {
960 return X->s;
961 }
962 if (X->p[i - 1] < Y->p[i - 1]) {
963 return -X->s;
964 }
965 }
966
967 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000968}
969
Janos Follathee6abce2019-09-05 14:47:19 +0100970/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000971 * Compare signed values
972 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100973int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000974{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975 mbedtls_mpi Y;
976 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000977
Gilles Peskine449bd832023-01-11 14:50:10 +0100978 *p = mpi_sint_abs(z);
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100979 Y.s = TO_SIGN(z);
Paul Bakker5121ce52009-01-03 21:22:43 +0000980 Y.n = 1;
981 Y.p = p;
982
Gilles Peskine449bd832023-01-11 14:50:10 +0100983 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +0000984}
985
986/*
987 * Unsigned addition: X = |A| + |B| (HAC 14.7)
988 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100989int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +0000990{
Janos Follath24eed8d2019-11-22 13:21:35 +0000991 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100992 size_t j;
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +0100993 mbedtls_mpi_uint *p;
994 mbedtls_mpi_uint c;
Paul Bakker5121ce52009-01-03 21:22:43 +0000995
Gilles Peskine449bd832023-01-11 14:50:10 +0100996 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000998 }
999
Gilles Peskine449bd832023-01-11 14:50:10 +01001000 if (X != A) {
1001 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1002 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001003
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001004 /*
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001005 * X must always be positive as a result of unsigned additions.
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001006 */
1007 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001008
Gilles Peskine449bd832023-01-11 14:50:10 +01001009 for (j = B->n; j > 0; j--) {
1010 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001011 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001012 }
1013 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001014
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001015 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1016 * and B is 0 (of any size). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001017 if (j == 0) {
1018 return 0;
1019 }
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001020
Gilles Peskine449bd832023-01-11 14:50:10 +01001021 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001022
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001023 /* j is the number of non-zero limbs of B. Add those to X. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001024
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +01001025 p = X->p;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001026
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +01001027 c = mbedtls_mpi_core_add(p, p, B->p, j);
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001028
1029 p += j;
1030
1031 /* Now propagate any carry */
Paul Bakker5121ce52009-01-03 21:22:43 +00001032
Gilles Peskine449bd832023-01-11 14:50:10 +01001033 while (c != 0) {
1034 if (j >= X->n) {
1035 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001036 p = X->p + j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001037 }
1038
Gilles Peskine449bd832023-01-11 14:50:10 +01001039 *p += c; c = (*p < c); j++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001040 }
1041
1042cleanup:
1043
Gilles Peskine449bd832023-01-11 14:50:10 +01001044 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001045}
1046
Paul Bakker5121ce52009-01-03 21:22:43 +00001047/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001048 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001050int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001051{
Janos Follath24eed8d2019-11-22 13:21:35 +00001052 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001053 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001054 mbedtls_mpi_uint carry;
Paul Bakker5121ce52009-01-03 21:22:43 +00001055
Gilles Peskine449bd832023-01-11 14:50:10 +01001056 for (n = B->n; n > 0; n--) {
1057 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001059 }
1060 }
1061 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001062 /* B >= (2^ciL)^n > A */
1063 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1064 goto cleanup;
1065 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001066
Gilles Peskine449bd832023-01-11 14:50:10 +01001067 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001068
1069 /* Set the high limbs of X to match A. Don't touch the lower limbs
1070 * because X might be aliased to B, and we must not overwrite the
1071 * significant digits of B. */
Aaron M. Uckoaf67d2c2023-01-17 11:52:22 -05001072 if (A->n > n && A != X) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001073 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1074 }
1075 if (X->n > A->n) {
1076 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1077 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001078
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1080 if (carry != 0) {
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001081 /* Propagate the carry through the rest of X. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001082 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001083
1084 /* If we have further carry/borrow, the result is negative. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001085 if (carry != 0) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001086 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1087 goto cleanup;
1088 }
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001089 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001090
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001091 /* X should always be positive as a result of unsigned subtractions. */
1092 X->s = 1;
1093
Paul Bakker5121ce52009-01-03 21:22:43 +00001094cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001095 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001096}
1097
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001098/* Common function for signed addition and subtraction.
1099 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001101static int add_sub_mpi(mbedtls_mpi *X,
1102 const mbedtls_mpi *A, const mbedtls_mpi *B,
1103 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001104{
Hanno Becker73d7d792018-12-11 10:35:51 +00001105 int ret, s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001106
Hanno Becker73d7d792018-12-11 10:35:51 +00001107 s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 if (A->s * B->s * flip_B < 0) {
1109 int cmp = mbedtls_mpi_cmp_abs(A, B);
1110 if (cmp >= 0) {
1111 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001112 /* If |A| = |B|, the result is 0 and we must set the sign bit
1113 * to +1 regardless of which of A or B was negative. Otherwise,
1114 * since |A| > |B|, the sign is the sign of A. */
1115 X->s = cmp == 0 ? 1 : s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001116 } else {
1117 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001118 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001119 X->s = -s;
1120 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001121 } else {
1122 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001123 X->s = s;
1124 }
1125
1126cleanup:
1127
Gilles Peskine449bd832023-01-11 14:50:10 +01001128 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001129}
1130
1131/*
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001132 * Signed addition: X = A + B
1133 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001134int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001135{
Gilles Peskine449bd832023-01-11 14:50:10 +01001136 return add_sub_mpi(X, A, B, 1);
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001137}
1138
1139/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001140 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001141 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001142int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001143{
Gilles Peskine449bd832023-01-11 14:50:10 +01001144 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001145}
1146
1147/*
1148 * Signed addition: X = A + b
1149 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001150int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001151{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001152 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001153 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001154
Gilles Peskine449bd832023-01-11 14:50:10 +01001155 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001156 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001157 B.n = 1;
1158 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001159
Gilles Peskine449bd832023-01-11 14:50:10 +01001160 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001161}
1162
1163/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001164 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001165 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001166int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001167{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001168 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001170
Gilles Peskine449bd832023-01-11 14:50:10 +01001171 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001172 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001173 B.n = 1;
1174 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001175
Gilles Peskine449bd832023-01-11 14:50:10 +01001176 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001177}
1178
Paul Bakker5121ce52009-01-03 21:22:43 +00001179/*
1180 * Baseline multiplication: X = A * B (HAC 14.12)
1181 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001182int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001183{
Janos Follath24eed8d2019-11-22 13:21:35 +00001184 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001185 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001186 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001187 int result_is_zero = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001188
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001189 mbedtls_mpi_init(&TA);
1190 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001191
Gilles Peskine449bd832023-01-11 14:50:10 +01001192 if (X == A) {
1193 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1194 }
1195 if (X == B) {
1196 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1197 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Gilles Peskine449bd832023-01-11 14:50:10 +01001199 for (i = A->n; i > 0; i--) {
1200 if (A->p[i - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001201 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001202 }
1203 }
1204 if (i == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001205 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001206 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001207
Gilles Peskine449bd832023-01-11 14:50:10 +01001208 for (j = B->n; j > 0; j--) {
1209 if (B->p[j - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001210 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001211 }
1212 }
1213 if (j == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001214 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001215 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001216
Gilles Peskine449bd832023-01-11 14:50:10 +01001217 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1218 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001219
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001220 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Paul Bakker5121ce52009-01-03 21:22:43 +00001221
Hanno Beckerda763de2022-04-13 06:50:02 +01001222 /* If the result is 0, we don't shortcut the operation, which reduces
1223 * but does not eliminate side channels leaking the zero-ness. We do
1224 * need to take care to set the sign bit properly since the library does
1225 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001226 if (result_is_zero) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001227 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001228 } else {
Hanno Beckerda763de2022-04-13 06:50:02 +01001229 X->s = A->s * B->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001230 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001231
1232cleanup:
1233
Gilles Peskine449bd832023-01-11 14:50:10 +01001234 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001235
Gilles Peskine449bd832023-01-11 14:50:10 +01001236 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001237}
1238
1239/*
1240 * Baseline multiplication: X = A * b
1241 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001242int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001243{
Hanno Becker35771312022-04-14 11:52:11 +01001244 size_t n = A->n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001245 while (n > 0 && A->p[n - 1] == 0) {
Hanno Becker35771312022-04-14 11:52:11 +01001246 --n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001247 }
Hanno Becker35771312022-04-14 11:52:11 +01001248
Hanno Becker74a11a32022-04-06 06:27:00 +01001249 /* The general method below doesn't work if b==0. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001250 if (b == 0 || n == 0) {
1251 return mbedtls_mpi_lset(X, 0);
1252 }
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001253
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001254 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001255 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001256 /* In general, A * b requires 1 limb more than b. If
1257 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1258 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001259 * copy() will take care of the growth if needed. However, experimentally,
1260 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001261 * calls to calloc() in ECP code, presumably because it reuses the
1262 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001263 * grow to its final size.
1264 *
1265 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1266 * A,X can be the same. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001267 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1268 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1269 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001270
1271cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001272 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001273}
1274
1275/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001276 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1277 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001278 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001279static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1280 mbedtls_mpi_uint u0,
1281 mbedtls_mpi_uint d,
1282 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001283{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001284#if defined(MBEDTLS_HAVE_UDBL)
1285 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001286#else
Simon Butcher9803d072016-01-03 00:24:34 +00001287 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001288 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001289 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1290 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001291 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001292#endif
1293
Simon Butcher15b15d12015-11-26 19:35:03 +00001294 /*
1295 * Check for overflow
1296 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001297 if (0 == d || u1 >= d) {
1298 if (r != NULL) {
1299 *r = ~(mbedtls_mpi_uint) 0u;
1300 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001301
Gilles Peskine449bd832023-01-11 14:50:10 +01001302 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001303 }
1304
1305#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001306 dividend = (mbedtls_t_udbl) u1 << biL;
1307 dividend |= (mbedtls_t_udbl) u0;
1308 quotient = dividend / d;
Gilles Peskine449bd832023-01-11 14:50:10 +01001309 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1310 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1311 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001312
Gilles Peskine449bd832023-01-11 14:50:10 +01001313 if (r != NULL) {
1314 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1315 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001316
1317 return (mbedtls_mpi_uint) quotient;
1318#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001319
1320 /*
1321 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1322 * Vol. 2 - Seminumerical Algorithms, Knuth
1323 */
1324
1325 /*
1326 * Normalize the divisor, d, and dividend, u0, u1
1327 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001328 s = mbedtls_mpi_core_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001329 d = d << s;
1330
1331 u1 = u1 << s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001332 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001333 u0 = u0 << s;
1334
1335 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001336 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001337
1338 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001339 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001340
1341 /*
1342 * Find the first quotient and remainder
1343 */
1344 q1 = u1 / d1;
1345 r0 = u1 - d1 * q1;
1346
Gilles Peskine449bd832023-01-11 14:50:10 +01001347 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001348 q1 -= 1;
1349 r0 += d1;
1350
Gilles Peskine449bd832023-01-11 14:50:10 +01001351 if (r0 >= radix) {
1352 break;
1353 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001354 }
1355
Gilles Peskine449bd832023-01-11 14:50:10 +01001356 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001357 q0 = rAX / d1;
1358 r0 = rAX - q0 * d1;
1359
Gilles Peskine449bd832023-01-11 14:50:10 +01001360 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001361 q0 -= 1;
1362 r0 += d1;
1363
Gilles Peskine449bd832023-01-11 14:50:10 +01001364 if (r0 >= radix) {
1365 break;
1366 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001367 }
1368
Gilles Peskine449bd832023-01-11 14:50:10 +01001369 if (r != NULL) {
1370 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1371 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001372
1373 quotient = q1 * radix + q0;
1374
1375 return quotient;
1376#endif
1377}
1378
1379/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001381 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001382int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1383 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001384{
Janos Follath24eed8d2019-11-22 13:21:35 +00001385 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001386 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001388 mbedtls_mpi_uint TP2[3];
Paul Bakker5121ce52009-01-03 21:22:43 +00001389
Gilles Peskine449bd832023-01-11 14:50:10 +01001390 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1391 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1392 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001393
Gilles Peskine449bd832023-01-11 14:50:10 +01001394 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1395 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001396 /*
1397 * Avoid dynamic memory allocations for constant-size T2.
1398 *
1399 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1400 * so nobody increase the size of the MPI and we're safe to use an on-stack
1401 * buffer.
1402 */
Alexander K35d6d462019-10-31 14:46:45 +03001403 T2.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001404 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001405 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001406
Gilles Peskine449bd832023-01-11 14:50:10 +01001407 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1408 if (Q != NULL) {
1409 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1410 }
1411 if (R != NULL) {
1412 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1413 }
1414 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001415 }
1416
Gilles Peskine449bd832023-01-11 14:50:10 +01001417 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1418 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001419 X.s = Y.s = 1;
1420
Gilles Peskine449bd832023-01-11 14:50:10 +01001421 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1422 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1423 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001424
Gilles Peskine449bd832023-01-11 14:50:10 +01001425 k = mbedtls_mpi_bitlen(&Y) % biL;
1426 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 k = biL - 1 - k;
Gilles Peskine449bd832023-01-11 14:50:10 +01001428 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1429 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1430 } else {
1431 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001432 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001433
1434 n = X.n - 1;
1435 t = Y.n - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001436 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001437
Gilles Peskine449bd832023-01-11 14:50:10 +01001438 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 Z.p[n - t]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001440 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001441 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001442 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001443
Gilles Peskine449bd832023-01-11 14:50:10 +01001444 for (i = n; i > t; i--) {
1445 if (X.p[i] >= Y.p[t]) {
1446 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1447 } else {
1448 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1449 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001450 }
1451
Gilles Peskine449bd832023-01-11 14:50:10 +01001452 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1453 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001454 T2.p[2] = X.p[i];
1455
Paul Bakker5121ce52009-01-03 21:22:43 +00001456 Z.p[i - t - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001457 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001458 Z.p[i - t - 1]--;
1459
Gilles Peskine449bd832023-01-11 14:50:10 +01001460 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1461 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001462 T1.p[1] = Y.p[t];
Gilles Peskine449bd832023-01-11 14:50:10 +01001463 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1464 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001465
Gilles Peskine449bd832023-01-11 14:50:10 +01001466 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1467 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1468 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001469
Gilles Peskine449bd832023-01-11 14:50:10 +01001470 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1471 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1472 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1473 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001474 Z.p[i - t - 1]--;
1475 }
1476 }
1477
Gilles Peskine449bd832023-01-11 14:50:10 +01001478 if (Q != NULL) {
1479 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001480 Q->s = A->s * B->s;
1481 }
1482
Gilles Peskine449bd832023-01-11 14:50:10 +01001483 if (R != NULL) {
1484 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001485 X.s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001486 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
Gilles Peskine449bd832023-01-11 14:50:10 +01001488 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001489 R->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001490 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001491 }
1492
1493cleanup:
1494
Gilles Peskine449bd832023-01-11 14:50:10 +01001495 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1496 mbedtls_mpi_free(&T1);
1497 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001498
Gilles Peskine449bd832023-01-11 14:50:10 +01001499 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001500}
1501
1502/*
1503 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001505int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1506 const mbedtls_mpi *A,
1507 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001508{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001509 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510 mbedtls_mpi_uint p[1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001511
Gilles Peskine449bd832023-01-11 14:50:10 +01001512 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001513 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001514 B.n = 1;
1515 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
Gilles Peskine449bd832023-01-11 14:50:10 +01001517 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001518}
1519
1520/*
1521 * Modulo: R = A mod B
1522 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001523int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001524{
Janos Follath24eed8d2019-11-22 13:21:35 +00001525 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
Gilles Peskine449bd832023-01-11 14:50:10 +01001527 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1528 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1529 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001530
Gilles Peskine449bd832023-01-11 14:50:10 +01001531 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
Gilles Peskine449bd832023-01-11 14:50:10 +01001533 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1534 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1535 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001536
Gilles Peskine449bd832023-01-11 14:50:10 +01001537 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1538 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1539 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
1541cleanup:
1542
Gilles Peskine449bd832023-01-11 14:50:10 +01001543 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001544}
1545
1546/*
1547 * Modulo: r = A mod b
1548 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001549int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001550{
Paul Bakker23986e52011-04-24 08:57:21 +00001551 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 mbedtls_mpi_uint x, y, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
Gilles Peskine449bd832023-01-11 14:50:10 +01001554 if (b == 0) {
1555 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1556 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001557
Gilles Peskine449bd832023-01-11 14:50:10 +01001558 if (b < 0) {
1559 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1560 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001561
1562 /*
1563 * handle trivial cases
1564 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001565 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001566 *r = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001567 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001568 }
1569
Gilles Peskine449bd832023-01-11 14:50:10 +01001570 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001571 *r = A->p[0] & 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001572 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001573 }
1574
1575 /*
1576 * general case
1577 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001578 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001579 x = A->p[i - 1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001580 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001581 z = y / b;
1582 y -= z * b;
1583
1584 x <<= biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001585 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001586 z = y / b;
1587 y -= z * b;
1588 }
1589
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001590 /*
1591 * If A is negative, then the current y represents a negative value.
1592 * Flipping it to the positive side.
1593 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001594 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001595 y = b - y;
Gilles Peskine449bd832023-01-11 14:50:10 +01001596 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001597
Paul Bakker5121ce52009-01-03 21:22:43 +00001598 *r = y;
1599
Gilles Peskine449bd832023-01-11 14:50:10 +01001600 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001601}
1602
Gilles Peskine449bd832023-01-11 14:50:10 +01001603static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001604{
Gilles Peskine449bd832023-01-11 14:50:10 +01001605 *mm = mbedtls_mpi_core_montmul_init(N->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001606}
1607
Tom Cosgrove93842842022-08-05 16:59:43 +01001608/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1609 *
1610 * \param[in,out] A One of the numbers to multiply.
1611 * It must have at least as many limbs as N
1612 * (A->n >= N->n), and any limbs beyond n are ignored.
1613 * On successful completion, A contains the result of
1614 * the multiplication A * B * R^-1 mod N where
1615 * R = (2^ciL)^n.
1616 * \param[in] B One of the numbers to multiply.
1617 * It must be nonzero and must not have more limbs than N
1618 * (B->n <= N->n).
Tom Cosgrove40d22942022-08-17 06:42:44 +01001619 * \param[in] N The modulus. \p N must be odd.
Tom Cosgrove93842842022-08-05 16:59:43 +01001620 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1621 * This is -N^-1 mod 2^ciL.
1622 * \param[in,out] T A bignum for temporary storage.
1623 * It must be at least twice the limb size of N plus 1
1624 * (T->n >= 2 * N->n + 1).
1625 * Its initial content is unused and
1626 * its final content is indeterminate.
Tom Cosgrove5dd97e62022-08-30 14:31:49 +01001627 * It does not get reallocated.
Tom Cosgrove93842842022-08-05 16:59:43 +01001628 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001629static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1630 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1631 mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001632{
Gilles Peskine449bd832023-01-11 14:50:10 +01001633 mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001634}
1635
1636/*
1637 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001638 *
Tom Cosgrove93842842022-08-05 16:59:43 +01001639 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001641static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1642 mbedtls_mpi_uint mm, mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001643{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 mbedtls_mpi_uint z = 1;
1645 mbedtls_mpi U;
Gilles Peskine053022f2023-06-29 19:26:48 +02001646 U.n = 1;
1647 U.s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 U.p = &z;
1649
Gilles Peskine449bd832023-01-11 14:50:10 +01001650 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001651}
1652
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001653/**
1654 * Select an MPI from a table without leaking the index.
1655 *
1656 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1657 * reads the entire table in order to avoid leaking the value of idx to an
1658 * attacker able to observe memory access patterns.
1659 *
1660 * \param[out] R Where to write the selected MPI.
1661 * \param[in] T The table to read from.
1662 * \param[in] T_size The number of elements in the table.
1663 * \param[in] idx The index of the element to select;
1664 * this must satisfy 0 <= idx < T_size.
1665 *
1666 * \return \c 0 on success, or a negative error code.
1667 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001668static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001669{
1670 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1671
Gilles Peskine449bd832023-01-11 14:50:10 +01001672 for (size_t i = 0; i < T_size; i++) {
1673 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
Dave Rodgmanb7825ce2023-08-10 11:58:18 +01001674 (unsigned char) mbedtls_ct_uint_eq(i, idx)));
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001675 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001676cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001677 return ret;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001678}
1679
Paul Bakker5121ce52009-01-03 21:22:43 +00001680/*
1681 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1682 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001683int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1684 const mbedtls_mpi *E, const mbedtls_mpi *N,
1685 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00001686{
Janos Follath24eed8d2019-11-22 13:21:35 +00001687 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath74601202022-11-21 15:54:20 +00001688 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00001689 size_t i, j, nblimbs;
1690 size_t bufsize, nbits;
Paul Elliott1748de12023-02-13 15:35:35 +00001691 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine449bd832023-01-11 14:50:10 +01001693 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001694 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001695
Gilles Peskine449bd832023-01-11 14:50:10 +01001696 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1697 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1698 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
Gilles Peskine449bd832023-01-11 14:50:10 +01001700 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1701 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1702 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00001703
Gilles Peskine449bd832023-01-11 14:50:10 +01001704 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1705 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1706 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1707 }
Chris Jones9246d042020-11-25 15:12:39 +00001708
Paul Bakkerf6198c12012-05-16 08:02:29 +00001709 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001710 * Init temps and window size
1711 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001712 mpi_montg_init(&mm, N);
1713 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
1714 mbedtls_mpi_init(&Apos);
1715 mbedtls_mpi_init(&WW);
1716 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00001717
Gilles Peskine449bd832023-01-11 14:50:10 +01001718 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
Gilles Peskine449bd832023-01-11 14:50:10 +01001720 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1721 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001722
Gilles Peskine449bd832023-01-11 14:50:10 +01001723#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
1724 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath7fa11b82022-11-21 14:48:02 +00001725 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +01001726 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001727#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001728
Janos Follathc8d66d52022-11-22 10:47:10 +00001729 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath06000952022-11-22 10:18:06 +00001730
Paul Bakker5121ce52009-01-03 21:22:43 +00001731 /*
Janos Follathbe54ca72022-11-21 16:14:54 +00001732 * This function is not constant-trace: its memory accesses depend on the
1733 * exponent value. To defend against timing attacks, callers (such as RSA
1734 * and DHM) should use exponent blinding. However this is not enough if the
1735 * adversary can find the exponent in a single trace, so this function
1736 * takes extra precautions against adversaries who can observe memory
1737 * access patterns.
Janos Follathf08b40e2022-11-11 15:56:38 +00001738 *
Janos Follathbe54ca72022-11-21 16:14:54 +00001739 * This function performs a series of multiplications by table elements and
1740 * squarings, and we want the prevent the adversary from finding out which
1741 * table element was used, and from distinguishing between multiplications
1742 * and squarings. Firstly, when multiplying by an element of the window
1743 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
1744 * squarings as having a different memory access patterns from other
Gilles Peskinee6cb45e2023-08-10 15:59:28 +02001745 * multiplications. So secondly, we put the accumulator in the table as
1746 * well, and also do a constant-trace table lookup to multiply by the
1747 * accumulator which is W[x_index].
Janos Follathbe54ca72022-11-21 16:14:54 +00001748 *
1749 * This way, all multiplications take the form of a lookup-and-multiply.
1750 * The number of lookup-and-multiply operations inside each iteration of
1751 * the main loop still depends on the bits of the exponent, but since the
1752 * other operations in the loop don't have an easily recognizable memory
1753 * trace, an adversary is unlikely to be able to observe the exact
1754 * patterns.
1755 *
1756 * An adversary may still be able to recover the exponent if they can
1757 * observe both memory accesses and branches. However, branch prediction
1758 * exploitation typically requires many traces of execution over the same
1759 * data, which is defeated by randomized blinding.
Janos Follath8e7d6a02022-10-04 13:27:40 +01001760 */
Janos Follathc8d66d52022-11-22 10:47:10 +00001761 const size_t x_index = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001762 mbedtls_mpi_init(&W[x_index]);
Janos Follath84461482022-11-21 14:31:22 +00001763
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 j = N->n + 1;
Gilles Peskinee6cb45e2023-08-10 15:59:28 +02001765 /* All W[i] including the accumulator must have at least N->n limbs for
1766 * the mpi_montmul() and mpi_montred() calls later. Here we ensure that
1767 * W[1] and the accumulator W[x_index] are large enough. later we'll grow
1768 * other W[i] to the same length. They must not be shrunk midway through
1769 * this function!
Paul Bakker5121ce52009-01-03 21:22:43 +00001770 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001771 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1772 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
1773 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001774
1775 /*
Paul Bakker50546922012-05-19 08:40:49 +00001776 * Compensate for negative A (and correct at the end)
1777 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001778 neg = (A->s == -1);
1779 if (neg) {
1780 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00001781 Apos.s = 1;
1782 A = &Apos;
1783 }
1784
1785 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001786 * If 1st call, pre-compute R^2 mod N
1787 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001788 if (prec_RR == NULL || prec_RR->p == NULL) {
1789 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
1790 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
1791 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
Gilles Peskine449bd832023-01-11 14:50:10 +01001793 if (prec_RR != NULL) {
1794 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
1795 }
1796 } else {
1797 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00001798 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001799
1800 /*
1801 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1802 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001803 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1804 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001805 /* This should be a no-op because W[1] is already that large before
1806 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Tom Cosgrove93842842022-08-05 16:59:43 +01001807 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001808 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
1809 } else {
1810 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001811 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001813 /* Note that this is safe because W[1] always has at least N->n limbs
1814 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001815 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
1817 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001818 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001820 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1821 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001822
Janos Follathc8d66d52022-11-22 10:47:10 +00001823
Gilles Peskine449bd832023-01-11 14:50:10 +01001824 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 /*
Janos Follath74601202022-11-21 15:54:20 +00001826 * W[i] = W[1] ^ i
1827 *
1828 * The first bit of the sliding window is always 1 and therefore we
1829 * only need to store the second half of the table.
Janos Follathc8d66d52022-11-22 10:47:10 +00001830 *
1831 * (There are two special elements in the table: W[0] for the
1832 * accumulator/result and W[1] for A in Montgomery form. Both of these
1833 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 */
Janos Follath74601202022-11-21 15:54:20 +00001835 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
Gilles Peskine449bd832023-01-11 14:50:10 +01001837 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1838 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
Gilles Peskine449bd832023-01-11 14:50:10 +01001840 for (i = 0; i < window_bitsize - 1; i++) {
1841 mpi_montmul(&W[j], &W[j], N, mm, &T);
1842 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01001843
Paul Bakker5121ce52009-01-03 21:22:43 +00001844 /*
1845 * W[i] = W[i - 1] * W[1]
1846 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001847 for (i = j + 1; i < w_table_used_size; i++) {
1848 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1849 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001850
Gilles Peskine449bd832023-01-11 14:50:10 +01001851 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001852 }
1853 }
1854
1855 nblimbs = E->n;
1856 bufsize = 0;
1857 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 state = 0;
1859
Gilles Peskine449bd832023-01-11 14:50:10 +01001860 while (1) {
1861 if (bufsize == 0) {
1862 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001864 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001865
Paul Bakker0d7702c2013-10-29 16:18:35 +01001866 nblimbs--;
1867
Gilles Peskine449bd832023-01-11 14:50:10 +01001868 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 }
1870
1871 bufsize--;
1872
1873 ei = (E->p[nblimbs] >> bufsize) & 1;
1874
1875 /*
1876 * skip leading 0s
1877 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001878 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001879 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01001880 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
Gilles Peskine449bd832023-01-11 14:50:10 +01001882 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001883 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001884 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001886 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1887 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001888 continue;
1889 }
1890
1891 /*
1892 * add ei to current window
1893 */
1894 state = 2;
1895
1896 nbits++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001897 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
Gilles Peskine449bd832023-01-11 14:50:10 +01001899 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001900 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001901 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001903 for (i = 0; i < window_bitsize; i++) {
1904 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1905 x_index));
1906 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001907 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
1909 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001910 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001911 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001912 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1913 exponent_bits_in_window));
1914 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
1916 state--;
1917 nbits = 0;
Janos Follath7fa11b82022-11-21 14:48:02 +00001918 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001919 }
1920 }
1921
1922 /*
1923 * process the remaining bits
1924 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001925 for (i = 0; i < nbits; i++) {
1926 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1927 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
Janos Follath7fa11b82022-11-21 14:48:02 +00001929 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
Gilles Peskine449bd832023-01-11 14:50:10 +01001931 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
1932 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
1933 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001934 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 }
1936
1937 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001938 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001940 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
Gilles Peskine449bd832023-01-11 14:50:10 +01001942 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath8e7d6a02022-10-04 13:27:40 +01001943 W[x_index].s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001944 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00001945 }
1946
Janos Follath8e7d6a02022-10-04 13:27:40 +01001947 /*
1948 * Load the result in the output variable.
1949 */
Chien Wonge2caf412023-08-01 21:38:46 +08001950 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
Janos Follath8e7d6a02022-10-04 13:27:40 +01001951
Paul Bakker5121ce52009-01-03 21:22:43 +00001952cleanup:
1953
Janos Follathb2c2fca2022-11-21 15:05:31 +00001954 /* The first bit of the sliding window is always 1 and therefore the first
1955 * half of the table was unused. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001956 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
1957 mbedtls_mpi_free(&W[i]);
1958 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
Gilles Peskine449bd832023-01-11 14:50:10 +01001960 mbedtls_mpi_free(&W[x_index]);
1961 mbedtls_mpi_free(&W[1]);
1962 mbedtls_mpi_free(&T);
1963 mbedtls_mpi_free(&Apos);
1964 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00001965
Gilles Peskine449bd832023-01-11 14:50:10 +01001966 if (prec_RR == NULL || prec_RR->p == NULL) {
1967 mbedtls_mpi_free(&RR);
1968 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
Gilles Peskine449bd832023-01-11 14:50:10 +01001970 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001971}
1972
Paul Bakker5121ce52009-01-03 21:22:43 +00001973/*
1974 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1975 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001976int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001977{
Janos Follath24eed8d2019-11-22 13:21:35 +00001978 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001979 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03001980 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001981
Gilles Peskine449bd832023-01-11 14:50:10 +01001982 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
Gilles Peskine449bd832023-01-11 14:50:10 +01001984 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1985 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001986
Gilles Peskine449bd832023-01-11 14:50:10 +01001987 lz = mbedtls_mpi_lsb(&TA);
1988 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001989
Gilles Peskine27253bc2021-06-09 13:26:43 +02001990 /* The loop below gives the correct result when A==0 but not when B==0.
1991 * So have a special case for B==0. Leverage the fact that we just
1992 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1993 * slightly more efficient than cmp_int(). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001994 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1995 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02001996 goto cleanup;
1997 }
1998
Gilles Peskine449bd832023-01-11 14:50:10 +01001999 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002000 lz = lzt;
Gilles Peskine449bd832023-01-11 14:50:10 +01002001 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002002
Paul Bakker5121ce52009-01-03 21:22:43 +00002003 TA.s = TB.s = 1;
2004
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002005 /* We mostly follow the procedure described in HAC 14.54, but with some
2006 * minor differences:
2007 * - Sequences of multiplications or divisions by 2 are grouped into a
2008 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002009 * - The procedure in HAC assumes that 0 < TB <= TA.
2010 * - The condition TB <= TA is not actually necessary for correctness.
2011 * TA and TB have symmetric roles except for the loop termination
2012 * condition, and the shifts at the beginning of the loop body
2013 * remove any significance from the ordering of TA vs TB before
2014 * the shifts.
2015 * - If TA = 0, the loop goes through 0 iterations and the result is
2016 * correctly TB.
2017 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002018 *
2019 * For the correctness proof below, decompose the original values of
2020 * A and B as
2021 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2022 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2023 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2024 * and gcd(A',B') is odd or 0.
2025 *
2026 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2027 * The code maintains the following invariant:
2028 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002029 */
2030
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002031 /* Proof that the loop terminates:
2032 * At each iteration, either the right-shift by 1 is made on a nonzero
2033 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2034 * by at least 1, or the right-shift by 1 is made on zero and then
2035 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2036 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2037 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002038 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002039 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002040 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2041 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002042
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002043 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2044 * TA-TB is even so the division by 2 has an integer result.
2045 * Invariant (I) is preserved since any odd divisor of both TA and TB
2046 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08002047 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002048 * divides TA.
2049 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002050 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2051 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2052 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2053 } else {
2054 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2055 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002056 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002057 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 }
2059
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002060 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2061 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2062 * - If there was at least one loop iteration, then one of TA or TB is odd,
2063 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2064 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2065 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002066 * 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 +02002067 */
2068
Gilles Peskine449bd832023-01-11 14:50:10 +01002069 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2070 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002071
2072cleanup:
2073
Gilles Peskine449bd832023-01-11 14:50:10 +01002074 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002075
Gilles Peskine449bd832023-01-11 14:50:10 +01002076 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002077}
2078
Paul Bakker33dc46b2014-04-30 16:11:39 +02002079/*
2080 * Fill X with size bytes of random.
Gilles Peskine22cdd0c2022-10-27 20:15:13 +02002081 * The bytes returned from the RNG are used in a specific order which
2082 * is suitable for deterministic ECDSA (see the specification of
2083 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Paul Bakker33dc46b2014-04-30 16:11:39 +02002084 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002085int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2086 int (*f_rng)(void *, unsigned char *, size_t),
2087 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002088{
Janos Follath24eed8d2019-11-22 13:21:35 +00002089 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01002090 const size_t limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002091
Hanno Beckerda1655a2017-10-18 14:21:44 +01002092 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +01002093 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2094 if (size == 0) {
2095 return 0;
2096 }
Paul Bakker287781a2011-03-26 13:18:49 +00002097
Gilles Peskine449bd832023-01-11 14:50:10 +01002098 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002099
2100cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002101 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002102}
2103
Gilles Peskine449bd832023-01-11 14:50:10 +01002104int mbedtls_mpi_random(mbedtls_mpi *X,
2105 mbedtls_mpi_sint min,
2106 const mbedtls_mpi *N,
2107 int (*f_rng)(void *, unsigned char *, size_t),
2108 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002109{
Gilles Peskine449bd832023-01-11 14:50:10 +01002110 if (min < 0) {
2111 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2112 }
2113 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2114 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2115 }
Gilles Peskine1e918f42021-03-29 22:14:51 +02002116
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002117 /* Ensure that target MPI has exactly the same number of limbs
2118 * as the upper bound, even if the upper bound has leading zeros.
Gilles Peskine6b7ce962022-12-15 15:04:33 +01002119 * This is necessary for mbedtls_mpi_core_random. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002120 int ret = mbedtls_mpi_resize_clear(X, N->n);
2121 if (ret != 0) {
2122 return ret;
2123 }
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002124
Gilles Peskine449bd832023-01-11 14:50:10 +01002125 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002126}
2127
Paul Bakker5121ce52009-01-03 21:22:43 +00002128/*
2129 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2130 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002131int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002132{
Janos Follath24eed8d2019-11-22 13:21:35 +00002133 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002134 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002135
Gilles Peskine449bd832023-01-11 14:50:10 +01002136 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2137 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2138 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002139
Gilles Peskine449bd832023-01-11 14:50:10 +01002140 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2141 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2142 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
Gilles Peskine449bd832023-01-11 14:50:10 +01002144 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002145
Gilles Peskine449bd832023-01-11 14:50:10 +01002146 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002148 goto cleanup;
2149 }
2150
Gilles Peskine449bd832023-01-11 14:50:10 +01002151 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2152 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2153 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2154 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
Gilles Peskine449bd832023-01-11 14:50:10 +01002156 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2157 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2158 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2159 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
Gilles Peskine449bd832023-01-11 14:50:10 +01002161 do {
2162 while ((TU.p[0] & 1) == 0) {
2163 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002164
Gilles Peskine449bd832023-01-11 14:50:10 +01002165 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2166 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2167 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002168 }
2169
Gilles Peskine449bd832023-01-11 14:50:10 +01002170 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2171 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002172 }
2173
Gilles Peskine449bd832023-01-11 14:50:10 +01002174 while ((TV.p[0] & 1) == 0) {
2175 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002176
Gilles Peskine449bd832023-01-11 14:50:10 +01002177 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2178 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2179 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 }
2181
Gilles Peskine449bd832023-01-11 14:50:10 +01002182 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2183 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002184 }
2185
Gilles Peskine449bd832023-01-11 14:50:10 +01002186 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2187 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2188 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2189 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2190 } else {
2191 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2192 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2193 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002195 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2196
2197 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2198 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002199 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
Gilles Peskine449bd832023-01-11 14:50:10 +01002201 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2202 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2203 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
Gilles Peskine449bd832023-01-11 14:50:10 +01002205 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002206
2207cleanup:
2208
Gilles Peskine449bd832023-01-11 14:50:10 +01002209 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2210 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2211 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
Gilles Peskine449bd832023-01-11 14:50:10 +01002213 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002214}
2215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002216#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002217
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002218/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
2219static const unsigned char small_prime_gaps[] = {
2220 2, 2, 4, 2, 4, 2, 4, 6,
2221 2, 6, 4, 2, 4, 6, 6, 2,
2222 6, 4, 2, 6, 4, 6, 8, 4,
2223 2, 4, 2, 4, 14, 4, 6, 2,
2224 10, 2, 6, 6, 4, 6, 6, 2,
2225 10, 2, 4, 2, 12, 12, 4, 2,
2226 4, 6, 2, 10, 6, 6, 6, 2,
2227 6, 4, 2, 10, 14, 4, 2, 4,
2228 14, 6, 10, 2, 4, 6, 8, 6,
2229 6, 4, 6, 8, 4, 8, 10, 2,
2230 10, 2, 6, 4, 6, 8, 4, 2,
2231 4, 12, 8, 4, 8, 4, 6, 12,
2232 2, 18, 6, 10, 6, 6, 2, 6,
2233 10, 6, 6, 2, 6, 6, 4, 2,
2234 12, 10, 2, 4, 6, 6, 2, 12,
2235 4, 6, 8, 10, 8, 10, 8, 6,
2236 6, 4, 8, 6, 4, 8, 4, 14,
2237 10, 12, 2, 10, 2, 4, 2, 10,
2238 14, 4, 2, 4, 14, 4, 2, 4,
2239 20, 4, 8, 10, 8, 4, 6, 6,
2240 14, 4, 6, 6, 8, 6, /*reaches 997*/
Gilles Peskine30b03782023-08-22 11:06:47 +02002241 0 /* the last entry is effectively unused */
Paul Bakker5121ce52009-01-03 21:22:43 +00002242};
2243
2244/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002245 * Small divisors test (X must be positive)
2246 *
2247 * Return values:
2248 * 0: no small factor (possible prime, more tests needed)
2249 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002251 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002252 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002253static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002254{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002255 int ret = 0;
2256 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 mbedtls_mpi_uint r;
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002258 unsigned p = 3; /* The first odd prime */
Paul Bakker5121ce52009-01-03 21:22:43 +00002259
Gilles Peskine449bd832023-01-11 14:50:10 +01002260 if ((X->p[0] & 1) == 0) {
2261 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2262 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002264 for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2265 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
Gilles Peskine449bd832023-01-11 14:50:10 +01002266 if (r == 0) {
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002267 if (mbedtls_mpi_cmp_int(X, p) == 0) {
2268 return 1;
2269 } else {
2270 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2271 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002272 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002273 }
2274
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002275cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002276 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002277}
2278
2279/*
2280 * Miller-Rabin pseudo-primality test (HAC 4.24)
2281 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002282static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2283 int (*f_rng)(void *, unsigned char *, size_t),
2284 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002285{
Pascal Junodb99183d2015-03-11 16:49:45 +01002286 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002287 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002289
Gilles Peskine449bd832023-01-11 14:50:10 +01002290 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2291 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2292 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002293
Paul Bakker5121ce52009-01-03 21:22:43 +00002294 /*
2295 * W = |X| - 1
2296 * R = W >> lsb( W )
2297 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002298 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2299 s = mbedtls_mpi_lsb(&W);
2300 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2301 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
Gilles Peskine449bd832023-01-11 14:50:10 +01002303 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 /*
2305 * pick a random A, 1 < A < |X| - 1
2306 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002307 count = 0;
2308 do {
Gilles Peskine449bd832023-01-11 14:50:10 +01002309 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002310
Gilles Peskine449bd832023-01-11 14:50:10 +01002311 j = mbedtls_mpi_bitlen(&A);
2312 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002313 if (j > k) {
Gilles Peskine449bd832023-01-11 14:50:10 +01002314 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002315 }
2316
2317 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002318 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2319 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002320 }
2321
Gilles Peskine449bd832023-01-11 14:50:10 +01002322 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2323 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002324
2325 /*
2326 * A = A^R mod |X|
2327 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002328 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
Gilles Peskine449bd832023-01-11 14:50:10 +01002330 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2331 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01002333 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
2335 j = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002336 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002337 /*
2338 * A = A * A mod |X|
2339 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002340 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2341 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
Gilles Peskine449bd832023-01-11 14:50:10 +01002343 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002344 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01002345 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
2347 j++;
2348 }
2349
2350 /*
2351 * not prime if A != |X| - 1 or A == 1
2352 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002353 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2354 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002356 break;
2357 }
2358 }
2359
2360cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002361 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2362 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2363 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
Gilles Peskine449bd832023-01-11 14:50:10 +01002365 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002366}
2367
2368/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002369 * Pseudo-primality test: small factors, then Miller-Rabin
2370 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002371int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2372 int (*f_rng)(void *, unsigned char *, size_t),
2373 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002374{
Janos Follath24eed8d2019-11-22 13:21:35 +00002375 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_mpi XX;
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002377
2378 XX.s = 1;
2379 XX.n = X->n;
2380 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002381
Gilles Peskine449bd832023-01-11 14:50:10 +01002382 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2383 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2384 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002385 }
2386
Gilles Peskine449bd832023-01-11 14:50:10 +01002387 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2388 return 0;
2389 }
2390
2391 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2392 if (ret == 1) {
2393 return 0;
2394 }
2395
2396 return ret;
2397 }
2398
2399 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002400}
2401
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002402/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002403 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002404 *
Janos Follathf301d232018-08-14 13:34:01 +01002405 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2406 * be either 1024 bits or 1536 bits long, and flags must contain
2407 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002409int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2410 int (*f_rng)(void *, unsigned char *, size_t),
2411 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002412{
Jethro Beekman66689272018-02-14 19:24:10 -08002413#ifdef MBEDTLS_HAVE_INT64
2414// ceil(2^63.5)
2415#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2416#else
2417// ceil(2^31.5)
2418#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2419#endif
2420 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002421 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002422 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423 mbedtls_mpi_uint r;
2424 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
Gilles Peskine449bd832023-01-11 14:50:10 +01002426 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2427 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2428 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002429
Gilles Peskine449bd832023-01-11 14:50:10 +01002430 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
Gilles Peskine449bd832023-01-11 14:50:10 +01002432 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Gilles Peskine449bd832023-01-11 14:50:10 +01002434 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002435 /*
2436 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2437 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002438 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2439 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2440 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2441 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002442 /*
2443 * 2^-100 error probability, number of rounds computed based on HAC,
2444 * fact 4.48
2445 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002446 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2447 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2448 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2449 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002450 }
2451
Gilles Peskine449bd832023-01-11 14:50:10 +01002452 while (1) {
2453 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002454 /* 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 +01002455 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2456 continue;
2457 }
Jethro Beekman66689272018-02-14 19:24:10 -08002458
2459 k = n * biL;
Gilles Peskine449bd832023-01-11 14:50:10 +01002460 if (k > nbits) {
2461 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2462 }
Jethro Beekman66689272018-02-14 19:24:10 -08002463 X->p[0] |= 1;
2464
Gilles Peskine449bd832023-01-11 14:50:10 +01002465 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2466 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002467
Gilles Peskine449bd832023-01-11 14:50:10 +01002468 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002469 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002470 }
2471 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002472 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002473 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002474 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2475 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002476 */
Jethro Beekman66689272018-02-14 19:24:10 -08002477
2478 X->p[0] |= 2;
2479
Gilles Peskine449bd832023-01-11 14:50:10 +01002480 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2481 if (r == 0) {
2482 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2483 } else if (r == 1) {
2484 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2485 }
Jethro Beekman66689272018-02-14 19:24:10 -08002486
2487 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine449bd832023-01-11 14:50:10 +01002488 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2489 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002490
Gilles Peskine449bd832023-01-11 14:50:10 +01002491 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002492 /*
2493 * First, check small factors for X and Y
2494 * before doing Miller-Rabin on any of them
2495 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002496 if ((ret = mpi_check_small_factors(X)) == 0 &&
2497 (ret = mpi_check_small_factors(&Y)) == 0 &&
2498 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2499 == 0 &&
2500 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2501 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002502 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002503 }
Jethro Beekman66689272018-02-14 19:24:10 -08002504
Gilles Peskine449bd832023-01-11 14:50:10 +01002505 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002506 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002507 }
Jethro Beekman66689272018-02-14 19:24:10 -08002508
2509 /*
2510 * Next candidates. We want to preserve Y = (X-1) / 2 and
2511 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2512 * so up Y by 6 and X by 12.
2513 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002514 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2515 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002516 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002517 }
2518 }
2519
2520cleanup:
2521
Gilles Peskine449bd832023-01-11 14:50:10 +01002522 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002523
Gilles Peskine449bd832023-01-11 14:50:10 +01002524 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002525}
2526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002530
Paul Bakker23986e52011-04-24 08:57:21 +00002531#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002532
2533static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2534{
2535 { 693, 609, 21 },
2536 { 1764, 868, 28 },
2537 { 768454923, 542167814, 1 }
2538};
2539
Paul Bakker5121ce52009-01-03 21:22:43 +00002540/*
2541 * Checkup routine
2542 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002543int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00002544{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002545 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002546 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002547
Gilles Peskine449bd832023-01-11 14:50:10 +01002548 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2549 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002550
Gilles Peskine449bd832023-01-11 14:50:10 +01002551 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2552 "EFE021C2645FD1DC586E69184AF4A31E" \
2553 "D5F53E93B5F123FA41680867BA110131" \
2554 "944FE7952E2517337780CB0DB80E61AA" \
2555 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002556
Gilles Peskine449bd832023-01-11 14:50:10 +01002557 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2558 "B2E7EFD37075B9F03FF989C7C5051C20" \
2559 "34D2A323810251127E7BF8625A4F49A5" \
2560 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2561 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002562
Gilles Peskine449bd832023-01-11 14:50:10 +01002563 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2564 "0066A198186C18C10B2F5ED9B522752A" \
2565 "9830B69916E535C8F047518A889A43A5" \
2566 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002567
Gilles Peskine449bd832023-01-11 14:50:10 +01002568 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002569
Gilles Peskine449bd832023-01-11 14:50:10 +01002570 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2571 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2572 "9E857EA95A03512E2BAE7391688D264A" \
2573 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2574 "8001B72E848A38CAE1C65F78E56ABDEF" \
2575 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2576 "ECF677152EF804370C1A305CAF3B5BF1" \
2577 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002578
Gilles Peskine449bd832023-01-11 14:50:10 +01002579 if (verbose != 0) {
2580 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2581 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002582
Gilles Peskine449bd832023-01-11 14:50:10 +01002583 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2584 if (verbose != 0) {
2585 mbedtls_printf("failed\n");
2586 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002587
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002588 ret = 1;
2589 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002590 }
2591
Gilles Peskine449bd832023-01-11 14:50:10 +01002592 if (verbose != 0) {
2593 mbedtls_printf("passed\n");
2594 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002595
Gilles Peskine449bd832023-01-11 14:50:10 +01002596 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002597
Gilles Peskine449bd832023-01-11 14:50:10 +01002598 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2599 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002600
Gilles Peskine449bd832023-01-11 14:50:10 +01002601 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2602 "6613F26162223DF488E9CD48CC132C7A" \
2603 "0AC93C701B001B092E4E5B9F73BCD27B" \
2604 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002605
Gilles Peskine449bd832023-01-11 14:50:10 +01002606 if (verbose != 0) {
2607 mbedtls_printf(" MPI test #2 (div_mpi): ");
2608 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002609
Gilles Peskine449bd832023-01-11 14:50:10 +01002610 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2611 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2612 if (verbose != 0) {
2613 mbedtls_printf("failed\n");
2614 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002615
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002616 ret = 1;
2617 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002618 }
2619
Gilles Peskine449bd832023-01-11 14:50:10 +01002620 if (verbose != 0) {
2621 mbedtls_printf("passed\n");
2622 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002623
Gilles Peskine449bd832023-01-11 14:50:10 +01002624 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00002625
Gilles Peskine449bd832023-01-11 14:50:10 +01002626 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2627 "36E139AEA55215609D2816998ED020BB" \
2628 "BD96C37890F65171D948E9BC7CBAA4D9" \
2629 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002630
Gilles Peskine449bd832023-01-11 14:50:10 +01002631 if (verbose != 0) {
2632 mbedtls_printf(" MPI test #3 (exp_mod): ");
2633 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002634
Gilles Peskine449bd832023-01-11 14:50:10 +01002635 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2636 if (verbose != 0) {
2637 mbedtls_printf("failed\n");
2638 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002639
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002640 ret = 1;
2641 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002642 }
2643
Gilles Peskine449bd832023-01-11 14:50:10 +01002644 if (verbose != 0) {
2645 mbedtls_printf("passed\n");
2646 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002647
Gilles Peskine449bd832023-01-11 14:50:10 +01002648 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002649
Gilles Peskine449bd832023-01-11 14:50:10 +01002650 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2651 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2652 "C3DBA76456363A10869622EAC2DD84EC" \
2653 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002654
Gilles Peskine449bd832023-01-11 14:50:10 +01002655 if (verbose != 0) {
2656 mbedtls_printf(" MPI test #4 (inv_mod): ");
2657 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002658
Gilles Peskine449bd832023-01-11 14:50:10 +01002659 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2660 if (verbose != 0) {
2661 mbedtls_printf("failed\n");
2662 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002663
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002664 ret = 1;
2665 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002666 }
2667
Gilles Peskine449bd832023-01-11 14:50:10 +01002668 if (verbose != 0) {
2669 mbedtls_printf("passed\n");
2670 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002671
Gilles Peskine449bd832023-01-11 14:50:10 +01002672 if (verbose != 0) {
2673 mbedtls_printf(" MPI test #5 (simple gcd): ");
2674 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002675
Gilles Peskine449bd832023-01-11 14:50:10 +01002676 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2677 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2678 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002679
Gilles Peskine449bd832023-01-11 14:50:10 +01002680 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002681
Gilles Peskine449bd832023-01-11 14:50:10 +01002682 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2683 if (verbose != 0) {
2684 mbedtls_printf("failed at %d\n", i);
2685 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002686
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002687 ret = 1;
2688 goto cleanup;
2689 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002690 }
2691
Gilles Peskine449bd832023-01-11 14:50:10 +01002692 if (verbose != 0) {
2693 mbedtls_printf("passed\n");
2694 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002695
Paul Bakker5121ce52009-01-03 21:22:43 +00002696cleanup:
2697
Gilles Peskine449bd832023-01-11 14:50:10 +01002698 if (ret != 0 && verbose != 0) {
2699 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2700 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002701
Gilles Peskine449bd832023-01-11 14:50:10 +01002702 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2703 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002704
Gilles Peskine449bd832023-01-11 14:50:10 +01002705 if (verbose != 0) {
2706 mbedtls_printf("\n");
2707 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002708
Gilles Peskine449bd832023-01-11 14:50:10 +01002709 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002710}
2711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002712#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002714#endif /* MBEDTLS_BIGNUM_C */