blob: 795952ccd0fd4a0a781be206e7b60f2ffa21f8a0 [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
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
Simon Butcher15b15d12015-11-26 19:35:03 +000019
Paul Bakker5121ce52009-01-03 21:22:43 +000020/*
Simon Butcher15b15d12015-11-26 19:35:03 +000021 * The following sources were referenced in the design of this Multi-precision
22 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000023 *
Simon Butcher15b15d12015-11-26 19:35:03 +000024 * [1] Handbook of Applied Cryptography - 1997
25 * Menezes, van Oorschot and Vanstone
26 *
27 * [2] Multi-Precision Math
28 * Tom St Denis
29 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30 *
31 * [3] GNU Multi-Precision Arithmetic Library
32 * https://gmplib.org/manual/index.html
33 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000034 */
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Gilles Peskinedb09ef62020-06-03 01:43:33 +020036#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/bignum.h"
Janos Follath4614b9a2022-07-21 15:34:47 +010041#include "bignum_core.h"
Chris Jones4c5819c2021-03-03 17:45:34 +000042#include "bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050043#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000044#include "mbedtls/error.h"
Gabor Mezei22c9a6f2021-10-20 12:09:35 +020045#include "constant_time_internal.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000046
Dave Rodgman351c71b2021-12-06 17:50:53 +000047#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <string.h>
49
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000050#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020051
Gilles Peskine449bd832023-01-11 14:50:10 +010052#define MPI_VALIDATE_RET(cond) \
53 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
54#define MPI_VALIDATE(cond) \
55 MBEDTLS_INTERNAL_VALIDATE(cond)
Gabor Mezei66669142022-08-03 12:52:26 +020056
Dave Rodgman7d4f0192023-05-09 14:01:05 +010057/*
58 * Compare signed values in constant time
59 */
60int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
61 const mbedtls_mpi *Y,
62 unsigned *ret)
63{
Dave Rodgman1f39f032023-08-01 09:19:16 +010064 mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
Dave Rodgman7d4f0192023-05-09 14:01:05 +010065
66 MPI_VALIDATE_RET(X != NULL);
67 MPI_VALIDATE_RET(Y != NULL);
68 MPI_VALIDATE_RET(ret != NULL);
69
70 if (X->n != Y->n) {
71 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
72 }
73
74 /*
Dave Rodgmanb69239c2023-08-09 14:53:18 +010075 * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.
Dave Rodgman7d4f0192023-05-09 14:01:05 +010076 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
77 */
Dave Rodgman1a7a5622023-05-17 13:47:56 +010078 X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
79 Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010080
81 /*
82 * If the signs are different, then the positive operand is the bigger.
83 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
84 * is false if X is positive (X_is_negative == 0).
85 */
Dave Rodgman1cfc43c2023-09-19 16:18:59 +010086 different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
Dave Rodgman1f39f032023-08-01 09:19:16 +010087 result = mbedtls_ct_bool_and(different_sign, X_is_negative);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010088
Dave Rodgman32d72602023-07-31 12:28:05 +010089 /*
90 * Assuming signs are the same, compare X and Y. We switch the comparison
Dave Rodgman1a7a5622023-05-17 13:47:56 +010091 * order if they are negative so that we get the right result, regardles of
92 * sign.
Dave Rodgman7d4f0192023-05-09 14:01:05 +010093 */
Dave Rodgman7d4f0192023-05-09 14:01:05 +010094
Dave Rodgman32d72602023-07-31 12:28:05 +010095 /* This array is used to conditionally swap the pointers in const time */
Dave Rodgman1a7a5622023-05-17 13:47:56 +010096 void * const p[2] = { X->p, Y->p };
Dave Rodgman98ddc012023-08-10 12:11:31 +010097 size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
Dave Rodgman2c764842023-05-18 13:28:21 +010098 mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
Dave Rodgman7d4f0192023-05-09 14:01:05 +010099
Dave Rodgman32d72602023-07-31 12:28:05 +0100100 /*
Dave Rodgman1f39f032023-08-01 09:19:16 +0100101 * Store in result iff the signs are the same (i.e., iff different_sign == false). If
Dave Rodgman32d72602023-07-31 12:28:05 +0100102 * the signs differ, result has already been set, so we don't change it.
103 */
Dave Rodgman1f39f032023-08-01 09:19:16 +0100104 result = mbedtls_ct_bool_or(result,
105 mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
Dave Rodgman1a7a5622023-05-17 13:47:56 +0100106
Dave Rodgman98ddc012023-08-10 12:11:31 +0100107 *ret = mbedtls_ct_uint_if_else_0(result, 1);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100108
109 return 0;
110}
111
112/*
113 * Conditionally assign X = Y, without leaking information
114 * about whether the assignment was made or not.
115 * (Leaking information about the respective sizes of X and Y is ok however.)
116 */
Dave Rodgman0a487172023-09-15 11:52:06 +0100117#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
118 (_MSC_FULL_VER < 193131103)
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100119/*
120 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
121 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
122 */
123__declspec(noinline)
124#endif
125int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
126 const mbedtls_mpi *Y,
127 unsigned char assign)
128{
129 int ret = 0;
130 MPI_VALIDATE_RET(X != NULL);
131 MPI_VALIDATE_RET(Y != NULL);
132
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100133 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
134
Dave Rodgman7e9af052023-09-28 17:08:16 +0100135 {
136 mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
Dave Rodgman589ccb82023-05-17 13:55:01 +0100137
Dave Rodgman7e9af052023-09-28 17:08:16 +0100138 X->s = (int) mbedtls_ct_uint_if(do_assign, Y->s, X->s);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100139
Dave Rodgman7e9af052023-09-28 17:08:16 +0100140 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100141
Dave Rodgman7e9af052023-09-28 17:08:16 +0100142 mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
143 for (size_t i = Y->n; i < X->n; i++) {
144 X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
145 }
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100146 }
147
148cleanup:
149 return ret;
150}
151
152/*
153 * Conditionally swap X and Y, without leaking information
154 * about whether the swap was made or not.
155 * Here it is not ok to simply swap the pointers, which would lead to
156 * different memory access patterns when X and Y are used afterwards.
157 */
158int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
159 mbedtls_mpi *Y,
160 unsigned char swap)
161{
162 int ret = 0;
163 int s;
164 MPI_VALIDATE_RET(X != NULL);
165 MPI_VALIDATE_RET(Y != NULL);
166
167 if (X == Y) {
168 return 0;
169 }
170
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100171 mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
172
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100173 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
174 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
175
176 s = X->s;
Dave Rodgman2b4486a2023-05-17 15:51:59 +0100177 X->s = (int) mbedtls_ct_uint_if(do_swap, Y->s, X->s);
178 Y->s = (int) mbedtls_ct_uint_if(do_swap, s, Y->s);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100179
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100180 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100181
182cleanup:
183 return ret;
184}
185
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500186/* Implementation that should never be optimized out by the compiler */
Tom Cosgrovebc345e82023-07-25 15:17:39 +0100187#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500188
Paul Bakker5121ce52009-01-03 21:22:43 +0000189/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000190 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000191 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100192void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000193{
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000195
Paul Bakker6c591fa2011-05-05 11:49:20 +0000196 X->s = 1;
197 X->n = 0;
198 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000199}
200
201/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000202 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000203 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100204void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000205{
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +0000207 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000209
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 if (X->p != NULL) {
Tom Cosgrove46259f62023-07-18 16:44:14 +0100211 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000212 }
213
Paul Bakker6c591fa2011-05-05 11:49:20 +0000214 X->s = 1;
215 X->n = 0;
216 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217}
218
219/*
220 * Enlarge to the specified number of limbs
221 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100222int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +0000223{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 mbedtls_mpi_uint *p;
Gilles Peskine449bd832023-01-11 14:50:10 +0100225 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000226
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
228 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
229 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000230
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 if (X->n < nblimbs) {
232 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
233 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
234 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000235
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 if (X->p != NULL) {
237 memcpy(p, X->p, X->n * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100238 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000239 }
240
Gilles Peskine053022f2023-06-29 19:26:48 +0200241 /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
242 * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
243 X->n = (unsigned short) nblimbs;
Paul Bakker5121ce52009-01-03 21:22:43 +0000244 X->p = p;
245 }
246
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000248}
249
250/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100251 * Resize down as much as possible,
252 * while keeping at least the specified number of limbs
253 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100254int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100255{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100257 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100258 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000259
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
261 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
262 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100263
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100264 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 if (X->n <= nblimbs) {
266 return mbedtls_mpi_grow(X, nblimbs);
267 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100268 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100269
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 for (i = X->n - 1; i > 0; i--) {
271 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100272 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 }
274 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100275 i++;
276
Gilles Peskine449bd832023-01-11 14:50:10 +0100277 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100278 i = nblimbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100280
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
282 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
283 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100284
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 if (X->p != NULL) {
286 memcpy(p, X->p, i * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100287 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100288 }
289
Gilles Peskine053022f2023-06-29 19:26:48 +0200290 /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
291 * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
292 X->n = (unsigned short) i;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100293 X->p = p;
294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100296}
297
Gilles Peskineed32b572021-06-02 22:17:52 +0200298/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100299static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200300{
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 if (limbs == 0) {
302 mbedtls_mpi_free(X);
303 return 0;
304 } else if (X->n == limbs) {
305 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200306 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 return 0;
308 } else {
309 mbedtls_mpi_free(X);
310 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200311 }
312}
313
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100314/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200315 * Copy the contents of Y into X.
316 *
317 * This function is not constant-time. Leading zeros in Y may be removed.
318 *
319 * Ensure that X does not shrink. This is not guaranteed by the public API,
320 * but some code in the bignum module relies on this property, for example
321 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000322 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100323int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000324{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100325 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000326 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100327 MPI_VALIDATE_RET(X != NULL);
328 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000329
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 if (X == Y) {
331 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200332 }
333
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 if (Y->n == 0) {
335 if (X->n != 0) {
336 X->s = 1;
337 memset(X->p, 0, X->n * ciL);
338 }
339 return 0;
340 }
341
342 for (i = Y->n - 1; i > 0; i--) {
343 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000344 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 }
346 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000347 i++;
348
349 X->s = Y->s;
350
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 if (X->n < i) {
352 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
353 } else {
354 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100355 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
Gilles Peskine449bd832023-01-11 14:50:10 +0100357 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000358
359cleanup:
360
Gilles Peskine449bd832023-01-11 14:50:10 +0100361 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000362}
363
364/*
365 * Swap the contents of X and Y
366 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100367void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000368{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 MPI_VALIDATE(X != NULL);
371 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000372
Gilles Peskine449bd832023-01-11 14:50:10 +0100373 memcpy(&T, X, sizeof(mbedtls_mpi));
374 memcpy(X, Y, sizeof(mbedtls_mpi));
375 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000376}
377
Gilles Peskine449bd832023-01-11 14:50:10 +0100378static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100379{
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 if (z >= 0) {
381 return z;
382 }
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100383 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
384 * A naive -z would have undefined behavior.
385 * Write this in a way that makes popular compilers happy (GCC, Clang,
386 * MSVC). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100388}
389
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100390/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
391 * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
Dave Rodgman73d85912023-09-28 17:00:50 +0100392#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100393
Paul Bakker5121ce52009-01-03 21:22:43 +0000394/*
395 * Set value from integer
396 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100397int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000398{
Janos Follath24eed8d2019-11-22 13:21:35 +0000399 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
403 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000404
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 X->p[0] = mpi_sint_abs(z);
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100406 X->s = TO_SIGN(z);
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
408cleanup:
409
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000411}
412
413/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000414 * Get a specific bit
415 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100416int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000417{
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000419
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 if (X->n * biL <= pos) {
421 return 0;
422 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000425}
426
427/*
428 * Set a bit to a specific value of 0 or 1
429 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100430int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000431{
432 int ret = 0;
433 size_t off = pos / biL;
434 size_t idx = pos % biL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000436
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 if (val != 0 && val != 1) {
438 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000439 }
440
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 if (X->n * biL <= pos) {
442 if (val == 0) {
443 return 0;
444 }
445
446 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
447 }
448
449 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000451
452cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200453
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000455}
456
457/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200458 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000459 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100460size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000461{
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100462 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100465#if defined(__has_builtin)
466#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
467 #define mbedtls_mpi_uint_ctz __builtin_ctz
468#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
469 #define mbedtls_mpi_uint_ctz __builtin_ctzl
470#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
471 #define mbedtls_mpi_uint_ctz __builtin_ctzll
472#endif
473#endif
474
475#if defined(mbedtls_mpi_uint_ctz)
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 for (i = 0; i < X->n; i++) {
Dave Rodgman960eca92023-08-09 20:43:18 +0100477 if (X->p[i] != 0) {
478 return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
479 }
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100480 }
481#else
482 size_t count = 0;
483 for (i = 0; i < X->n; i++) {
484 for (size_t j = 0; j < biL; j++, count++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 if (((X->p[i] >> j) & 1) != 0) {
486 return count;
487 }
488 }
489 }
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100490#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000491
Gilles Peskine449bd832023-01-11 14:50:10 +0100492 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000493}
494
495/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200496 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000497 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100498size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000499{
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 return mbedtls_mpi_core_bitlen(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000501}
502
503/*
504 * Return the total size in bytes
505 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100506size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000507{
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000509}
510
511/*
512 * Convert an ASCII character to digit value
513 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100514static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000515{
516 *d = 255;
517
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 if (c >= 0x30 && c <= 0x39) {
519 *d = c - 0x30;
520 }
521 if (c >= 0x41 && c <= 0x46) {
522 *d = c - 0x37;
523 }
524 if (c >= 0x61 && c <= 0x66) {
525 *d = c - 0x57;
526 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000527
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 if (*d >= (mbedtls_mpi_uint) radix) {
529 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
530 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000531
Gilles Peskine449bd832023-01-11 14:50:10 +0100532 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000533}
534
535/*
536 * Import from an ASCII string
537 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100538int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000539{
Janos Follath24eed8d2019-11-22 13:21:35 +0000540 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000541 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200542 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 mbedtls_mpi_uint d;
544 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 MPI_VALIDATE_RET(X != NULL);
546 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
Gilles Peskine449bd832023-01-11 14:50:10 +0100548 if (radix < 2 || radix > 16) {
549 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200550 }
551
Gilles Peskine449bd832023-01-11 14:50:10 +0100552 mbedtls_mpi_init(&T);
553
554 if (s[0] == 0) {
555 mbedtls_mpi_free(X);
556 return 0;
557 }
558
559 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200560 ++s;
561 sign = -1;
562 }
563
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000565
Gilles Peskine449bd832023-01-11 14:50:10 +0100566 if (radix == 16) {
Dave Rodgman68ef1d62023-05-18 20:49:03 +0100567 if (slen > SIZE_MAX >> 2) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100568 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000569 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Gilles Peskine449bd832023-01-11 14:50:10 +0100571 n = BITS_TO_LIMBS(slen << 2);
572
573 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
574 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
575
576 for (i = slen, j = 0; i > 0; i--, j++) {
577 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
578 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
579 }
580 } else {
581 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
582
583 for (i = 0; i < slen; i++) {
584 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
585 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
586 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 }
588 }
589
Gilles Peskine449bd832023-01-11 14:50:10 +0100590 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200591 X->s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200593
Paul Bakker5121ce52009-01-03 21:22:43 +0000594cleanup:
595
Gilles Peskine449bd832023-01-11 14:50:10 +0100596 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000597
Gilles Peskine449bd832023-01-11 14:50:10 +0100598 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599}
600
601/*
Ron Eldora16fa292018-11-20 14:07:01 +0200602 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100604static int mpi_write_hlp(mbedtls_mpi *X, int radix,
605 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000606{
Janos Follath24eed8d2019-11-22 13:21:35 +0000607 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200609 size_t length = 0;
610 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 do {
613 if (length >= buflen) {
614 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200615 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
Gilles Peskine449bd832023-01-11 14:50:10 +0100617 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
618 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200619 /*
620 * Write the residue in the current position, as an ASCII character.
621 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100622 if (r < 0xA) {
623 *(--p_end) = (char) ('0' + r);
624 } else {
625 *(--p_end) = (char) ('A' + (r - 0xA));
626 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
Ron Eldora16fa292018-11-20 14:07:01 +0200628 length++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100629 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
Gilles Peskine449bd832023-01-11 14:50:10 +0100631 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200632 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000633
634cleanup:
635
Gilles Peskine449bd832023-01-11 14:50:10 +0100636 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000637}
638
639/*
640 * Export into an ASCII string
641 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100642int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
643 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000644{
Paul Bakker23986e52011-04-24 08:57:21 +0000645 int ret = 0;
646 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000647 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100649 MPI_VALIDATE_RET(X != NULL);
650 MPI_VALIDATE_RET(olen != NULL);
651 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 if (radix < 2 || radix > 16) {
654 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
655 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
Gilles Peskine449bd832023-01-11 14:50:10 +0100657 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
658 if (radix >= 4) {
659 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000660 * `n`. If radix > 4, this might be a strict
661 * overapproximation of the number of
662 * radix-adic digits needed to present `n`. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100663 }
664 if (radix >= 16) {
665 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000666 * present `n`. */
667
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 }
Janos Follath80470622019-03-06 13:43:02 +0000669 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000670 n += 1; /* Compensate for the divisions above, which round down `n`
671 * in case it's not even. */
672 n += 1; /* Potential '-'-sign. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000674 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000675
Gilles Peskine449bd832023-01-11 14:50:10 +0100676 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100677 *olen = n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100678 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000679 }
680
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100681 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
Gilles Peskine449bd832023-01-11 14:50:10 +0100684 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000685 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000686 buflen--;
687 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000688
Gilles Peskine449bd832023-01-11 14:50:10 +0100689 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000690 int c;
691 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
Gilles Peskine449bd832023-01-11 14:50:10 +0100693 for (i = X->n, k = 0; i > 0; i--) {
694 for (j = ciL; j > 0; j--) {
695 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000696
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000698 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100699 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000700
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000701 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000702 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000703 k = 1;
704 }
705 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100706 } else {
707 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000708
Gilles Peskine449bd832023-01-11 14:50:10 +0100709 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000710 T.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100711 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000712
Gilles Peskine449bd832023-01-11 14:50:10 +0100713 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000714 }
715
716 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100717 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000718
719cleanup:
720
Gilles Peskine449bd832023-01-11 14:50:10 +0100721 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000722
Gilles Peskine449bd832023-01-11 14:50:10 +0100723 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000724}
725
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000727/*
728 * Read X from an opened file
729 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100730int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000731{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000733 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000735 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000736 * Buffer should have space for (short) label and decimal formatted MPI,
737 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000738 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100739 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000740
Gilles Peskine449bd832023-01-11 14:50:10 +0100741 MPI_VALIDATE_RET(X != NULL);
742 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000743
Gilles Peskine449bd832023-01-11 14:50:10 +0100744 if (radix < 2 || radix > 16) {
745 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
746 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000747
Gilles Peskine449bd832023-01-11 14:50:10 +0100748 memset(s, 0, sizeof(s));
749 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
750 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
751 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000752
Gilles Peskine449bd832023-01-11 14:50:10 +0100753 slen = strlen(s);
754 if (slen == sizeof(s) - 2) {
755 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
756 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000757
Gilles Peskine449bd832023-01-11 14:50:10 +0100758 if (slen > 0 && s[slen - 1] == '\n') {
759 slen--; s[slen] = '\0';
760 }
761 if (slen > 0 && s[slen - 1] == '\r') {
762 slen--; s[slen] = '\0';
763 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
765 p = s + slen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100766 while (p-- > s) {
767 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000768 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100769 }
770 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000771
Gilles Peskine449bd832023-01-11 14:50:10 +0100772 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000773}
774
775/*
776 * Write X into an opened file (or stdout if fout == NULL)
777 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100778int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000779{
Janos Follath24eed8d2019-11-22 13:21:35 +0000780 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000781 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000782 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000783 * Buffer should have space for (short) label and decimal formatted MPI,
784 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000785 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100786 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
787 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000788
Gilles Peskine449bd832023-01-11 14:50:10 +0100789 if (radix < 2 || radix > 16) {
790 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
791 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000792
Gilles Peskine449bd832023-01-11 14:50:10 +0100793 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000794
Gilles Peskine449bd832023-01-11 14:50:10 +0100795 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000796
Gilles Peskine449bd832023-01-11 14:50:10 +0100797 if (p == NULL) {
798 p = "";
799 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000800
Gilles Peskine449bd832023-01-11 14:50:10 +0100801 plen = strlen(p);
802 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000803 s[slen++] = '\r';
804 s[slen++] = '\n';
805
Gilles Peskine449bd832023-01-11 14:50:10 +0100806 if (fout != NULL) {
807 if (fwrite(p, 1, plen, fout) != plen ||
808 fwrite(s, 1, slen, fout) != slen) {
809 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
810 }
811 } else {
812 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000814
815cleanup:
816
Gilles Peskine449bd832023-01-11 14:50:10 +0100817 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000818}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000820
821/*
Janos Follatha778a942019-02-13 10:28:28 +0000822 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100823 *
824 * This function is guaranteed to return an MPI with exactly the necessary
825 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000826 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100827int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
828 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000829{
Janos Follath24eed8d2019-11-22 13:21:35 +0000830 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100831 const size_t limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000832
833 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100834 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000835
Gilles Peskine449bd832023-01-11 14:50:10 +0100836 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Janos Follatha778a942019-02-13 10:28:28 +0000837
838cleanup:
839
Janos Follath171a7ef2019-02-15 16:17:45 +0000840 /*
841 * This function is also used to import keys. However, wiping the buffers
842 * upon failure is not necessary because failure only can happen before any
843 * input is copied.
844 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100845 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000846}
847
848/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000849 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100850 *
851 * This function is guaranteed to return an MPI with exactly the necessary
852 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000853 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100854int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000855{
Janos Follath24eed8d2019-11-22 13:21:35 +0000856 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100857 const size_t limbs = CHARS_TO_LIMBS(buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000858
Gilles Peskine449bd832023-01-11 14:50:10 +0100859 MPI_VALIDATE_RET(X != NULL);
860 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000861
Hanno Becker073c1992017-10-17 15:17:27 +0100862 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100863 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000864
Gilles Peskine449bd832023-01-11 14:50:10 +0100865 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000866
867cleanup:
868
Janos Follath171a7ef2019-02-15 16:17:45 +0000869 /*
870 * This function is also used to import keys. However, wiping the buffers
871 * upon failure is not necessary because failure only can happen before any
872 * input is copied.
873 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100874 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000875}
876
877/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000878 * Export X into unsigned binary data, little endian
879 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100880int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
881 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000882{
Gilles Peskine449bd832023-01-11 14:50:10 +0100883 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Janos Follathe344d0f2019-02-19 16:17:40 +0000884}
885
886/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000887 * Export X into unsigned binary data, big endian
888 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100889int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
890 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000891{
Gilles Peskine449bd832023-01-11 14:50:10 +0100892 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000893}
894
895/*
896 * Left-shift: X <<= count
897 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100898int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000899{
Janos Follath24eed8d2019-11-22 13:21:35 +0000900 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Minos Galanakis0144b352023-05-02 14:02:32 +0100901 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100902 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000903
Gilles Peskine449bd832023-01-11 14:50:10 +0100904 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
Gilles Peskine449bd832023-01-11 14:50:10 +0100906 if (X->n * biL < i) {
907 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
908 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
910 ret = 0;
911
Minos Galanakis0144b352023-05-02 14:02:32 +0100912 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Paul Bakker5121ce52009-01-03 21:22:43 +0000913cleanup:
914
Gilles Peskine449bd832023-01-11 14:50:10 +0100915 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000916}
917
918/*
919 * Right-shift: X >>= count
920 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100921int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000922{
Gilles Peskine449bd832023-01-11 14:50:10 +0100923 MPI_VALIDATE_RET(X != NULL);
924 if (X->n != 0) {
925 mbedtls_mpi_core_shift_r(X->p, X->n, count);
926 }
927 return 0;
Gilles Peskine66414202022-09-21 15:36:16 +0200928}
929
Paul Bakker5121ce52009-01-03 21:22:43 +0000930/*
931 * Compare unsigned values
932 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100933int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000934{
Paul Bakker23986e52011-04-24 08:57:21 +0000935 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100936 MPI_VALIDATE_RET(X != NULL);
937 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000938
Gilles Peskine449bd832023-01-11 14:50:10 +0100939 for (i = X->n; i > 0; i--) {
940 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000941 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100942 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 }
944
Gilles Peskine449bd832023-01-11 14:50:10 +0100945 for (j = Y->n; j > 0; j--) {
946 if (Y->p[j - 1] != 0) {
947 break;
948 }
949 }
950
Dave Rodgmanebcd7852023-08-09 18:56:42 +0100951 /* If i == j == 0, i.e. abs(X) == abs(Y),
952 * we end up returning 0 at the end of the function. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100953
954 if (i > j) {
955 return 1;
956 }
957 if (j > i) {
958 return -1;
959 }
960
961 for (; i > 0; i--) {
962 if (X->p[i - 1] > Y->p[i - 1]) {
963 return 1;
964 }
965 if (X->p[i - 1] < Y->p[i - 1]) {
966 return -1;
967 }
968 }
969
970 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000971}
972
973/*
974 * Compare signed values
975 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100976int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000977{
Paul Bakker23986e52011-04-24 08:57:21 +0000978 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100979 MPI_VALIDATE_RET(X != NULL);
980 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000981
Gilles Peskine449bd832023-01-11 14:50:10 +0100982 for (i = X->n; i > 0; i--) {
983 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100985 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000986 }
987
Gilles Peskine449bd832023-01-11 14:50:10 +0100988 for (j = Y->n; j > 0; j--) {
989 if (Y->p[j - 1] != 0) {
990 break;
991 }
992 }
993
994 if (i == 0 && j == 0) {
995 return 0;
996 }
997
998 if (i > j) {
999 return X->s;
1000 }
1001 if (j > i) {
1002 return -Y->s;
1003 }
1004
1005 if (X->s > 0 && Y->s < 0) {
1006 return 1;
1007 }
1008 if (Y->s > 0 && X->s < 0) {
1009 return -1;
1010 }
1011
1012 for (; i > 0; i--) {
1013 if (X->p[i - 1] > Y->p[i - 1]) {
1014 return X->s;
1015 }
1016 if (X->p[i - 1] < Y->p[i - 1]) {
1017 return -X->s;
1018 }
1019 }
1020
1021 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001022}
1023
Janos Follathee6abce2019-09-05 14:47:19 +01001024/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 * Compare signed values
1026 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001027int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +00001028{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001029 mbedtls_mpi Y;
1030 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001031 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001032
Gilles Peskine449bd832023-01-11 14:50:10 +01001033 *p = mpi_sint_abs(z);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001034 Y.s = TO_SIGN(z);
Paul Bakker5121ce52009-01-03 21:22:43 +00001035 Y.n = 1;
1036 Y.p = p;
1037
Gilles Peskine449bd832023-01-11 14:50:10 +01001038 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00001039}
1040
1041/*
1042 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1043 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001044int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001045{
Janos Follath24eed8d2019-11-22 13:21:35 +00001046 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001047 size_t j;
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +01001048 mbedtls_mpi_uint *p;
1049 mbedtls_mpi_uint c;
Gilles Peskine449bd832023-01-11 14:50:10 +01001050 MPI_VALIDATE_RET(X != NULL);
1051 MPI_VALIDATE_RET(A != NULL);
1052 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001053
Gilles Peskine449bd832023-01-11 14:50:10 +01001054 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 }
1057
Gilles Peskine449bd832023-01-11 14:50:10 +01001058 if (X != A) {
1059 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1060 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001061
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001062 /*
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001063 * X must always be positive as a result of unsigned additions.
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001064 */
1065 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001066
Gilles Peskine449bd832023-01-11 14:50:10 +01001067 for (j = B->n; j > 0; j--) {
1068 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001070 }
1071 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001072
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001073 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1074 * and B is 0 (of any size). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001075 if (j == 0) {
1076 return 0;
1077 }
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001078
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001080
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001081 /* j is the number of non-zero limbs of B. Add those to X. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001082
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +01001083 p = X->p;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001084
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +01001085 c = mbedtls_mpi_core_add(p, p, B->p, j);
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001086
1087 p += j;
1088
1089 /* Now propagate any carry */
Paul Bakker5121ce52009-01-03 21:22:43 +00001090
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 while (c != 0) {
1092 if (j >= X->n) {
1093 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001094 p = X->p + j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 }
1096
Gilles Peskine449bd832023-01-11 14:50:10 +01001097 *p += c; c = (*p < c); j++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 }
1099
1100cleanup:
1101
Gilles Peskine449bd832023-01-11 14:50:10 +01001102 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001103}
1104
Paul Bakker5121ce52009-01-03 21:22:43 +00001105/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001106 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001107 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001108int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001109{
Janos Follath24eed8d2019-11-22 13:21:35 +00001110 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001111 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001112 mbedtls_mpi_uint carry;
Gilles Peskine449bd832023-01-11 14:50:10 +01001113 MPI_VALIDATE_RET(X != NULL);
1114 MPI_VALIDATE_RET(A != NULL);
1115 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001116
Gilles Peskine449bd832023-01-11 14:50:10 +01001117 for (n = B->n; n > 0; n--) {
1118 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001119 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001120 }
1121 }
1122 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001123 /* B >= (2^ciL)^n > A */
1124 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1125 goto cleanup;
1126 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001127
Gilles Peskine449bd832023-01-11 14:50:10 +01001128 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001129
1130 /* Set the high limbs of X to match A. Don't touch the lower limbs
1131 * because X might be aliased to B, and we must not overwrite the
1132 * significant digits of B. */
Aaron M. Uckoaf67d2c2023-01-17 11:52:22 -05001133 if (A->n > n && A != X) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1135 }
1136 if (X->n > A->n) {
1137 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1138 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001139
Gilles Peskine449bd832023-01-11 14:50:10 +01001140 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1141 if (carry != 0) {
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001142 /* Propagate the carry through the rest of X. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001143 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001144
1145 /* If we have further carry/borrow, the result is negative. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001146 if (carry != 0) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001147 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1148 goto cleanup;
1149 }
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001150 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001151
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001152 /* X should always be positive as a result of unsigned subtractions. */
1153 X->s = 1;
1154
Paul Bakker5121ce52009-01-03 21:22:43 +00001155cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001156 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001157}
1158
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001159/* Common function for signed addition and subtraction.
1160 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001162static int add_sub_mpi(mbedtls_mpi *X,
1163 const mbedtls_mpi *A, const mbedtls_mpi *B,
1164 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001165{
Hanno Becker73d7d792018-12-11 10:35:51 +00001166 int ret, s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001167 MPI_VALIDATE_RET(X != NULL);
1168 MPI_VALIDATE_RET(A != NULL);
1169 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001170
Hanno Becker73d7d792018-12-11 10:35:51 +00001171 s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001172 if (A->s * B->s * flip_B < 0) {
1173 int cmp = mbedtls_mpi_cmp_abs(A, B);
1174 if (cmp >= 0) {
1175 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001176 /* If |A| = |B|, the result is 0 and we must set the sign bit
1177 * to +1 regardless of which of A or B was negative. Otherwise,
1178 * since |A| > |B|, the sign is the sign of A. */
1179 X->s = cmp == 0 ? 1 : s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001180 } else {
1181 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001182 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001183 X->s = -s;
1184 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001185 } else {
1186 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001187 X->s = s;
1188 }
1189
1190cleanup:
1191
Gilles Peskine449bd832023-01-11 14:50:10 +01001192 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001193}
1194
1195/*
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001196 * Signed addition: X = A + B
1197 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001198int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001199{
Gilles Peskine449bd832023-01-11 14:50:10 +01001200 return add_sub_mpi(X, A, B, 1);
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001201}
1202
1203/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001204 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001205 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001206int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001207{
Gilles Peskine449bd832023-01-11 14:50:10 +01001208 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001209}
1210
1211/*
1212 * Signed addition: X = A + b
1213 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001214int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001215{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001216 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001218 MPI_VALIDATE_RET(X != NULL);
1219 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001220
Gilles Peskine449bd832023-01-11 14:50:10 +01001221 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001222 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001223 B.n = 1;
1224 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001225
Gilles Peskine449bd832023-01-11 14:50:10 +01001226 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001227}
1228
1229/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001230 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001232int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001233{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001234 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001236 MPI_VALIDATE_RET(X != NULL);
1237 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001238
Gilles Peskine449bd832023-01-11 14:50:10 +01001239 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001240 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001241 B.n = 1;
1242 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001243
Gilles Peskine449bd832023-01-11 14:50:10 +01001244 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001245}
1246
Paul Bakker5121ce52009-01-03 21:22:43 +00001247/*
1248 * Baseline multiplication: X = A * B (HAC 14.12)
1249 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001250int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001251{
Janos Follath24eed8d2019-11-22 13:21:35 +00001252 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001253 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001255 int result_is_zero = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001256 MPI_VALIDATE_RET(X != NULL);
1257 MPI_VALIDATE_RET(A != NULL);
1258 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001259
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001260 mbedtls_mpi_init(&TA);
1261 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001262
Gilles Peskine449bd832023-01-11 14:50:10 +01001263 if (X == A) {
1264 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1265 }
1266 if (X == B) {
1267 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1268 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001269
Gilles Peskine449bd832023-01-11 14:50:10 +01001270 for (i = A->n; i > 0; i--) {
1271 if (A->p[i - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001272 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001273 }
1274 }
1275 if (i == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001276 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001277 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001278
Gilles Peskine449bd832023-01-11 14:50:10 +01001279 for (j = B->n; j > 0; j--) {
1280 if (B->p[j - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001281 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001282 }
1283 }
1284 if (j == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001285 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001286 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001287
Gilles Peskine449bd832023-01-11 14:50:10 +01001288 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1289 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001290
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001291 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Paul Bakker5121ce52009-01-03 21:22:43 +00001292
Hanno Beckerda763de2022-04-13 06:50:02 +01001293 /* If the result is 0, we don't shortcut the operation, which reduces
1294 * but does not eliminate side channels leaking the zero-ness. We do
1295 * need to take care to set the sign bit properly since the library does
1296 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001297 if (result_is_zero) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001298 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001299 } else {
Hanno Beckerda763de2022-04-13 06:50:02 +01001300 X->s = A->s * B->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001301 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001302
1303cleanup:
1304
Gilles Peskine449bd832023-01-11 14:50:10 +01001305 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001306
Gilles Peskine449bd832023-01-11 14:50:10 +01001307 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001308}
1309
1310/*
1311 * Baseline multiplication: X = A * b
1312 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001313int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001314{
Gilles Peskine449bd832023-01-11 14:50:10 +01001315 MPI_VALIDATE_RET(X != NULL);
1316 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001317
Hanno Becker35771312022-04-14 11:52:11 +01001318 size_t n = A->n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001319 while (n > 0 && A->p[n - 1] == 0) {
Hanno Becker35771312022-04-14 11:52:11 +01001320 --n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001321 }
Hanno Becker35771312022-04-14 11:52:11 +01001322
Hanno Becker74a11a32022-04-06 06:27:00 +01001323 /* The general method below doesn't work if b==0. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001324 if (b == 0 || n == 0) {
1325 return mbedtls_mpi_lset(X, 0);
1326 }
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001327
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001328 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001329 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001330 /* In general, A * b requires 1 limb more than b. If
1331 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1332 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001333 * copy() will take care of the growth if needed. However, experimentally,
1334 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001335 * calls to calloc() in ECP code, presumably because it reuses the
1336 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001337 * grow to its final size.
1338 *
1339 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1340 * A,X can be the same. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001341 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1342 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1343 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001344
1345cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001346 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001347}
1348
1349/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001350 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1351 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001352 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001353static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1354 mbedtls_mpi_uint u0,
1355 mbedtls_mpi_uint d,
1356 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001357{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001358#if defined(MBEDTLS_HAVE_UDBL)
1359 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001360#else
Simon Butcher9803d072016-01-03 00:24:34 +00001361 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001362 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001363 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1364 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001365 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001366#endif
1367
Simon Butcher15b15d12015-11-26 19:35:03 +00001368 /*
1369 * Check for overflow
1370 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001371 if (0 == d || u1 >= d) {
1372 if (r != NULL) {
1373 *r = ~(mbedtls_mpi_uint) 0u;
1374 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001375
Gilles Peskine449bd832023-01-11 14:50:10 +01001376 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001377 }
1378
1379#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001380 dividend = (mbedtls_t_udbl) u1 << biL;
1381 dividend |= (mbedtls_t_udbl) u0;
1382 quotient = dividend / d;
Gilles Peskine449bd832023-01-11 14:50:10 +01001383 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1384 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1385 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001386
Gilles Peskine449bd832023-01-11 14:50:10 +01001387 if (r != NULL) {
1388 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1389 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001390
1391 return (mbedtls_mpi_uint) quotient;
1392#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001393
1394 /*
1395 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1396 * Vol. 2 - Seminumerical Algorithms, Knuth
1397 */
1398
1399 /*
1400 * Normalize the divisor, d, and dividend, u0, u1
1401 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001402 s = mbedtls_mpi_core_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001403 d = d << s;
1404
1405 u1 = u1 << s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001406 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001407 u0 = u0 << s;
1408
1409 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001410 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001411
1412 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001413 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001414
1415 /*
1416 * Find the first quotient and remainder
1417 */
1418 q1 = u1 / d1;
1419 r0 = u1 - d1 * q1;
1420
Gilles Peskine449bd832023-01-11 14:50:10 +01001421 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001422 q1 -= 1;
1423 r0 += d1;
1424
Gilles Peskine449bd832023-01-11 14:50:10 +01001425 if (r0 >= radix) {
1426 break;
1427 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001428 }
1429
Gilles Peskine449bd832023-01-11 14:50:10 +01001430 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001431 q0 = rAX / d1;
1432 r0 = rAX - q0 * d1;
1433
Gilles Peskine449bd832023-01-11 14:50:10 +01001434 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001435 q0 -= 1;
1436 r0 += d1;
1437
Gilles Peskine449bd832023-01-11 14:50:10 +01001438 if (r0 >= radix) {
1439 break;
1440 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001441 }
1442
Gilles Peskine449bd832023-01-11 14:50:10 +01001443 if (r != NULL) {
1444 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1445 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001446
1447 quotient = q1 * radix + q0;
1448
1449 return quotient;
1450#endif
1451}
1452
1453/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001454 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001455 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001456int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1457 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001458{
Janos Follath24eed8d2019-11-22 13:21:35 +00001459 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001460 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001462 mbedtls_mpi_uint TP2[3];
Gilles Peskine449bd832023-01-11 14:50:10 +01001463 MPI_VALIDATE_RET(A != NULL);
1464 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001465
Gilles Peskine449bd832023-01-11 14:50:10 +01001466 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1467 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1468 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001469
Gilles Peskine449bd832023-01-11 14:50:10 +01001470 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1471 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001472 /*
1473 * Avoid dynamic memory allocations for constant-size T2.
1474 *
1475 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1476 * so nobody increase the size of the MPI and we're safe to use an on-stack
1477 * buffer.
1478 */
Alexander K35d6d462019-10-31 14:46:45 +03001479 T2.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001480 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001481 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
Gilles Peskine449bd832023-01-11 14:50:10 +01001483 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1484 if (Q != NULL) {
1485 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1486 }
1487 if (R != NULL) {
1488 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1489 }
1490 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001491 }
1492
Gilles Peskine449bd832023-01-11 14:50:10 +01001493 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1494 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001495 X.s = Y.s = 1;
1496
Gilles Peskine449bd832023-01-11 14:50:10 +01001497 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1498 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1499 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001500
Gilles Peskine449bd832023-01-11 14:50:10 +01001501 k = mbedtls_mpi_bitlen(&Y) % biL;
1502 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 k = biL - 1 - k;
Gilles Peskine449bd832023-01-11 14:50:10 +01001504 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1505 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1506 } else {
1507 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001509
1510 n = X.n - 1;
1511 t = Y.n - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001512 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
Gilles Peskine449bd832023-01-11 14:50:10 +01001514 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001515 Z.p[n - t]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001516 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001518 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001519
Gilles Peskine449bd832023-01-11 14:50:10 +01001520 for (i = n; i > t; i--) {
1521 if (X.p[i] >= Y.p[t]) {
1522 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1523 } else {
1524 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1525 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001526 }
1527
Gilles Peskine449bd832023-01-11 14:50:10 +01001528 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1529 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001530 T2.p[2] = X.p[i];
1531
Paul Bakker5121ce52009-01-03 21:22:43 +00001532 Z.p[i - t - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001533 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001534 Z.p[i - t - 1]--;
1535
Gilles Peskine449bd832023-01-11 14:50:10 +01001536 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1537 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001538 T1.p[1] = Y.p[t];
Gilles Peskine449bd832023-01-11 14:50:10 +01001539 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1540 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Gilles Peskine449bd832023-01-11 14:50:10 +01001542 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1543 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1544 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001545
Gilles Peskine449bd832023-01-11 14:50:10 +01001546 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1547 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1548 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1549 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 Z.p[i - t - 1]--;
1551 }
1552 }
1553
Gilles Peskine449bd832023-01-11 14:50:10 +01001554 if (Q != NULL) {
1555 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001556 Q->s = A->s * B->s;
1557 }
1558
Gilles Peskine449bd832023-01-11 14:50:10 +01001559 if (R != NULL) {
1560 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001561 X.s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001562 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001563
Gilles Peskine449bd832023-01-11 14:50:10 +01001564 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001565 R->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001566 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001567 }
1568
1569cleanup:
1570
Gilles Peskine449bd832023-01-11 14:50:10 +01001571 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1572 mbedtls_mpi_free(&T1);
1573 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001574
Gilles Peskine449bd832023-01-11 14:50:10 +01001575 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001576}
1577
1578/*
1579 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001580 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001581int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1582 const mbedtls_mpi *A,
1583 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001584{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001585 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001587 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001588
Gilles Peskine449bd832023-01-11 14:50:10 +01001589 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001590 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001591 B.n = 1;
1592 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001593
Gilles Peskine449bd832023-01-11 14:50:10 +01001594 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001595}
1596
1597/*
1598 * Modulo: R = A mod B
1599 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001600int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001601{
Janos Follath24eed8d2019-11-22 13:21:35 +00001602 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01001603 MPI_VALIDATE_RET(R != NULL);
1604 MPI_VALIDATE_RET(A != NULL);
1605 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
Gilles Peskine449bd832023-01-11 14:50:10 +01001607 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1608 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1609 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001610
Gilles Peskine449bd832023-01-11 14:50:10 +01001611 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001612
Gilles Peskine449bd832023-01-11 14:50:10 +01001613 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1614 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1615 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001616
Gilles Peskine449bd832023-01-11 14:50:10 +01001617 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1618 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1619 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
1621cleanup:
1622
Gilles Peskine449bd832023-01-11 14:50:10 +01001623 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001624}
1625
1626/*
1627 * Modulo: r = A mod b
1628 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001629int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001630{
Paul Bakker23986e52011-04-24 08:57:21 +00001631 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 mbedtls_mpi_uint x, y, z;
Gilles Peskine449bd832023-01-11 14:50:10 +01001633 MPI_VALIDATE_RET(r != NULL);
1634 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001635
Gilles Peskine449bd832023-01-11 14:50:10 +01001636 if (b == 0) {
1637 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1638 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001639
Gilles Peskine449bd832023-01-11 14:50:10 +01001640 if (b < 0) {
1641 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1642 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
1644 /*
1645 * handle trivial cases
1646 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001647 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 *r = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001649 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 }
1651
Gilles Peskine449bd832023-01-11 14:50:10 +01001652 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 *r = A->p[0] & 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001654 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001655 }
1656
1657 /*
1658 * general case
1659 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001660 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001661 x = A->p[i - 1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001662 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001663 z = y / b;
1664 y -= z * b;
1665
1666 x <<= biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001667 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001668 z = y / b;
1669 y -= z * b;
1670 }
1671
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001672 /*
1673 * If A is negative, then the current y represents a negative value.
1674 * Flipping it to the positive side.
1675 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001676 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001677 y = b - y;
Gilles Peskine449bd832023-01-11 14:50:10 +01001678 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001679
Paul Bakker5121ce52009-01-03 21:22:43 +00001680 *r = y;
1681
Gilles Peskine449bd832023-01-11 14:50:10 +01001682 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001683}
1684
Gilles Peskine449bd832023-01-11 14:50:10 +01001685static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001686{
Gilles Peskine449bd832023-01-11 14:50:10 +01001687 *mm = mbedtls_mpi_core_montmul_init(N->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001688}
1689
Tom Cosgrove93842842022-08-05 16:59:43 +01001690/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1691 *
1692 * \param[in,out] A One of the numbers to multiply.
1693 * It must have at least as many limbs as N
1694 * (A->n >= N->n), and any limbs beyond n are ignored.
1695 * On successful completion, A contains the result of
1696 * the multiplication A * B * R^-1 mod N where
1697 * R = (2^ciL)^n.
1698 * \param[in] B One of the numbers to multiply.
1699 * It must be nonzero and must not have more limbs than N
1700 * (B->n <= N->n).
Tom Cosgrove40d22942022-08-17 06:42:44 +01001701 * \param[in] N The modulus. \p N must be odd.
Tom Cosgrove93842842022-08-05 16:59:43 +01001702 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1703 * This is -N^-1 mod 2^ciL.
1704 * \param[in,out] T A bignum for temporary storage.
1705 * It must be at least twice the limb size of N plus 1
1706 * (T->n >= 2 * N->n + 1).
1707 * Its initial content is unused and
1708 * its final content is indeterminate.
Tom Cosgrove5dd97e62022-08-30 14:31:49 +01001709 * It does not get reallocated.
Tom Cosgrove93842842022-08-05 16:59:43 +01001710 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001711static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1712 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1713 mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001714{
Gilles Peskine449bd832023-01-11 14:50:10 +01001715 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 +00001716}
1717
1718/*
1719 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001720 *
Tom Cosgrove93842842022-08-05 16:59:43 +01001721 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001723static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1724 mbedtls_mpi_uint mm, mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001725{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001726 mbedtls_mpi_uint z = 1;
1727 mbedtls_mpi U;
Gilles Peskine053022f2023-06-29 19:26:48 +02001728 U.n = 1;
1729 U.s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001730 U.p = &z;
1731
Gilles Peskine449bd832023-01-11 14:50:10 +01001732 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001733}
1734
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001735/**
1736 * Select an MPI from a table without leaking the index.
1737 *
1738 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1739 * reads the entire table in order to avoid leaking the value of idx to an
1740 * attacker able to observe memory access patterns.
1741 *
1742 * \param[out] R Where to write the selected MPI.
1743 * \param[in] T The table to read from.
1744 * \param[in] T_size The number of elements in the table.
1745 * \param[in] idx The index of the element to select;
1746 * this must satisfy 0 <= idx < T_size.
1747 *
1748 * \return \c 0 on success, or a negative error code.
1749 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001750static 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 +01001751{
1752 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1753
Gilles Peskine449bd832023-01-11 14:50:10 +01001754 for (size_t i = 0; i < T_size; i++) {
1755 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
Dave Rodgmanb7825ce2023-08-10 11:58:18 +01001756 (unsigned char) mbedtls_ct_uint_eq(i, idx)));
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001757 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001758cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001759 return ret;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001760}
1761
Paul Bakker5121ce52009-01-03 21:22:43 +00001762/*
1763 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1764 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001765int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1766 const mbedtls_mpi *E, const mbedtls_mpi *N,
1767 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00001768{
Janos Follath24eed8d2019-11-22 13:21:35 +00001769 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath74601202022-11-21 15:54:20 +00001770 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00001771 size_t i, j, nblimbs;
1772 size_t bufsize, nbits;
Paul Elliott1748de12023-02-13 15:35:35 +00001773 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine449bd832023-01-11 14:50:10 +01001775 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001776 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001777
Gilles Peskine449bd832023-01-11 14:50:10 +01001778 MPI_VALIDATE_RET(X != NULL);
1779 MPI_VALIDATE_RET(A != NULL);
1780 MPI_VALIDATE_RET(E != NULL);
1781 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001782
Gilles Peskine449bd832023-01-11 14:50:10 +01001783 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1784 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1785 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001786
Gilles Peskine449bd832023-01-11 14:50:10 +01001787 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1788 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1789 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00001790
Gilles Peskine449bd832023-01-11 14:50:10 +01001791 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1792 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1793 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1794 }
Chris Jones9246d042020-11-25 15:12:39 +00001795
Paul Bakkerf6198c12012-05-16 08:02:29 +00001796 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001797 * Init temps and window size
1798 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001799 mpi_montg_init(&mm, N);
1800 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
1801 mbedtls_mpi_init(&Apos);
1802 mbedtls_mpi_init(&WW);
1803 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Gilles Peskine449bd832023-01-11 14:50:10 +01001805 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
Gilles Peskine449bd832023-01-11 14:50:10 +01001807 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1808 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Gilles Peskine449bd832023-01-11 14:50:10 +01001810#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
1811 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath7fa11b82022-11-21 14:48:02 +00001812 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +01001813 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001814#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001815
Janos Follathc8d66d52022-11-22 10:47:10 +00001816 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath06000952022-11-22 10:18:06 +00001817
Paul Bakker5121ce52009-01-03 21:22:43 +00001818 /*
Janos Follathbe54ca72022-11-21 16:14:54 +00001819 * This function is not constant-trace: its memory accesses depend on the
1820 * exponent value. To defend against timing attacks, callers (such as RSA
1821 * and DHM) should use exponent blinding. However this is not enough if the
1822 * adversary can find the exponent in a single trace, so this function
1823 * takes extra precautions against adversaries who can observe memory
1824 * access patterns.
Janos Follathf08b40e2022-11-11 15:56:38 +00001825 *
Janos Follathbe54ca72022-11-21 16:14:54 +00001826 * This function performs a series of multiplications by table elements and
1827 * squarings, and we want the prevent the adversary from finding out which
1828 * table element was used, and from distinguishing between multiplications
1829 * and squarings. Firstly, when multiplying by an element of the window
1830 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
1831 * squarings as having a different memory access patterns from other
Gilles Peskinee6cb45e2023-08-10 15:59:28 +02001832 * multiplications. So secondly, we put the accumulator in the table as
1833 * well, and also do a constant-trace table lookup to multiply by the
1834 * accumulator which is W[x_index].
Janos Follathbe54ca72022-11-21 16:14:54 +00001835 *
1836 * This way, all multiplications take the form of a lookup-and-multiply.
1837 * The number of lookup-and-multiply operations inside each iteration of
1838 * the main loop still depends on the bits of the exponent, but since the
1839 * other operations in the loop don't have an easily recognizable memory
1840 * trace, an adversary is unlikely to be able to observe the exact
1841 * patterns.
1842 *
1843 * An adversary may still be able to recover the exponent if they can
1844 * observe both memory accesses and branches. However, branch prediction
1845 * exploitation typically requires many traces of execution over the same
1846 * data, which is defeated by randomized blinding.
Janos Follath8e7d6a02022-10-04 13:27:40 +01001847 */
Janos Follathc8d66d52022-11-22 10:47:10 +00001848 const size_t x_index = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001849 mbedtls_mpi_init(&W[x_index]);
Janos Follath84461482022-11-21 14:31:22 +00001850
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 j = N->n + 1;
Gilles Peskinee6cb45e2023-08-10 15:59:28 +02001852 /* All W[i] including the accumulator must have at least N->n limbs for
1853 * the mpi_montmul() and mpi_montred() calls later. Here we ensure that
1854 * W[1] and the accumulator W[x_index] are large enough. later we'll grow
1855 * other W[i] to the same length. They must not be shrunk midway through
1856 * this function!
Paul Bakker5121ce52009-01-03 21:22:43 +00001857 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001858 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1859 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
1860 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001861
1862 /*
Paul Bakker50546922012-05-19 08:40:49 +00001863 * Compensate for negative A (and correct at the end)
1864 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001865 neg = (A->s == -1);
1866 if (neg) {
1867 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00001868 Apos.s = 1;
1869 A = &Apos;
1870 }
1871
1872 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 * If 1st call, pre-compute R^2 mod N
1874 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001875 if (prec_RR == NULL || prec_RR->p == NULL) {
1876 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
1877 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
1878 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001879
Gilles Peskine449bd832023-01-11 14:50:10 +01001880 if (prec_RR != NULL) {
1881 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
1882 }
1883 } else {
1884 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
1887 /*
1888 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1889 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001890 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1891 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001892 /* This should be a no-op because W[1] is already that large before
1893 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Tom Cosgrove93842842022-08-05 16:59:43 +01001894 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001895 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
1896 } else {
1897 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001898 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001900 /* Note that this is safe because W[1] always has at least N->n limbs
1901 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001902 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
1904 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001905 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001906 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001907 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1908 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001909
Janos Follathc8d66d52022-11-22 10:47:10 +00001910
Gilles Peskine449bd832023-01-11 14:50:10 +01001911 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001912 /*
Janos Follath74601202022-11-21 15:54:20 +00001913 * W[i] = W[1] ^ i
1914 *
1915 * The first bit of the sliding window is always 1 and therefore we
1916 * only need to store the second half of the table.
Janos Follathc8d66d52022-11-22 10:47:10 +00001917 *
1918 * (There are two special elements in the table: W[0] for the
1919 * accumulator/result and W[1] for A in Montgomery form. Both of these
1920 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00001921 */
Janos Follath74601202022-11-21 15:54:20 +00001922 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
Gilles Peskine449bd832023-01-11 14:50:10 +01001924 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1925 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001926
Gilles Peskine449bd832023-01-11 14:50:10 +01001927 for (i = 0; i < window_bitsize - 1; i++) {
1928 mpi_montmul(&W[j], &W[j], N, mm, &T);
1929 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01001930
Paul Bakker5121ce52009-01-03 21:22:43 +00001931 /*
1932 * W[i] = W[i - 1] * W[1]
1933 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001934 for (i = j + 1; i < w_table_used_size; i++) {
1935 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1936 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
Gilles Peskine449bd832023-01-11 14:50:10 +01001938 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 }
1940 }
1941
1942 nblimbs = E->n;
1943 bufsize = 0;
1944 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001945 state = 0;
1946
Gilles Peskine449bd832023-01-11 14:50:10 +01001947 while (1) {
1948 if (bufsize == 0) {
1949 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001950 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001951 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001952
Paul Bakker0d7702c2013-10-29 16:18:35 +01001953 nblimbs--;
1954
Gilles Peskine449bd832023-01-11 14:50:10 +01001955 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001956 }
1957
1958 bufsize--;
1959
1960 ei = (E->p[nblimbs] >> bufsize) & 1;
1961
1962 /*
1963 * skip leading 0s
1964 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001965 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001966 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01001967 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
Gilles Peskine449bd832023-01-11 14:50:10 +01001969 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001970 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001971 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00001972 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001973 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1974 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001975 continue;
1976 }
1977
1978 /*
1979 * add ei to current window
1980 */
1981 state = 2;
1982
1983 nbits++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001984 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
Gilles Peskine449bd832023-01-11 14:50:10 +01001986 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001988 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001989 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001990 for (i = 0; i < window_bitsize; i++) {
1991 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1992 x_index));
1993 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001994 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
1996 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001997 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001998 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001999 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
2000 exponent_bits_in_window));
2001 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002002
2003 state--;
2004 nbits = 0;
Janos Follath7fa11b82022-11-21 14:48:02 +00002005 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002006 }
2007 }
2008
2009 /*
2010 * process the remaining bits
2011 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002012 for (i = 0; i < nbits; i++) {
2013 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
2014 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002015
Janos Follath7fa11b82022-11-21 14:48:02 +00002016 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
Gilles Peskine449bd832023-01-11 14:50:10 +01002018 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
2019 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
2020 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01002021 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002022 }
2023
2024 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01002025 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002026 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002027 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
Gilles Peskine449bd832023-01-11 14:50:10 +01002029 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath8e7d6a02022-10-04 13:27:40 +01002030 W[x_index].s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002031 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00002032 }
2033
Janos Follath8e7d6a02022-10-04 13:27:40 +01002034 /*
2035 * Load the result in the output variable.
2036 */
Chien Wonge2caf412023-08-01 21:38:46 +08002037 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
Janos Follath8e7d6a02022-10-04 13:27:40 +01002038
Paul Bakker5121ce52009-01-03 21:22:43 +00002039cleanup:
2040
Janos Follathb2c2fca2022-11-21 15:05:31 +00002041 /* The first bit of the sliding window is always 1 and therefore the first
2042 * half of the table was unused. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002043 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
2044 mbedtls_mpi_free(&W[i]);
2045 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
Gilles Peskine449bd832023-01-11 14:50:10 +01002047 mbedtls_mpi_free(&W[x_index]);
2048 mbedtls_mpi_free(&W[1]);
2049 mbedtls_mpi_free(&T);
2050 mbedtls_mpi_free(&Apos);
2051 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00002052
Gilles Peskine449bd832023-01-11 14:50:10 +01002053 if (prec_RR == NULL || prec_RR->p == NULL) {
2054 mbedtls_mpi_free(&RR);
2055 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
Gilles Peskine449bd832023-01-11 14:50:10 +01002057 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002058}
2059
Paul Bakker5121ce52009-01-03 21:22:43 +00002060/*
2061 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2062 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002063int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002064{
Janos Follath24eed8d2019-11-22 13:21:35 +00002065 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002066 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002067 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002068
Gilles Peskine449bd832023-01-11 14:50:10 +01002069 MPI_VALIDATE_RET(G != NULL);
2070 MPI_VALIDATE_RET(A != NULL);
2071 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002072
Gilles Peskine449bd832023-01-11 14:50:10 +01002073 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
Gilles Peskine449bd832023-01-11 14:50:10 +01002075 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2076 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002077
Gilles Peskine449bd832023-01-11 14:50:10 +01002078 lz = mbedtls_mpi_lsb(&TA);
2079 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002080
Gilles Peskine27253bc2021-06-09 13:26:43 +02002081 /* The loop below gives the correct result when A==0 but not when B==0.
2082 * So have a special case for B==0. Leverage the fact that we just
2083 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2084 * slightly more efficient than cmp_int(). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002085 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
2086 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02002087 goto cleanup;
2088 }
2089
Gilles Peskine449bd832023-01-11 14:50:10 +01002090 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002091 lz = lzt;
Gilles Peskine449bd832023-01-11 14:50:10 +01002092 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002093
Paul Bakker5121ce52009-01-03 21:22:43 +00002094 TA.s = TB.s = 1;
2095
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002096 /* We mostly follow the procedure described in HAC 14.54, but with some
2097 * minor differences:
2098 * - Sequences of multiplications or divisions by 2 are grouped into a
2099 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002100 * - The procedure in HAC assumes that 0 < TB <= TA.
2101 * - The condition TB <= TA is not actually necessary for correctness.
2102 * TA and TB have symmetric roles except for the loop termination
2103 * condition, and the shifts at the beginning of the loop body
2104 * remove any significance from the ordering of TA vs TB before
2105 * the shifts.
2106 * - If TA = 0, the loop goes through 0 iterations and the result is
2107 * correctly TB.
2108 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002109 *
2110 * For the correctness proof below, decompose the original values of
2111 * A and B as
2112 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2113 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2114 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2115 * and gcd(A',B') is odd or 0.
2116 *
2117 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2118 * The code maintains the following invariant:
2119 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002120 */
2121
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002122 /* Proof that the loop terminates:
2123 * At each iteration, either the right-shift by 1 is made on a nonzero
2124 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2125 * by at least 1, or the right-shift by 1 is made on zero and then
2126 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2127 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2128 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002129 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002130 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002131 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2132 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002134 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2135 * TA-TB is even so the division by 2 has an integer result.
2136 * Invariant (I) is preserved since any odd divisor of both TA and TB
2137 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08002138 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002139 * divides TA.
2140 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002141 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2142 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2143 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2144 } else {
2145 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2146 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002147 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002148 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002149 }
2150
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002151 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2152 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2153 * - If there was at least one loop iteration, then one of TA or TB is odd,
2154 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2155 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2156 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002157 * 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 +02002158 */
2159
Gilles Peskine449bd832023-01-11 14:50:10 +01002160 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2161 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002162
2163cleanup:
2164
Gilles Peskine449bd832023-01-11 14:50:10 +01002165 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002166
Gilles Peskine449bd832023-01-11 14:50:10 +01002167 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002168}
2169
Paul Bakker33dc46b2014-04-30 16:11:39 +02002170/*
2171 * Fill X with size bytes of random.
Gilles Peskine22cdd0c2022-10-27 20:15:13 +02002172 * The bytes returned from the RNG are used in a specific order which
2173 * is suitable for deterministic ECDSA (see the specification of
2174 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Paul Bakker33dc46b2014-04-30 16:11:39 +02002175 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002176int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2177 int (*f_rng)(void *, unsigned char *, size_t),
2178 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002179{
Janos Follath24eed8d2019-11-22 13:21:35 +00002180 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01002181 const size_t limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002182
Gilles Peskine449bd832023-01-11 14:50:10 +01002183 MPI_VALIDATE_RET(X != NULL);
2184 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002185
Hanno Beckerda1655a2017-10-18 14:21:44 +01002186 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +01002187 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2188 if (size == 0) {
2189 return 0;
2190 }
Paul Bakker287781a2011-03-26 13:18:49 +00002191
Gilles Peskine449bd832023-01-11 14:50:10 +01002192 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002193
2194cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002195 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002196}
2197
Gilles Peskine449bd832023-01-11 14:50:10 +01002198int mbedtls_mpi_random(mbedtls_mpi *X,
2199 mbedtls_mpi_sint min,
2200 const mbedtls_mpi *N,
2201 int (*f_rng)(void *, unsigned char *, size_t),
2202 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002203{
Gilles Peskine449bd832023-01-11 14:50:10 +01002204 if (min < 0) {
2205 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2206 }
2207 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2208 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2209 }
Gilles Peskine1e918f42021-03-29 22:14:51 +02002210
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002211 /* Ensure that target MPI has exactly the same number of limbs
2212 * as the upper bound, even if the upper bound has leading zeros.
Gilles Peskine6b7ce962022-12-15 15:04:33 +01002213 * This is necessary for mbedtls_mpi_core_random. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002214 int ret = mbedtls_mpi_resize_clear(X, N->n);
2215 if (ret != 0) {
2216 return ret;
2217 }
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002218
Gilles Peskine449bd832023-01-11 14:50:10 +01002219 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002220}
2221
Paul Bakker5121ce52009-01-03 21:22:43 +00002222/*
2223 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2224 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002225int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002226{
Janos Follath24eed8d2019-11-22 13:21:35 +00002227 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine449bd832023-01-11 14:50:10 +01002229 MPI_VALIDATE_RET(X != NULL);
2230 MPI_VALIDATE_RET(A != NULL);
2231 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002232
Gilles Peskine449bd832023-01-11 14:50:10 +01002233 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2234 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2235 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002236
Gilles Peskine449bd832023-01-11 14:50:10 +01002237 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2238 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2239 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002240
Gilles Peskine449bd832023-01-11 14:50:10 +01002241 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
Gilles Peskine449bd832023-01-11 14:50:10 +01002243 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 goto cleanup;
2246 }
2247
Gilles Peskine449bd832023-01-11 14:50:10 +01002248 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2249 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2250 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2251 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
Gilles Peskine449bd832023-01-11 14:50:10 +01002253 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2254 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2255 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2256 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002257
Gilles Peskine449bd832023-01-11 14:50:10 +01002258 do {
2259 while ((TU.p[0] & 1) == 0) {
2260 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
Gilles Peskine449bd832023-01-11 14:50:10 +01002262 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2263 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2264 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 }
2266
Gilles Peskine449bd832023-01-11 14:50:10 +01002267 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2268 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 }
2270
Gilles Peskine449bd832023-01-11 14:50:10 +01002271 while ((TV.p[0] & 1) == 0) {
2272 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
Gilles Peskine449bd832023-01-11 14:50:10 +01002274 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2275 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2276 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002277 }
2278
Gilles Peskine449bd832023-01-11 14:50:10 +01002279 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2280 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 }
2282
Gilles Peskine449bd832023-01-11 14:50:10 +01002283 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2284 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2285 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2286 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2287 } else {
2288 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2289 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2290 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002291 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002292 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2293
2294 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2295 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
Gilles Peskine449bd832023-01-11 14:50:10 +01002298 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2299 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2300 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002301
Gilles Peskine449bd832023-01-11 14:50:10 +01002302 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
2304cleanup:
2305
Gilles Peskine449bd832023-01-11 14:50:10 +01002306 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2307 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2308 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002309
Gilles Peskine449bd832023-01-11 14:50:10 +01002310 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002311}
2312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002314
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002315/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
2316static const unsigned char small_prime_gaps[] = {
2317 2, 2, 4, 2, 4, 2, 4, 6,
2318 2, 6, 4, 2, 4, 6, 6, 2,
2319 6, 4, 2, 6, 4, 6, 8, 4,
2320 2, 4, 2, 4, 14, 4, 6, 2,
2321 10, 2, 6, 6, 4, 6, 6, 2,
2322 10, 2, 4, 2, 12, 12, 4, 2,
2323 4, 6, 2, 10, 6, 6, 6, 2,
2324 6, 4, 2, 10, 14, 4, 2, 4,
2325 14, 6, 10, 2, 4, 6, 8, 6,
2326 6, 4, 6, 8, 4, 8, 10, 2,
2327 10, 2, 6, 4, 6, 8, 4, 2,
2328 4, 12, 8, 4, 8, 4, 6, 12,
2329 2, 18, 6, 10, 6, 6, 2, 6,
2330 10, 6, 6, 2, 6, 6, 4, 2,
2331 12, 10, 2, 4, 6, 6, 2, 12,
2332 4, 6, 8, 10, 8, 10, 8, 6,
2333 6, 4, 8, 6, 4, 8, 4, 14,
2334 10, 12, 2, 10, 2, 4, 2, 10,
2335 14, 4, 2, 4, 14, 4, 2, 4,
2336 20, 4, 8, 10, 8, 4, 6, 6,
2337 14, 4, 6, 6, 8, 6, /*reaches 997*/
Gilles Peskine30b03782023-08-22 11:06:47 +02002338 0 /* the last entry is effectively unused */
Paul Bakker5121ce52009-01-03 21:22:43 +00002339};
2340
2341/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002342 * Small divisors test (X must be positive)
2343 *
2344 * Return values:
2345 * 0: no small factor (possible prime, more tests needed)
2346 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002348 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002349 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002350static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002351{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002352 int ret = 0;
2353 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 mbedtls_mpi_uint r;
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002355 unsigned p = 3; /* The first odd prime */
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
Gilles Peskine449bd832023-01-11 14:50:10 +01002357 if ((X->p[0] & 1) == 0) {
2358 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2359 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002361 for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
2362 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
Gilles Peskine449bd832023-01-11 14:50:10 +01002363 if (r == 0) {
Gilles Peskineb2bc1712019-02-08 17:27:11 +01002364 if (mbedtls_mpi_cmp_int(X, p) == 0) {
2365 return 1;
2366 } else {
2367 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2368 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002369 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002370 }
2371
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002372cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002373 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002374}
2375
2376/*
2377 * Miller-Rabin pseudo-primality test (HAC 4.24)
2378 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002379static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2380 int (*f_rng)(void *, unsigned char *, size_t),
2381 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002382{
Pascal Junodb99183d2015-03-11 16:49:45 +01002383 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002384 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002386
Gilles Peskine449bd832023-01-11 14:50:10 +01002387 MPI_VALIDATE_RET(X != NULL);
2388 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002389
Gilles Peskine449bd832023-01-11 14:50:10 +01002390 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2391 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2392 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002393
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 /*
2395 * W = |X| - 1
2396 * R = W >> lsb( W )
2397 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002398 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2399 s = mbedtls_mpi_lsb(&W);
2400 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2401 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
Gilles Peskine449bd832023-01-11 14:50:10 +01002403 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002404 /*
2405 * pick a random A, 1 < A < |X| - 1
2406 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002407 count = 0;
2408 do {
Gilles Peskine449bd832023-01-11 14:50:10 +01002409 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002410
Gilles Peskine449bd832023-01-11 14:50:10 +01002411 j = mbedtls_mpi_bitlen(&A);
2412 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002413 if (j > k) {
Gilles Peskine449bd832023-01-11 14:50:10 +01002414 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002415 }
2416
2417 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002418 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2419 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002420 }
2421
Gilles Peskine449bd832023-01-11 14:50:10 +01002422 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2423 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002424
2425 /*
2426 * A = A^R mod |X|
2427 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002428 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002429
Gilles Peskine449bd832023-01-11 14:50:10 +01002430 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2431 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002432 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01002433 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002434
2435 j = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002436 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002437 /*
2438 * A = A * A mod |X|
2439 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002440 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2441 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002442
Gilles Peskine449bd832023-01-11 14:50:10 +01002443 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002444 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01002445 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002446
2447 j++;
2448 }
2449
2450 /*
2451 * not prime if A != |X| - 1 or A == 1
2452 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002453 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2454 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002456 break;
2457 }
2458 }
2459
2460cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002461 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2462 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2463 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002464
Gilles Peskine449bd832023-01-11 14:50:10 +01002465 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002466}
2467
2468/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002469 * Pseudo-primality test: small factors, then Miller-Rabin
2470 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002471int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2472 int (*f_rng)(void *, unsigned char *, size_t),
2473 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002474{
Janos Follath24eed8d2019-11-22 13:21:35 +00002475 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002476 mbedtls_mpi XX;
Gilles Peskine449bd832023-01-11 14:50:10 +01002477 MPI_VALIDATE_RET(X != NULL);
2478 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002479
2480 XX.s = 1;
2481 XX.n = X->n;
2482 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002483
Gilles Peskine449bd832023-01-11 14:50:10 +01002484 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2485 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2486 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002487 }
2488
Gilles Peskine449bd832023-01-11 14:50:10 +01002489 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2490 return 0;
2491 }
2492
2493 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2494 if (ret == 1) {
2495 return 0;
2496 }
2497
2498 return ret;
2499 }
2500
2501 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002502}
2503
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002504/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002505 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002506 *
Janos Follathf301d232018-08-14 13:34:01 +01002507 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2508 * be either 1024 bits or 1536 bits long, and flags must contain
2509 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002510 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002511int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2512 int (*f_rng)(void *, unsigned char *, size_t),
2513 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002514{
Jethro Beekman66689272018-02-14 19:24:10 -08002515#ifdef MBEDTLS_HAVE_INT64
2516// ceil(2^63.5)
2517#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2518#else
2519// ceil(2^31.5)
2520#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2521#endif
2522 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002523 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002524 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 mbedtls_mpi_uint r;
2526 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002527
Gilles Peskine449bd832023-01-11 14:50:10 +01002528 MPI_VALIDATE_RET(X != NULL);
2529 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002530
Gilles Peskine449bd832023-01-11 14:50:10 +01002531 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2532 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2533 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002534
Gilles Peskine449bd832023-01-11 14:50:10 +01002535 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002536
Gilles Peskine449bd832023-01-11 14:50:10 +01002537 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002538
Gilles Peskine449bd832023-01-11 14:50:10 +01002539 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002540 /*
2541 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2542 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002543 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2544 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2545 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2546 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002547 /*
2548 * 2^-100 error probability, number of rounds computed based on HAC,
2549 * fact 4.48
2550 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002551 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2552 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2553 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2554 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002555 }
2556
Gilles Peskine449bd832023-01-11 14:50:10 +01002557 while (1) {
2558 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002559 /* 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 +01002560 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2561 continue;
2562 }
Jethro Beekman66689272018-02-14 19:24:10 -08002563
2564 k = n * biL;
Gilles Peskine449bd832023-01-11 14:50:10 +01002565 if (k > nbits) {
2566 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2567 }
Jethro Beekman66689272018-02-14 19:24:10 -08002568 X->p[0] |= 1;
2569
Gilles Peskine449bd832023-01-11 14:50:10 +01002570 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2571 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002572
Gilles Peskine449bd832023-01-11 14:50:10 +01002573 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002574 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002575 }
2576 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002577 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002578 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002579 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2580 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002581 */
Jethro Beekman66689272018-02-14 19:24:10 -08002582
2583 X->p[0] |= 2;
2584
Gilles Peskine449bd832023-01-11 14:50:10 +01002585 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2586 if (r == 0) {
2587 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2588 } else if (r == 1) {
2589 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2590 }
Jethro Beekman66689272018-02-14 19:24:10 -08002591
2592 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine449bd832023-01-11 14:50:10 +01002593 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2594 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002595
Gilles Peskine449bd832023-01-11 14:50:10 +01002596 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002597 /*
2598 * First, check small factors for X and Y
2599 * before doing Miller-Rabin on any of them
2600 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002601 if ((ret = mpi_check_small_factors(X)) == 0 &&
2602 (ret = mpi_check_small_factors(&Y)) == 0 &&
2603 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2604 == 0 &&
2605 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2606 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002607 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002608 }
Jethro Beekman66689272018-02-14 19:24:10 -08002609
Gilles Peskine449bd832023-01-11 14:50:10 +01002610 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002611 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002612 }
Jethro Beekman66689272018-02-14 19:24:10 -08002613
2614 /*
2615 * Next candidates. We want to preserve Y = (X-1) / 2 and
2616 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2617 * so up Y by 6 and X by 12.
2618 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002619 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2620 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002621 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002622 }
2623 }
2624
2625cleanup:
2626
Gilles Peskine449bd832023-01-11 14:50:10 +01002627 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002628
Gilles Peskine449bd832023-01-11 14:50:10 +01002629 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002630}
2631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002635
Paul Bakker23986e52011-04-24 08:57:21 +00002636#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002637
2638static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2639{
2640 { 693, 609, 21 },
2641 { 1764, 868, 28 },
2642 { 768454923, 542167814, 1 }
2643};
2644
Paul Bakker5121ce52009-01-03 21:22:43 +00002645/*
2646 * Checkup routine
2647 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002648int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00002649{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002650 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002651 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002652
Gilles Peskine449bd832023-01-11 14:50:10 +01002653 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2654 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Gilles Peskine449bd832023-01-11 14:50:10 +01002656 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2657 "EFE021C2645FD1DC586E69184AF4A31E" \
2658 "D5F53E93B5F123FA41680867BA110131" \
2659 "944FE7952E2517337780CB0DB80E61AA" \
2660 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
Gilles Peskine449bd832023-01-11 14:50:10 +01002662 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2663 "B2E7EFD37075B9F03FF989C7C5051C20" \
2664 "34D2A323810251127E7BF8625A4F49A5" \
2665 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2666 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002667
Gilles Peskine449bd832023-01-11 14:50:10 +01002668 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2669 "0066A198186C18C10B2F5ED9B522752A" \
2670 "9830B69916E535C8F047518A889A43A5" \
2671 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002672
Gilles Peskine449bd832023-01-11 14:50:10 +01002673 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002674
Gilles Peskine449bd832023-01-11 14:50:10 +01002675 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2676 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2677 "9E857EA95A03512E2BAE7391688D264A" \
2678 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2679 "8001B72E848A38CAE1C65F78E56ABDEF" \
2680 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2681 "ECF677152EF804370C1A305CAF3B5BF1" \
2682 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
Gilles Peskine449bd832023-01-11 14:50:10 +01002684 if (verbose != 0) {
2685 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2686 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002687
Gilles Peskine449bd832023-01-11 14:50:10 +01002688 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2689 if (verbose != 0) {
2690 mbedtls_printf("failed\n");
2691 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002692
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002693 ret = 1;
2694 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002695 }
2696
Gilles Peskine449bd832023-01-11 14:50:10 +01002697 if (verbose != 0) {
2698 mbedtls_printf("passed\n");
2699 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002700
Gilles Peskine449bd832023-01-11 14:50:10 +01002701 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002702
Gilles Peskine449bd832023-01-11 14:50:10 +01002703 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2704 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002705
Gilles Peskine449bd832023-01-11 14:50:10 +01002706 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2707 "6613F26162223DF488E9CD48CC132C7A" \
2708 "0AC93C701B001B092E4E5B9F73BCD27B" \
2709 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002710
Gilles Peskine449bd832023-01-11 14:50:10 +01002711 if (verbose != 0) {
2712 mbedtls_printf(" MPI test #2 (div_mpi): ");
2713 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002714
Gilles Peskine449bd832023-01-11 14:50:10 +01002715 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2716 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2717 if (verbose != 0) {
2718 mbedtls_printf("failed\n");
2719 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002720
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002721 ret = 1;
2722 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002723 }
2724
Gilles Peskine449bd832023-01-11 14:50:10 +01002725 if (verbose != 0) {
2726 mbedtls_printf("passed\n");
2727 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002728
Gilles Peskine449bd832023-01-11 14:50:10 +01002729 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00002730
Gilles Peskine449bd832023-01-11 14:50:10 +01002731 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2732 "36E139AEA55215609D2816998ED020BB" \
2733 "BD96C37890F65171D948E9BC7CBAA4D9" \
2734 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002735
Gilles Peskine449bd832023-01-11 14:50:10 +01002736 if (verbose != 0) {
2737 mbedtls_printf(" MPI test #3 (exp_mod): ");
2738 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002739
Gilles Peskine449bd832023-01-11 14:50:10 +01002740 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2741 if (verbose != 0) {
2742 mbedtls_printf("failed\n");
2743 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002744
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002745 ret = 1;
2746 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002747 }
2748
Gilles Peskine449bd832023-01-11 14:50:10 +01002749 if (verbose != 0) {
2750 mbedtls_printf("passed\n");
2751 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002752
Gilles Peskine449bd832023-01-11 14:50:10 +01002753 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002754
Gilles Peskine449bd832023-01-11 14:50:10 +01002755 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2756 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2757 "C3DBA76456363A10869622EAC2DD84EC" \
2758 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002759
Gilles Peskine449bd832023-01-11 14:50:10 +01002760 if (verbose != 0) {
2761 mbedtls_printf(" MPI test #4 (inv_mod): ");
2762 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002763
Gilles Peskine449bd832023-01-11 14:50:10 +01002764 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2765 if (verbose != 0) {
2766 mbedtls_printf("failed\n");
2767 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002768
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002769 ret = 1;
2770 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002771 }
2772
Gilles Peskine449bd832023-01-11 14:50:10 +01002773 if (verbose != 0) {
2774 mbedtls_printf("passed\n");
2775 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002776
Gilles Peskine449bd832023-01-11 14:50:10 +01002777 if (verbose != 0) {
2778 mbedtls_printf(" MPI test #5 (simple gcd): ");
2779 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002780
Gilles Peskine449bd832023-01-11 14:50:10 +01002781 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2782 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2783 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002784
Gilles Peskine449bd832023-01-11 14:50:10 +01002785 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002786
Gilles Peskine449bd832023-01-11 14:50:10 +01002787 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2788 if (verbose != 0) {
2789 mbedtls_printf("failed at %d\n", i);
2790 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002791
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002792 ret = 1;
2793 goto cleanup;
2794 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002795 }
2796
Gilles Peskine449bd832023-01-11 14:50:10 +01002797 if (verbose != 0) {
2798 mbedtls_printf("passed\n");
2799 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002800
Paul Bakker5121ce52009-01-03 21:22:43 +00002801cleanup:
2802
Gilles Peskine449bd832023-01-11 14:50:10 +01002803 if (ret != 0 && verbose != 0) {
2804 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2805 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002806
Gilles Peskine449bd832023-01-11 14:50:10 +01002807 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2808 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002809
Gilles Peskine449bd832023-01-11 14:50:10 +01002810 if (verbose != 0) {
2811 mbedtls_printf("\n");
2812 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002813
Gilles Peskine449bd832023-01-11 14:50:10 +01002814 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002815}
2816
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002818
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002819#endif /* MBEDTLS_BIGNUM_C */