blob: aa5f818c40d1df9b3aa2bdf4af49d189aa08e883 [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 Rodgman1a7a5622023-05-17 13:47:56 +010064 mbedtls_ct_condition_t cond, 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 /*
75 * Set sign_N to 1 if N >= 0, 0 if N < 0.
76 * 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 Rodgman1a7a5622023-05-17 13:47:56 +010086 cond = mbedtls_ct_bool_xor(X_is_negative, Y_is_negative); // non-zero if different sign
87 result = mbedtls_ct_bool_and(cond, 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 Rodgman2c764842023-05-18 13:28:21 +010097 size_t i = mbedtls_ct_size_if0(X_is_negative, 1);
98 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 /*
101 * Store in result iff the signs are the same (i.e., iff cond == false). If
102 * the signs differ, result has already been set, so we don't change it.
103 */
Dave Rodgman1a7a5622023-05-17 13:47:56 +0100104 result = mbedtls_ct_bool_or(result, mbedtls_ct_bool_and(mbedtls_ct_bool_not(cond), lt));
105
106 *ret = mbedtls_ct_uint_if0(result, 1);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100107
108 return 0;
109}
110
111/*
112 * Conditionally assign X = Y, without leaking information
113 * about whether the assignment was made or not.
114 * (Leaking information about the respective sizes of X and Y is ok however.)
115 */
116#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
117/*
118 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
119 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
120 */
121__declspec(noinline)
122#endif
123int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
124 const mbedtls_mpi *Y,
125 unsigned char assign)
126{
127 int ret = 0;
128 MPI_VALIDATE_RET(X != NULL);
129 MPI_VALIDATE_RET(Y != NULL);
130
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100131 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
132
Dave Rodgman589ccb82023-05-17 13:55:01 +0100133 mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
134
Dave Rodgman2b4486a2023-05-17 15:51:59 +0100135 X->s = (int) mbedtls_ct_uint_if(do_assign, Y->s, X->s);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100136
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100137 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100138
Dave Rodgman589ccb82023-05-17 13:55:01 +0100139 mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100140 for (size_t i = Y->n; i < X->n; i++) {
Dave Rodgman589ccb82023-05-17 13:55:01 +0100141 X->p[i] = mbedtls_ct_mpi_uint_if0(do_not_assign, X->p[i]);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100142 }
143
144cleanup:
145 return ret;
146}
147
148/*
149 * Conditionally swap X and Y, without leaking information
150 * about whether the swap was made or not.
151 * Here it is not ok to simply swap the pointers, which would lead to
152 * different memory access patterns when X and Y are used afterwards.
153 */
154int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
155 mbedtls_mpi *Y,
156 unsigned char swap)
157{
158 int ret = 0;
159 int s;
160 MPI_VALIDATE_RET(X != NULL);
161 MPI_VALIDATE_RET(Y != NULL);
162
163 if (X == Y) {
164 return 0;
165 }
166
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100167 mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
168
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100169 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
170 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
171
172 s = X->s;
Dave Rodgman2b4486a2023-05-17 15:51:59 +0100173 X->s = (int) mbedtls_ct_uint_if(do_swap, Y->s, X->s);
174 Y->s = (int) mbedtls_ct_uint_if(do_swap, s, Y->s);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100175
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100176 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100177
178cleanup:
179 return ret;
180}
181
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500182/* Implementation that should never be optimized out by the compiler */
Gilles Peskine449bd832023-01-11 14:50:10 +0100183static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -0500184{
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 mbedtls_platform_zeroize(v, ciL * n);
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500186}
187
Paul Bakker5121ce52009-01-03 21:22:43 +0000188/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000189 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000190 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100191void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000194
Paul Bakker6c591fa2011-05-05 11:49:20 +0000195 X->s = 1;
196 X->n = 0;
197 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000198}
199
200/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000201 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000202 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100203void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000204{
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +0000206 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 if (X->p != NULL) {
210 mbedtls_mpi_zeroize(X->p, X->n);
211 mbedtls_free(X->p);
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);
238 mbedtls_mpi_zeroize(X->p, X->n);
239 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000240 }
241
242 X->n = nblimbs;
243 X->p = p;
244 }
245
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000247}
248
249/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100250 * Resize down as much as possible,
251 * while keeping at least the specified number of limbs
252 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100253int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100254{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100256 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000258
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
260 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
261 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100262
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100263 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 if (X->n <= nblimbs) {
265 return mbedtls_mpi_grow(X, nblimbs);
266 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100267 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 for (i = X->n - 1; i > 0; i--) {
270 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100271 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 }
273 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100274 i++;
275
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100277 i = nblimbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100279
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
281 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
282 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 if (X->p != NULL) {
285 memcpy(p, X->p, i * ciL);
286 mbedtls_mpi_zeroize(X->p, X->n);
287 mbedtls_free(X->p);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100288 }
289
290 X->n = i;
291 X->p = p;
292
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100294}
295
Gilles Peskineed32b572021-06-02 22:17:52 +0200296/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100297static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200298{
Gilles Peskine449bd832023-01-11 14:50:10 +0100299 if (limbs == 0) {
300 mbedtls_mpi_free(X);
301 return 0;
302 } else if (X->n == limbs) {
303 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200304 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 return 0;
306 } else {
307 mbedtls_mpi_free(X);
308 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200309 }
310}
311
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100312/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200313 * Copy the contents of Y into X.
314 *
315 * This function is not constant-time. Leading zeros in Y may be removed.
316 *
317 * Ensure that X does not shrink. This is not guaranteed by the public API,
318 * but some code in the bignum module relies on this property, for example
319 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000320 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100321int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000322{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100323 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000324 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 MPI_VALIDATE_RET(X != NULL);
326 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000327
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 if (X == Y) {
329 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200330 }
331
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 if (Y->n == 0) {
333 if (X->n != 0) {
334 X->s = 1;
335 memset(X->p, 0, X->n * ciL);
336 }
337 return 0;
338 }
339
340 for (i = Y->n - 1; i > 0; i--) {
341 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000342 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 }
344 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000345 i++;
346
347 X->s = Y->s;
348
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 if (X->n < i) {
350 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
351 } else {
352 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100353 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000354
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
357cleanup:
358
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000360}
361
362/*
363 * Swap the contents of X and Y
364 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100365void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000366{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 MPI_VALIDATE(X != NULL);
369 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000370
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 memcpy(&T, X, sizeof(mbedtls_mpi));
372 memcpy(X, Y, sizeof(mbedtls_mpi));
373 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000374}
375
Gilles Peskine449bd832023-01-11 14:50:10 +0100376static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100377{
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 if (z >= 0) {
379 return z;
380 }
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100381 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
382 * A naive -z would have undefined behavior.
383 * Write this in a way that makes popular compilers happy (GCC, Clang,
384 * MSVC). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100385 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100386}
387
Paul Bakker5121ce52009-01-03 21:22:43 +0000388/*
389 * Set value from integer
390 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100391int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000392{
Janos Follath24eed8d2019-11-22 13:21:35 +0000393 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000395
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
397 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 X->p[0] = mpi_sint_abs(z);
400 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
402cleanup:
403
Gilles Peskine449bd832023-01-11 14:50:10 +0100404 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000405}
406
407/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000408 * Get a specific bit
409 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100410int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000411{
Gilles Peskine449bd832023-01-11 14:50:10 +0100412 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000413
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 if (X->n * biL <= pos) {
415 return 0;
416 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000417
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000419}
420
421/*
422 * Set a bit to a specific value of 0 or 1
423 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100424int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000425{
426 int ret = 0;
427 size_t off = pos / biL;
428 size_t idx = pos % biL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000430
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 if (val != 0 && val != 1) {
432 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000433 }
434
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 if (X->n * biL <= pos) {
436 if (val == 0) {
437 return 0;
438 }
439
440 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
441 }
442
443 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000445
446cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200447
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000449}
450
451/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200452 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000453 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100454size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000455{
Paul Bakker23986e52011-04-24 08:57:21 +0000456 size_t i, j, count = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100457 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 for (i = 0; i < X->n; i++) {
460 for (j = 0; j < biL; j++, count++) {
461 if (((X->p[i] >> j) & 1) != 0) {
462 return count;
463 }
464 }
465 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000468}
469
470/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200471 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000472 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100473size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000474{
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 return mbedtls_mpi_core_bitlen(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000476}
477
478/*
479 * Return the total size in bytes
480 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100481size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000482{
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000484}
485
486/*
487 * Convert an ASCII character to digit value
488 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100489static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000490{
491 *d = 255;
492
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 if (c >= 0x30 && c <= 0x39) {
494 *d = c - 0x30;
495 }
496 if (c >= 0x41 && c <= 0x46) {
497 *d = c - 0x37;
498 }
499 if (c >= 0x61 && c <= 0x66) {
500 *d = c - 0x57;
501 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000502
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 if (*d >= (mbedtls_mpi_uint) radix) {
504 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
505 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000508}
509
510/*
511 * Import from an ASCII string
512 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100513int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000514{
Janos Follath24eed8d2019-11-22 13:21:35 +0000515 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000516 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200517 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 mbedtls_mpi_uint d;
519 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 MPI_VALIDATE_RET(X != NULL);
521 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
Gilles Peskine449bd832023-01-11 14:50:10 +0100523 if (radix < 2 || radix > 16) {
524 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200525 }
526
Gilles Peskine449bd832023-01-11 14:50:10 +0100527 mbedtls_mpi_init(&T);
528
529 if (s[0] == 0) {
530 mbedtls_mpi_free(X);
531 return 0;
532 }
533
534 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200535 ++s;
536 sign = -1;
537 }
538
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000540
Gilles Peskine449bd832023-01-11 14:50:10 +0100541 if (radix == 16) {
Dave Rodgman68ef1d62023-05-18 20:49:03 +0100542 if (slen > SIZE_MAX >> 2) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100543 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000544 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000545
Gilles Peskine449bd832023-01-11 14:50:10 +0100546 n = BITS_TO_LIMBS(slen << 2);
547
548 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
549 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
550
551 for (i = slen, j = 0; i > 0; i--, j++) {
552 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
553 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
554 }
555 } else {
556 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
557
558 for (i = 0; i < slen; i++) {
559 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
560 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
561 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000562 }
563 }
564
Gilles Peskine449bd832023-01-11 14:50:10 +0100565 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200566 X->s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100567 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200568
Paul Bakker5121ce52009-01-03 21:22:43 +0000569cleanup:
570
Gilles Peskine449bd832023-01-11 14:50:10 +0100571 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000572
Gilles Peskine449bd832023-01-11 14:50:10 +0100573 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000574}
575
576/*
Ron Eldora16fa292018-11-20 14:07:01 +0200577 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100579static int mpi_write_hlp(mbedtls_mpi *X, int radix,
580 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000581{
Janos Follath24eed8d2019-11-22 13:21:35 +0000582 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200584 size_t length = 0;
585 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000586
Gilles Peskine449bd832023-01-11 14:50:10 +0100587 do {
588 if (length >= buflen) {
589 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200590 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
593 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200594 /*
595 * Write the residue in the current position, as an ASCII character.
596 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 if (r < 0xA) {
598 *(--p_end) = (char) ('0' + r);
599 } else {
600 *(--p_end) = (char) ('A' + (r - 0xA));
601 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000602
Ron Eldora16fa292018-11-20 14:07:01 +0200603 length++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100604 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200607 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
609cleanup:
610
Gilles Peskine449bd832023-01-11 14:50:10 +0100611 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000612}
613
614/*
615 * Export into an ASCII string
616 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100617int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
618 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000619{
Paul Bakker23986e52011-04-24 08:57:21 +0000620 int ret = 0;
621 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000622 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100624 MPI_VALIDATE_RET(X != NULL);
625 MPI_VALIDATE_RET(olen != NULL);
626 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 if (radix < 2 || radix > 16) {
629 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
630 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
Gilles Peskine449bd832023-01-11 14:50:10 +0100632 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
633 if (radix >= 4) {
634 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000635 * `n`. If radix > 4, this might be a strict
636 * overapproximation of the number of
637 * radix-adic digits needed to present `n`. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100638 }
639 if (radix >= 16) {
640 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000641 * present `n`. */
642
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 }
Janos Follath80470622019-03-06 13:43:02 +0000644 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000645 n += 1; /* Compensate for the divisions above, which round down `n`
646 * in case it's not even. */
647 n += 1; /* Potential '-'-sign. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100648 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000649 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
Gilles Peskine449bd832023-01-11 14:50:10 +0100651 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100652 *olen = n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 }
655
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100656 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100657 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
Gilles Peskine449bd832023-01-11 14:50:10 +0100659 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000661 buflen--;
662 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
Gilles Peskine449bd832023-01-11 14:50:10 +0100664 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000665 int c;
666 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 for (i = X->n, k = 0; i > 0; i--) {
669 for (j = ciL; j > 0; j--) {
670 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
Gilles Peskine449bd832023-01-11 14:50:10 +0100672 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000673 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100674 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000675
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000676 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000677 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000678 k = 1;
679 }
680 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100681 } else {
682 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000683
Gilles Peskine449bd832023-01-11 14:50:10 +0100684 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000685 T.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100686 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000687
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 }
690
691 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100692 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
694cleanup:
695
Gilles Peskine449bd832023-01-11 14:50:10 +0100696 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
Gilles Peskine449bd832023-01-11 14:50:10 +0100698 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000699}
700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000702/*
703 * Read X from an opened file
704 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100705int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000706{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000708 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000709 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000710 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000711 * Buffer should have space for (short) label and decimal formatted MPI,
712 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000713 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 MPI_VALIDATE_RET(X != NULL);
717 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000718
Gilles Peskine449bd832023-01-11 14:50:10 +0100719 if (radix < 2 || radix > 16) {
720 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
721 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000722
Gilles Peskine449bd832023-01-11 14:50:10 +0100723 memset(s, 0, sizeof(s));
724 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
725 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
726 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000727
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 slen = strlen(s);
729 if (slen == sizeof(s) - 2) {
730 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
731 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000732
Gilles Peskine449bd832023-01-11 14:50:10 +0100733 if (slen > 0 && s[slen - 1] == '\n') {
734 slen--; s[slen] = '\0';
735 }
736 if (slen > 0 && s[slen - 1] == '\r') {
737 slen--; s[slen] = '\0';
738 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
740 p = s + slen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100741 while (p-- > s) {
742 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000743 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100744 }
745 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000746
Gilles Peskine449bd832023-01-11 14:50:10 +0100747 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000748}
749
750/*
751 * Write X into an opened file (or stdout if fout == NULL)
752 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100753int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000754{
Janos Follath24eed8d2019-11-22 13:21:35 +0000755 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000756 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000757 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000758 * Buffer should have space for (short) label and decimal formatted MPI,
759 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000760 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100761 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
762 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000763
Gilles Peskine449bd832023-01-11 14:50:10 +0100764 if (radix < 2 || radix > 16) {
765 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
766 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000767
Gilles Peskine449bd832023-01-11 14:50:10 +0100768 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000769
Gilles Peskine449bd832023-01-11 14:50:10 +0100770 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000771
Gilles Peskine449bd832023-01-11 14:50:10 +0100772 if (p == NULL) {
773 p = "";
774 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000775
Gilles Peskine449bd832023-01-11 14:50:10 +0100776 plen = strlen(p);
777 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000778 s[slen++] = '\r';
779 s[slen++] = '\n';
780
Gilles Peskine449bd832023-01-11 14:50:10 +0100781 if (fout != NULL) {
782 if (fwrite(p, 1, plen, fout) != plen ||
783 fwrite(s, 1, slen, fout) != slen) {
784 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
785 }
786 } else {
787 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000788 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000789
790cleanup:
791
Gilles Peskine449bd832023-01-11 14:50:10 +0100792 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000793}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200794#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000795
796/*
Janos Follatha778a942019-02-13 10:28:28 +0000797 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100798 *
799 * This function is guaranteed to return an MPI with exactly the necessary
800 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000801 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100802int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
803 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000804{
Janos Follath24eed8d2019-11-22 13:21:35 +0000805 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100806 const size_t limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000807
808 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100809 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000810
Gilles Peskine449bd832023-01-11 14:50:10 +0100811 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Janos Follatha778a942019-02-13 10:28:28 +0000812
813cleanup:
814
Janos Follath171a7ef2019-02-15 16:17:45 +0000815 /*
816 * This function is also used to import keys. However, wiping the buffers
817 * upon failure is not necessary because failure only can happen before any
818 * input is copied.
819 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100820 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000821}
822
823/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000824 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100825 *
826 * This function is guaranteed to return an MPI with exactly the necessary
827 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100829int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000830{
Janos Follath24eed8d2019-11-22 13:21:35 +0000831 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100832 const size_t limbs = CHARS_TO_LIMBS(buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000833
Gilles Peskine449bd832023-01-11 14:50:10 +0100834 MPI_VALIDATE_RET(X != NULL);
835 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000836
Hanno Becker073c1992017-10-17 15:17:27 +0100837 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100838 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000839
Gilles Peskine449bd832023-01-11 14:50:10 +0100840 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000841
842cleanup:
843
Janos Follath171a7ef2019-02-15 16:17:45 +0000844 /*
845 * This function is also used to import keys. However, wiping the buffers
846 * upon failure is not necessary because failure only can happen before any
847 * input is copied.
848 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100849 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000850}
851
852/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000853 * Export X into unsigned binary data, little endian
854 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100855int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
856 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000857{
Gilles Peskine449bd832023-01-11 14:50:10 +0100858 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Janos Follathe344d0f2019-02-19 16:17:40 +0000859}
860
861/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000862 * Export X into unsigned binary data, big endian
863 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100864int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
865 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000866{
Gilles Peskine449bd832023-01-11 14:50:10 +0100867 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000868}
869
870/*
871 * Left-shift: X <<= count
872 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100873int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000874{
Janos Follath24eed8d2019-11-22 13:21:35 +0000875 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Minos Galanakis0144b352023-05-02 14:02:32 +0100876 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100877 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000878
Gilles Peskine449bd832023-01-11 14:50:10 +0100879 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000880
Gilles Peskine449bd832023-01-11 14:50:10 +0100881 if (X->n * biL < i) {
882 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
883 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000884
885 ret = 0;
886
Minos Galanakis0144b352023-05-02 14:02:32 +0100887 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Paul Bakker5121ce52009-01-03 21:22:43 +0000888cleanup:
889
Gilles Peskine449bd832023-01-11 14:50:10 +0100890 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000891}
892
893/*
894 * Right-shift: X >>= count
895 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100896int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000897{
Gilles Peskine449bd832023-01-11 14:50:10 +0100898 MPI_VALIDATE_RET(X != NULL);
899 if (X->n != 0) {
900 mbedtls_mpi_core_shift_r(X->p, X->n, count);
901 }
902 return 0;
Gilles Peskine66414202022-09-21 15:36:16 +0200903}
904
Paul Bakker5121ce52009-01-03 21:22:43 +0000905/*
906 * Compare unsigned values
907 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100908int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000909{
Paul Bakker23986e52011-04-24 08:57:21 +0000910 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100911 MPI_VALIDATE_RET(X != NULL);
912 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000913
Gilles Peskine449bd832023-01-11 14:50:10 +0100914 for (i = X->n; i > 0; i--) {
915 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000916 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100917 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000918 }
919
Gilles Peskine449bd832023-01-11 14:50:10 +0100920 for (j = Y->n; j > 0; j--) {
921 if (Y->p[j - 1] != 0) {
922 break;
923 }
924 }
925
926 if (i == 0 && j == 0) {
927 return 0;
928 }
929
930 if (i > j) {
931 return 1;
932 }
933 if (j > i) {
934 return -1;
935 }
936
937 for (; i > 0; i--) {
938 if (X->p[i - 1] > Y->p[i - 1]) {
939 return 1;
940 }
941 if (X->p[i - 1] < Y->p[i - 1]) {
942 return -1;
943 }
944 }
945
946 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000947}
948
949/*
950 * Compare signed values
951 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100952int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000953{
Paul Bakker23986e52011-04-24 08:57:21 +0000954 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100955 MPI_VALIDATE_RET(X != NULL);
956 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000957
Gilles Peskine449bd832023-01-11 14:50:10 +0100958 for (i = X->n; i > 0; i--) {
959 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000960 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100961 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000962 }
963
Gilles Peskine449bd832023-01-11 14:50:10 +0100964 for (j = Y->n; j > 0; j--) {
965 if (Y->p[j - 1] != 0) {
966 break;
967 }
968 }
969
970 if (i == 0 && j == 0) {
971 return 0;
972 }
973
974 if (i > j) {
975 return X->s;
976 }
977 if (j > i) {
978 return -Y->s;
979 }
980
981 if (X->s > 0 && Y->s < 0) {
982 return 1;
983 }
984 if (Y->s > 0 && X->s < 0) {
985 return -1;
986 }
987
988 for (; i > 0; i--) {
989 if (X->p[i - 1] > Y->p[i - 1]) {
990 return X->s;
991 }
992 if (X->p[i - 1] < Y->p[i - 1]) {
993 return -X->s;
994 }
995 }
996
997 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000998}
999
Janos Follathee6abce2019-09-05 14:47:19 +01001000/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 * Compare signed values
1002 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001003int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +00001004{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001005 mbedtls_mpi Y;
1006 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001007 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001008
Gilles Peskine449bd832023-01-11 14:50:10 +01001009 *p = mpi_sint_abs(z);
1010 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001011 Y.n = 1;
1012 Y.p = p;
1013
Gilles Peskine449bd832023-01-11 14:50:10 +01001014 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00001015}
1016
1017/*
1018 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1019 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001020int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001021{
Janos Follath24eed8d2019-11-22 13:21:35 +00001022 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001023 size_t j;
Gilles Peskine449bd832023-01-11 14:50:10 +01001024 MPI_VALIDATE_RET(X != NULL);
1025 MPI_VALIDATE_RET(A != NULL);
1026 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001027
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001029 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 }
1031
Gilles Peskine449bd832023-01-11 14:50:10 +01001032 if (X != A) {
1033 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1034 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001035
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001036 /*
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001037 * X must always be positive as a result of unsigned additions.
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001038 */
1039 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001040
Gilles Peskine449bd832023-01-11 14:50:10 +01001041 for (j = B->n; j > 0; j--) {
1042 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001044 }
1045 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001046
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001047 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1048 * and B is 0 (of any size). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001049 if (j == 0) {
1050 return 0;
1051 }
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001052
Gilles Peskine449bd832023-01-11 14:50:10 +01001053 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001055 /* j is the number of non-zero limbs of B. Add those to X. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001056
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001057 mbedtls_mpi_uint *p = X->p;
1058
Gilles Peskine449bd832023-01-11 14:50:10 +01001059 mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j);
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001060
1061 p += j;
1062
1063 /* Now propagate any carry */
Paul Bakker5121ce52009-01-03 21:22:43 +00001064
Gilles Peskine449bd832023-01-11 14:50:10 +01001065 while (c != 0) {
1066 if (j >= X->n) {
1067 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001068 p = X->p + j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 }
1070
Gilles Peskine449bd832023-01-11 14:50:10 +01001071 *p += c; c = (*p < c); j++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001072 }
1073
1074cleanup:
1075
Gilles Peskine449bd832023-01-11 14:50:10 +01001076 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001077}
1078
Paul Bakker5121ce52009-01-03 21:22:43 +00001079/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001080 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001082int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001083{
Janos Follath24eed8d2019-11-22 13:21:35 +00001084 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001085 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001086 mbedtls_mpi_uint carry;
Gilles Peskine449bd832023-01-11 14:50:10 +01001087 MPI_VALIDATE_RET(X != NULL);
1088 MPI_VALIDATE_RET(A != NULL);
1089 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001090
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 for (n = B->n; n > 0; n--) {
1092 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001094 }
1095 }
1096 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001097 /* B >= (2^ciL)^n > A */
1098 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1099 goto cleanup;
1100 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001101
Gilles Peskine449bd832023-01-11 14:50:10 +01001102 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001103
1104 /* Set the high limbs of X to match A. Don't touch the lower limbs
1105 * because X might be aliased to B, and we must not overwrite the
1106 * significant digits of B. */
Aaron M. Uckoaf67d2c2023-01-17 11:52:22 -05001107 if (A->n > n && A != X) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1109 }
1110 if (X->n > A->n) {
1111 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1112 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001113
Gilles Peskine449bd832023-01-11 14:50:10 +01001114 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1115 if (carry != 0) {
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001116 /* Propagate the carry through the rest of X. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001117 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001118
1119 /* If we have further carry/borrow, the result is negative. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001120 if (carry != 0) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001121 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1122 goto cleanup;
1123 }
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001124 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001125
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001126 /* X should always be positive as a result of unsigned subtractions. */
1127 X->s = 1;
1128
Paul Bakker5121ce52009-01-03 21:22:43 +00001129cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001130 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001131}
1132
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001133/* Common function for signed addition and subtraction.
1134 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001135 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001136static int add_sub_mpi(mbedtls_mpi *X,
1137 const mbedtls_mpi *A, const mbedtls_mpi *B,
1138 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001139{
Hanno Becker73d7d792018-12-11 10:35:51 +00001140 int ret, s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001141 MPI_VALIDATE_RET(X != NULL);
1142 MPI_VALIDATE_RET(A != NULL);
1143 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001144
Hanno Becker73d7d792018-12-11 10:35:51 +00001145 s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001146 if (A->s * B->s * flip_B < 0) {
1147 int cmp = mbedtls_mpi_cmp_abs(A, B);
1148 if (cmp >= 0) {
1149 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001150 /* If |A| = |B|, the result is 0 and we must set the sign bit
1151 * to +1 regardless of which of A or B was negative. Otherwise,
1152 * since |A| > |B|, the sign is the sign of A. */
1153 X->s = cmp == 0 ? 1 : s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001154 } else {
1155 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001156 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001157 X->s = -s;
1158 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001159 } else {
1160 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 X->s = s;
1162 }
1163
1164cleanup:
1165
Gilles Peskine449bd832023-01-11 14:50:10 +01001166 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001167}
1168
1169/*
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001170 * Signed addition: X = A + B
1171 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001172int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001173{
Gilles Peskine449bd832023-01-11 14:50:10 +01001174 return add_sub_mpi(X, A, B, 1);
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001175}
1176
1177/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001178 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001179 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001180int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001181{
Gilles Peskine449bd832023-01-11 14:50:10 +01001182 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001183}
1184
1185/*
1186 * Signed addition: X = A + b
1187 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001188int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001189{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001190 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001192 MPI_VALIDATE_RET(X != NULL);
1193 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
Gilles Peskine449bd832023-01-11 14:50:10 +01001195 p[0] = mpi_sint_abs(b);
1196 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001197 B.n = 1;
1198 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001199
Gilles Peskine449bd832023-01-11 14:50:10 +01001200 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001201}
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_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001207{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001208 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001209 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001210 MPI_VALIDATE_RET(X != NULL);
1211 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001212
Gilles Peskine449bd832023-01-11 14:50:10 +01001213 p[0] = mpi_sint_abs(b);
1214 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001215 B.n = 1;
1216 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001217
Gilles Peskine449bd832023-01-11 14:50:10 +01001218 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001219}
1220
Paul Bakker5121ce52009-01-03 21:22:43 +00001221/*
1222 * Baseline multiplication: X = A * B (HAC 14.12)
1223 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001224int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001225{
Janos Follath24eed8d2019-11-22 13:21:35 +00001226 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001227 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001228 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001229 int result_is_zero = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001230 MPI_VALIDATE_RET(X != NULL);
1231 MPI_VALIDATE_RET(A != NULL);
1232 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001233
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001234 mbedtls_mpi_init(&TA);
1235 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001236
Gilles Peskine449bd832023-01-11 14:50:10 +01001237 if (X == A) {
1238 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1239 }
1240 if (X == B) {
1241 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1242 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001243
Gilles Peskine449bd832023-01-11 14:50:10 +01001244 for (i = A->n; i > 0; i--) {
1245 if (A->p[i - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001246 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001247 }
1248 }
1249 if (i == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001250 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001251 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001252
Gilles Peskine449bd832023-01-11 14:50:10 +01001253 for (j = B->n; j > 0; j--) {
1254 if (B->p[j - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001255 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001256 }
1257 }
1258 if (j == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001259 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001260 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001261
Gilles Peskine449bd832023-01-11 14:50:10 +01001262 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1263 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001264
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001265 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
Hanno Beckerda763de2022-04-13 06:50:02 +01001267 /* If the result is 0, we don't shortcut the operation, which reduces
1268 * but does not eliminate side channels leaking the zero-ness. We do
1269 * need to take care to set the sign bit properly since the library does
1270 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001271 if (result_is_zero) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001272 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001273 } else {
Hanno Beckerda763de2022-04-13 06:50:02 +01001274 X->s = A->s * B->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001275 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001276
1277cleanup:
1278
Gilles Peskine449bd832023-01-11 14:50:10 +01001279 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001280
Gilles Peskine449bd832023-01-11 14:50:10 +01001281 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001282}
1283
1284/*
1285 * Baseline multiplication: X = A * b
1286 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001287int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001288{
Gilles Peskine449bd832023-01-11 14:50:10 +01001289 MPI_VALIDATE_RET(X != NULL);
1290 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001291
Hanno Becker35771312022-04-14 11:52:11 +01001292 size_t n = A->n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001293 while (n > 0 && A->p[n - 1] == 0) {
Hanno Becker35771312022-04-14 11:52:11 +01001294 --n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001295 }
Hanno Becker35771312022-04-14 11:52:11 +01001296
Hanno Becker74a11a32022-04-06 06:27:00 +01001297 /* The general method below doesn't work if b==0. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001298 if (b == 0 || n == 0) {
1299 return mbedtls_mpi_lset(X, 0);
1300 }
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001301
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001302 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001303 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001304 /* In general, A * b requires 1 limb more than b. If
1305 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1306 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001307 * copy() will take care of the growth if needed. However, experimentally,
1308 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001309 * calls to calloc() in ECP code, presumably because it reuses the
1310 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001311 * grow to its final size.
1312 *
1313 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1314 * A,X can be the same. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001315 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1316 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1317 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001318
1319cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001320 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001321}
1322
1323/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001324 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1325 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001326 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001327static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1328 mbedtls_mpi_uint u0,
1329 mbedtls_mpi_uint d,
1330 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001331{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001332#if defined(MBEDTLS_HAVE_UDBL)
1333 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001334#else
Simon Butcher9803d072016-01-03 00:24:34 +00001335 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001336 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001337 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1338 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001339 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001340#endif
1341
Simon Butcher15b15d12015-11-26 19:35:03 +00001342 /*
1343 * Check for overflow
1344 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001345 if (0 == d || u1 >= d) {
1346 if (r != NULL) {
1347 *r = ~(mbedtls_mpi_uint) 0u;
1348 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001349
Gilles Peskine449bd832023-01-11 14:50:10 +01001350 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001351 }
1352
1353#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001354 dividend = (mbedtls_t_udbl) u1 << biL;
1355 dividend |= (mbedtls_t_udbl) u0;
1356 quotient = dividend / d;
Gilles Peskine449bd832023-01-11 14:50:10 +01001357 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1358 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1359 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001360
Gilles Peskine449bd832023-01-11 14:50:10 +01001361 if (r != NULL) {
1362 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1363 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001364
1365 return (mbedtls_mpi_uint) quotient;
1366#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001367
1368 /*
1369 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1370 * Vol. 2 - Seminumerical Algorithms, Knuth
1371 */
1372
1373 /*
1374 * Normalize the divisor, d, and dividend, u0, u1
1375 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001376 s = mbedtls_mpi_core_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001377 d = d << s;
1378
1379 u1 = u1 << s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001380 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001381 u0 = u0 << s;
1382
1383 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001384 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001385
1386 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001387 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001388
1389 /*
1390 * Find the first quotient and remainder
1391 */
1392 q1 = u1 / d1;
1393 r0 = u1 - d1 * q1;
1394
Gilles Peskine449bd832023-01-11 14:50:10 +01001395 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001396 q1 -= 1;
1397 r0 += d1;
1398
Gilles Peskine449bd832023-01-11 14:50:10 +01001399 if (r0 >= radix) {
1400 break;
1401 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001402 }
1403
Gilles Peskine449bd832023-01-11 14:50:10 +01001404 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001405 q0 = rAX / d1;
1406 r0 = rAX - q0 * d1;
1407
Gilles Peskine449bd832023-01-11 14:50:10 +01001408 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001409 q0 -= 1;
1410 r0 += d1;
1411
Gilles Peskine449bd832023-01-11 14:50:10 +01001412 if (r0 >= radix) {
1413 break;
1414 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001415 }
1416
Gilles Peskine449bd832023-01-11 14:50:10 +01001417 if (r != NULL) {
1418 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1419 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001420
1421 quotient = q1 * radix + q0;
1422
1423 return quotient;
1424#endif
1425}
1426
1427/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001429 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001430int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1431 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001432{
Janos Follath24eed8d2019-11-22 13:21:35 +00001433 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001434 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001436 mbedtls_mpi_uint TP2[3];
Gilles Peskine449bd832023-01-11 14:50:10 +01001437 MPI_VALIDATE_RET(A != NULL);
1438 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001439
Gilles Peskine449bd832023-01-11 14:50:10 +01001440 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1441 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1442 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001443
Gilles Peskine449bd832023-01-11 14:50:10 +01001444 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1445 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001446 /*
1447 * Avoid dynamic memory allocations for constant-size T2.
1448 *
1449 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1450 * so nobody increase the size of the MPI and we're safe to use an on-stack
1451 * buffer.
1452 */
Alexander K35d6d462019-10-31 14:46:45 +03001453 T2.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001454 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001455 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001456
Gilles Peskine449bd832023-01-11 14:50:10 +01001457 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1458 if (Q != NULL) {
1459 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1460 }
1461 if (R != NULL) {
1462 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1463 }
1464 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001465 }
1466
Gilles Peskine449bd832023-01-11 14:50:10 +01001467 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1468 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001469 X.s = Y.s = 1;
1470
Gilles Peskine449bd832023-01-11 14:50:10 +01001471 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1472 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1473 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001474
Gilles Peskine449bd832023-01-11 14:50:10 +01001475 k = mbedtls_mpi_bitlen(&Y) % biL;
1476 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001477 k = biL - 1 - k;
Gilles Peskine449bd832023-01-11 14:50:10 +01001478 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1479 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1480 } else {
1481 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
1484 n = X.n - 1;
1485 t = Y.n - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001486 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
Gilles Peskine449bd832023-01-11 14:50:10 +01001488 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001489 Z.p[n - t]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001490 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001491 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001492 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001493
Gilles Peskine449bd832023-01-11 14:50:10 +01001494 for (i = n; i > t; i--) {
1495 if (X.p[i] >= Y.p[t]) {
1496 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1497 } else {
1498 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1499 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 }
1501
Gilles Peskine449bd832023-01-11 14:50:10 +01001502 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1503 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001504 T2.p[2] = X.p[i];
1505
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 Z.p[i - t - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001507 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 Z.p[i - t - 1]--;
1509
Gilles Peskine449bd832023-01-11 14:50:10 +01001510 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1511 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001512 T1.p[1] = Y.p[t];
Gilles Peskine449bd832023-01-11 14:50:10 +01001513 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1514 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001515
Gilles Peskine449bd832023-01-11 14:50:10 +01001516 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1517 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1518 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001519
Gilles Peskine449bd832023-01-11 14:50:10 +01001520 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1521 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1522 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1523 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001524 Z.p[i - t - 1]--;
1525 }
1526 }
1527
Gilles Peskine449bd832023-01-11 14:50:10 +01001528 if (Q != NULL) {
1529 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001530 Q->s = A->s * B->s;
1531 }
1532
Gilles Peskine449bd832023-01-11 14:50:10 +01001533 if (R != NULL) {
1534 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001535 X.s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001536 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
Gilles Peskine449bd832023-01-11 14:50:10 +01001538 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001539 R->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001540 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001541 }
1542
1543cleanup:
1544
Gilles Peskine449bd832023-01-11 14:50:10 +01001545 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1546 mbedtls_mpi_free(&T1);
1547 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001548
Gilles Peskine449bd832023-01-11 14:50:10 +01001549 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001550}
1551
1552/*
1553 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001554 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001555int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1556 const mbedtls_mpi *A,
1557 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001558{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001559 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001561 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001562
Gilles Peskine449bd832023-01-11 14:50:10 +01001563 p[0] = mpi_sint_abs(b);
1564 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001565 B.n = 1;
1566 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001567
Gilles Peskine449bd832023-01-11 14:50:10 +01001568 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001569}
1570
1571/*
1572 * Modulo: R = A mod B
1573 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001574int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001575{
Janos Follath24eed8d2019-11-22 13:21:35 +00001576 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01001577 MPI_VALIDATE_RET(R != NULL);
1578 MPI_VALIDATE_RET(A != NULL);
1579 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
Gilles Peskine449bd832023-01-11 14:50:10 +01001581 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1582 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1583 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001584
Gilles Peskine449bd832023-01-11 14:50:10 +01001585 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001586
Gilles Peskine449bd832023-01-11 14:50:10 +01001587 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1588 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1589 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001590
Gilles Peskine449bd832023-01-11 14:50:10 +01001591 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1592 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1593 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001594
1595cleanup:
1596
Gilles Peskine449bd832023-01-11 14:50:10 +01001597 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001598}
1599
1600/*
1601 * Modulo: r = A mod b
1602 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001603int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001604{
Paul Bakker23986e52011-04-24 08:57:21 +00001605 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 mbedtls_mpi_uint x, y, z;
Gilles Peskine449bd832023-01-11 14:50:10 +01001607 MPI_VALIDATE_RET(r != NULL);
1608 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
Gilles Peskine449bd832023-01-11 14:50:10 +01001610 if (b == 0) {
1611 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1612 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001613
Gilles Peskine449bd832023-01-11 14:50:10 +01001614 if (b < 0) {
1615 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1616 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
1618 /*
1619 * handle trivial cases
1620 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001621 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001622 *r = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001623 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001624 }
1625
Gilles Peskine449bd832023-01-11 14:50:10 +01001626 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001627 *r = A->p[0] & 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001628 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001629 }
1630
1631 /*
1632 * general case
1633 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001634 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001635 x = A->p[i - 1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001636 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001637 z = y / b;
1638 y -= z * b;
1639
1640 x <<= biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001641 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001642 z = y / b;
1643 y -= z * b;
1644 }
1645
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001646 /*
1647 * If A is negative, then the current y represents a negative value.
1648 * Flipping it to the positive side.
1649 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001650 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001651 y = b - y;
Gilles Peskine449bd832023-01-11 14:50:10 +01001652 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001653
Paul Bakker5121ce52009-01-03 21:22:43 +00001654 *r = y;
1655
Gilles Peskine449bd832023-01-11 14:50:10 +01001656 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001657}
1658
Gilles Peskine449bd832023-01-11 14:50:10 +01001659static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001660{
Gilles Peskine449bd832023-01-11 14:50:10 +01001661 *mm = mbedtls_mpi_core_montmul_init(N->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001662}
1663
Tom Cosgrove93842842022-08-05 16:59:43 +01001664/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1665 *
1666 * \param[in,out] A One of the numbers to multiply.
1667 * It must have at least as many limbs as N
1668 * (A->n >= N->n), and any limbs beyond n are ignored.
1669 * On successful completion, A contains the result of
1670 * the multiplication A * B * R^-1 mod N where
1671 * R = (2^ciL)^n.
1672 * \param[in] B One of the numbers to multiply.
1673 * It must be nonzero and must not have more limbs than N
1674 * (B->n <= N->n).
Tom Cosgrove40d22942022-08-17 06:42:44 +01001675 * \param[in] N The modulus. \p N must be odd.
Tom Cosgrove93842842022-08-05 16:59:43 +01001676 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1677 * This is -N^-1 mod 2^ciL.
1678 * \param[in,out] T A bignum for temporary storage.
1679 * It must be at least twice the limb size of N plus 1
1680 * (T->n >= 2 * N->n + 1).
1681 * Its initial content is unused and
1682 * its final content is indeterminate.
Tom Cosgrove5dd97e62022-08-30 14:31:49 +01001683 * It does not get reallocated.
Tom Cosgrove93842842022-08-05 16:59:43 +01001684 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001685static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1686 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1687 mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001688{
Gilles Peskine449bd832023-01-11 14:50:10 +01001689 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 +00001690}
1691
1692/*
1693 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001694 *
Tom Cosgrove93842842022-08-05 16:59:43 +01001695 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001696 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001697static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1698 mbedtls_mpi_uint mm, mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001699{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 mbedtls_mpi_uint z = 1;
1701 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001702
Paul Bakker8ddb6452013-02-27 14:56:33 +01001703 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 U.p = &z;
1705
Gilles Peskine449bd832023-01-11 14:50:10 +01001706 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001707}
1708
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001709/**
1710 * Select an MPI from a table without leaking the index.
1711 *
1712 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1713 * reads the entire table in order to avoid leaking the value of idx to an
1714 * attacker able to observe memory access patterns.
1715 *
1716 * \param[out] R Where to write the selected MPI.
1717 * \param[in] T The table to read from.
1718 * \param[in] T_size The number of elements in the table.
1719 * \param[in] idx The index of the element to select;
1720 * this must satisfy 0 <= idx < T_size.
1721 *
1722 * \return \c 0 on success, or a negative error code.
1723 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001724static 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 +01001725{
1726 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1727
Gilles Peskine449bd832023-01-11 14:50:10 +01001728 for (size_t i = 0; i < T_size; i++) {
1729 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
Dave Rodgmanee54faf2023-05-17 13:56:33 +01001730 (unsigned char) mbedtls_ct_bool_eq(i, idx)));
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001731 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001732cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001733 return ret;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001734}
1735
Paul Bakker5121ce52009-01-03 21:22:43 +00001736/*
1737 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1738 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001739int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1740 const mbedtls_mpi *E, const mbedtls_mpi *N,
1741 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00001742{
Janos Follath24eed8d2019-11-22 13:21:35 +00001743 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath74601202022-11-21 15:54:20 +00001744 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00001745 size_t i, j, nblimbs;
1746 size_t bufsize, nbits;
Paul Elliott1748de12023-02-13 15:35:35 +00001747 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001748 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine449bd832023-01-11 14:50:10 +01001749 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001750 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
Gilles Peskine449bd832023-01-11 14:50:10 +01001752 MPI_VALIDATE_RET(X != NULL);
1753 MPI_VALIDATE_RET(A != NULL);
1754 MPI_VALIDATE_RET(E != NULL);
1755 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001756
Gilles Peskine449bd832023-01-11 14:50:10 +01001757 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1758 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1759 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001760
Gilles Peskine449bd832023-01-11 14:50:10 +01001761 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1762 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1763 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00001764
Gilles Peskine449bd832023-01-11 14:50:10 +01001765 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1766 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1767 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1768 }
Chris Jones9246d042020-11-25 15:12:39 +00001769
Paul Bakkerf6198c12012-05-16 08:02:29 +00001770 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001771 * Init temps and window size
1772 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001773 mpi_montg_init(&mm, N);
1774 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
1775 mbedtls_mpi_init(&Apos);
1776 mbedtls_mpi_init(&WW);
1777 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
Gilles Peskine449bd832023-01-11 14:50:10 +01001779 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00001780
Gilles Peskine449bd832023-01-11 14:50:10 +01001781 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1782 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001783
Gilles Peskine449bd832023-01-11 14:50:10 +01001784#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
1785 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath7fa11b82022-11-21 14:48:02 +00001786 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +01001787 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001788#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001789
Janos Follathc8d66d52022-11-22 10:47:10 +00001790 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath06000952022-11-22 10:18:06 +00001791
Paul Bakker5121ce52009-01-03 21:22:43 +00001792 /*
Janos Follathbe54ca72022-11-21 16:14:54 +00001793 * This function is not constant-trace: its memory accesses depend on the
1794 * exponent value. To defend against timing attacks, callers (such as RSA
1795 * and DHM) should use exponent blinding. However this is not enough if the
1796 * adversary can find the exponent in a single trace, so this function
1797 * takes extra precautions against adversaries who can observe memory
1798 * access patterns.
Janos Follathf08b40e2022-11-11 15:56:38 +00001799 *
Janos Follathbe54ca72022-11-21 16:14:54 +00001800 * This function performs a series of multiplications by table elements and
1801 * squarings, and we want the prevent the adversary from finding out which
1802 * table element was used, and from distinguishing between multiplications
1803 * and squarings. Firstly, when multiplying by an element of the window
1804 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
1805 * squarings as having a different memory access patterns from other
1806 * multiplications. So secondly, we put the accumulator X in the table as
1807 * well, and also do a constant-trace table lookup to multiply by X.
1808 *
1809 * This way, all multiplications take the form of a lookup-and-multiply.
1810 * The number of lookup-and-multiply operations inside each iteration of
1811 * the main loop still depends on the bits of the exponent, but since the
1812 * other operations in the loop don't have an easily recognizable memory
1813 * trace, an adversary is unlikely to be able to observe the exact
1814 * patterns.
1815 *
1816 * An adversary may still be able to recover the exponent if they can
1817 * observe both memory accesses and branches. However, branch prediction
1818 * exploitation typically requires many traces of execution over the same
1819 * data, which is defeated by randomized blinding.
Janos Follath84461482022-11-21 14:31:22 +00001820 *
1821 * To achieve this, we make a copy of X and we use the table entry in each
1822 * calculation from this point on.
Janos Follath8e7d6a02022-10-04 13:27:40 +01001823 */
Janos Follathc8d66d52022-11-22 10:47:10 +00001824 const size_t x_index = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001825 mbedtls_mpi_init(&W[x_index]);
1826 mbedtls_mpi_copy(&W[x_index], X);
Janos Follath84461482022-11-21 14:31:22 +00001827
Paul Bakker5121ce52009-01-03 21:22:43 +00001828 j = N->n + 1;
Tom Cosgrove93842842022-08-05 16:59:43 +01001829 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 * and mpi_montred() calls later. Here we ensure that W[1] and X are
1831 * large enough, and later we'll grow other W[i] to the same length.
1832 * They must not be shrunk midway through this function!
1833 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001834 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1835 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
1836 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
1838 /*
Paul Bakker50546922012-05-19 08:40:49 +00001839 * Compensate for negative A (and correct at the end)
1840 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001841 neg = (A->s == -1);
1842 if (neg) {
1843 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00001844 Apos.s = 1;
1845 A = &Apos;
1846 }
1847
1848 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001849 * If 1st call, pre-compute R^2 mod N
1850 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001851 if (prec_RR == NULL || prec_RR->p == NULL) {
1852 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
1853 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
1854 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
Gilles Peskine449bd832023-01-11 14:50:10 +01001856 if (prec_RR != NULL) {
1857 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
1858 }
1859 } else {
1860 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00001861 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
1863 /*
1864 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1865 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001866 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1867 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001868 /* This should be a no-op because W[1] is already that large before
1869 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Tom Cosgrove93842842022-08-05 16:59:43 +01001870 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001871 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
1872 } else {
1873 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001874 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001876 /* Note that this is safe because W[1] always has at least N->n limbs
1877 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001878 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001879
1880 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001881 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001882 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001883 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1884 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
Janos Follathc8d66d52022-11-22 10:47:10 +00001886
Gilles Peskine449bd832023-01-11 14:50:10 +01001887 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001888 /*
Janos Follath74601202022-11-21 15:54:20 +00001889 * W[i] = W[1] ^ i
1890 *
1891 * The first bit of the sliding window is always 1 and therefore we
1892 * only need to store the second half of the table.
Janos Follathc8d66d52022-11-22 10:47:10 +00001893 *
1894 * (There are two special elements in the table: W[0] for the
1895 * accumulator/result and W[1] for A in Montgomery form. Both of these
1896 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 */
Janos Follath74601202022-11-21 15:54:20 +00001898 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
Gilles Peskine449bd832023-01-11 14:50:10 +01001900 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1901 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
Gilles Peskine449bd832023-01-11 14:50:10 +01001903 for (i = 0; i < window_bitsize - 1; i++) {
1904 mpi_montmul(&W[j], &W[j], N, mm, &T);
1905 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01001906
Paul Bakker5121ce52009-01-03 21:22:43 +00001907 /*
1908 * W[i] = W[i - 1] * W[1]
1909 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001910 for (i = j + 1; i < w_table_used_size; i++) {
1911 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1912 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001913
Gilles Peskine449bd832023-01-11 14:50:10 +01001914 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001915 }
1916 }
1917
1918 nblimbs = E->n;
1919 bufsize = 0;
1920 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001921 state = 0;
1922
Gilles Peskine449bd832023-01-11 14:50:10 +01001923 while (1) {
1924 if (bufsize == 0) {
1925 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001927 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
Paul Bakker0d7702c2013-10-29 16:18:35 +01001929 nblimbs--;
1930
Gilles Peskine449bd832023-01-11 14:50:10 +01001931 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001932 }
1933
1934 bufsize--;
1935
1936 ei = (E->p[nblimbs] >> bufsize) & 1;
1937
1938 /*
1939 * skip leading 0s
1940 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001941 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01001943 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
Gilles Peskine449bd832023-01-11 14:50:10 +01001945 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001947 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00001948 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001949 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1950 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 continue;
1952 }
1953
1954 /*
1955 * add ei to current window
1956 */
1957 state = 2;
1958
1959 nbits++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001960 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
Gilles Peskine449bd832023-01-11 14:50:10 +01001962 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001963 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001964 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001965 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001966 for (i = 0; i < window_bitsize; i++) {
1967 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1968 x_index));
1969 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001970 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
1972 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001973 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001975 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1976 exponent_bits_in_window));
1977 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
1979 state--;
1980 nbits = 0;
Janos Follath7fa11b82022-11-21 14:48:02 +00001981 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001982 }
1983 }
1984
1985 /*
1986 * process the remaining bits
1987 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001988 for (i = 0; i < nbits; i++) {
1989 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1990 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
Janos Follath7fa11b82022-11-21 14:48:02 +00001992 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
Gilles Peskine449bd832023-01-11 14:50:10 +01001994 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
1995 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
1996 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001997 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001998 }
1999
2000 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01002001 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002002 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002003 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002004
Gilles Peskine449bd832023-01-11 14:50:10 +01002005 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath8e7d6a02022-10-04 13:27:40 +01002006 W[x_index].s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002007 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00002008 }
2009
Janos Follath8e7d6a02022-10-04 13:27:40 +01002010 /*
2011 * Load the result in the output variable.
2012 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002013 mbedtls_mpi_copy(X, &W[x_index]);
Janos Follath8e7d6a02022-10-04 13:27:40 +01002014
Paul Bakker5121ce52009-01-03 21:22:43 +00002015cleanup:
2016
Janos Follathb2c2fca2022-11-21 15:05:31 +00002017 /* The first bit of the sliding window is always 1 and therefore the first
2018 * half of the table was unused. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002019 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
2020 mbedtls_mpi_free(&W[i]);
2021 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Gilles Peskine449bd832023-01-11 14:50:10 +01002023 mbedtls_mpi_free(&W[x_index]);
2024 mbedtls_mpi_free(&W[1]);
2025 mbedtls_mpi_free(&T);
2026 mbedtls_mpi_free(&Apos);
2027 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00002028
Gilles Peskine449bd832023-01-11 14:50:10 +01002029 if (prec_RR == NULL || prec_RR->p == NULL) {
2030 mbedtls_mpi_free(&RR);
2031 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
Gilles Peskine449bd832023-01-11 14:50:10 +01002033 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002034}
2035
Paul Bakker5121ce52009-01-03 21:22:43 +00002036/*
2037 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2038 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002039int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002040{
Janos Follath24eed8d2019-11-22 13:21:35 +00002041 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002042 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002043 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002044
Gilles Peskine449bd832023-01-11 14:50:10 +01002045 MPI_VALIDATE_RET(G != NULL);
2046 MPI_VALIDATE_RET(A != NULL);
2047 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002048
Gilles Peskine449bd832023-01-11 14:50:10 +01002049 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002050
Gilles Peskine449bd832023-01-11 14:50:10 +01002051 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2052 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002053
Gilles Peskine449bd832023-01-11 14:50:10 +01002054 lz = mbedtls_mpi_lsb(&TA);
2055 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002056
Gilles Peskine27253bc2021-06-09 13:26:43 +02002057 /* The loop below gives the correct result when A==0 but not when B==0.
2058 * So have a special case for B==0. Leverage the fact that we just
2059 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2060 * slightly more efficient than cmp_int(). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002061 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
2062 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02002063 goto cleanup;
2064 }
2065
Gilles Peskine449bd832023-01-11 14:50:10 +01002066 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002067 lz = lzt;
Gilles Peskine449bd832023-01-11 14:50:10 +01002068 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002069
Paul Bakker5121ce52009-01-03 21:22:43 +00002070 TA.s = TB.s = 1;
2071
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002072 /* We mostly follow the procedure described in HAC 14.54, but with some
2073 * minor differences:
2074 * - Sequences of multiplications or divisions by 2 are grouped into a
2075 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002076 * - The procedure in HAC assumes that 0 < TB <= TA.
2077 * - The condition TB <= TA is not actually necessary for correctness.
2078 * TA and TB have symmetric roles except for the loop termination
2079 * condition, and the shifts at the beginning of the loop body
2080 * remove any significance from the ordering of TA vs TB before
2081 * the shifts.
2082 * - If TA = 0, the loop goes through 0 iterations and the result is
2083 * correctly TB.
2084 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002085 *
2086 * For the correctness proof below, decompose the original values of
2087 * A and B as
2088 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2089 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2090 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2091 * and gcd(A',B') is odd or 0.
2092 *
2093 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2094 * The code maintains the following invariant:
2095 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002096 */
2097
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002098 /* Proof that the loop terminates:
2099 * At each iteration, either the right-shift by 1 is made on a nonzero
2100 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2101 * by at least 1, or the right-shift by 1 is made on zero and then
2102 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2103 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2104 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002105 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002106 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002107 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2108 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002110 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2111 * TA-TB is even so the division by 2 has an integer result.
2112 * Invariant (I) is preserved since any odd divisor of both TA and TB
2113 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08002114 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002115 * divides TA.
2116 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002117 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2118 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2119 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2120 } else {
2121 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2122 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002123 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002124 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002125 }
2126
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002127 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2128 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2129 * - If there was at least one loop iteration, then one of TA or TB is odd,
2130 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2131 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2132 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002133 * 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 +02002134 */
2135
Gilles Peskine449bd832023-01-11 14:50:10 +01002136 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2137 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002138
2139cleanup:
2140
Gilles Peskine449bd832023-01-11 14:50:10 +01002141 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002142
Gilles Peskine449bd832023-01-11 14:50:10 +01002143 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002144}
2145
Paul Bakker33dc46b2014-04-30 16:11:39 +02002146/*
2147 * Fill X with size bytes of random.
Gilles Peskine22cdd0c2022-10-27 20:15:13 +02002148 * The bytes returned from the RNG are used in a specific order which
2149 * is suitable for deterministic ECDSA (see the specification of
2150 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Paul Bakker33dc46b2014-04-30 16:11:39 +02002151 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002152int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2153 int (*f_rng)(void *, unsigned char *, size_t),
2154 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002155{
Janos Follath24eed8d2019-11-22 13:21:35 +00002156 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01002157 const size_t limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002158
Gilles Peskine449bd832023-01-11 14:50:10 +01002159 MPI_VALIDATE_RET(X != NULL);
2160 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002161
Hanno Beckerda1655a2017-10-18 14:21:44 +01002162 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +01002163 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2164 if (size == 0) {
2165 return 0;
2166 }
Paul Bakker287781a2011-03-26 13:18:49 +00002167
Gilles Peskine449bd832023-01-11 14:50:10 +01002168 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002169
2170cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002171 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002172}
2173
Gilles Peskine449bd832023-01-11 14:50:10 +01002174int mbedtls_mpi_random(mbedtls_mpi *X,
2175 mbedtls_mpi_sint min,
2176 const mbedtls_mpi *N,
2177 int (*f_rng)(void *, unsigned char *, size_t),
2178 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002179{
Gilles Peskine449bd832023-01-11 14:50:10 +01002180 if (min < 0) {
2181 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2182 }
2183 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2184 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2185 }
Gilles Peskine1e918f42021-03-29 22:14:51 +02002186
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002187 /* Ensure that target MPI has exactly the same number of limbs
2188 * as the upper bound, even if the upper bound has leading zeros.
Gilles Peskine6b7ce962022-12-15 15:04:33 +01002189 * This is necessary for mbedtls_mpi_core_random. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002190 int ret = mbedtls_mpi_resize_clear(X, N->n);
2191 if (ret != 0) {
2192 return ret;
2193 }
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002194
Gilles Peskine449bd832023-01-11 14:50:10 +01002195 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002196}
2197
Paul Bakker5121ce52009-01-03 21:22:43 +00002198/*
2199 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2200 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002201int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002202{
Janos Follath24eed8d2019-11-22 13:21:35 +00002203 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine449bd832023-01-11 14:50:10 +01002205 MPI_VALIDATE_RET(X != NULL);
2206 MPI_VALIDATE_RET(A != NULL);
2207 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002208
Gilles Peskine449bd832023-01-11 14:50:10 +01002209 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2210 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2211 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
Gilles Peskine449bd832023-01-11 14:50:10 +01002213 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2214 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2215 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002216
Gilles Peskine449bd832023-01-11 14:50:10 +01002217 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002218
Gilles Peskine449bd832023-01-11 14:50:10 +01002219 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002221 goto cleanup;
2222 }
2223
Gilles Peskine449bd832023-01-11 14:50:10 +01002224 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2225 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2226 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2227 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002228
Gilles Peskine449bd832023-01-11 14:50:10 +01002229 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2230 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2231 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2232 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
Gilles Peskine449bd832023-01-11 14:50:10 +01002234 do {
2235 while ((TU.p[0] & 1) == 0) {
2236 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
Gilles Peskine449bd832023-01-11 14:50:10 +01002238 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2239 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2240 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002241 }
2242
Gilles Peskine449bd832023-01-11 14:50:10 +01002243 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2244 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 }
2246
Gilles Peskine449bd832023-01-11 14:50:10 +01002247 while ((TV.p[0] & 1) == 0) {
2248 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002249
Gilles Peskine449bd832023-01-11 14:50:10 +01002250 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2251 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2252 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 }
2254
Gilles Peskine449bd832023-01-11 14:50:10 +01002255 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2256 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 }
2258
Gilles Peskine449bd832023-01-11 14:50:10 +01002259 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2260 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2261 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2262 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2263 } else {
2264 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2265 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2266 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002268 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2269
2270 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2271 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
Gilles Peskine449bd832023-01-11 14:50:10 +01002274 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2275 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2276 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002277
Gilles Peskine449bd832023-01-11 14:50:10 +01002278 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
2280cleanup:
2281
Gilles Peskine449bd832023-01-11 14:50:10 +01002282 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2283 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2284 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
Gilles Peskine449bd832023-01-11 14:50:10 +01002286 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002287}
2288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002289#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002290
Paul Bakker5121ce52009-01-03 21:22:43 +00002291static const int small_prime[] =
2292{
Gilles Peskine449bd832023-01-11 14:50:10 +01002293 3, 5, 7, 11, 13, 17, 19, 23,
2294 29, 31, 37, 41, 43, 47, 53, 59,
2295 61, 67, 71, 73, 79, 83, 89, 97,
2296 101, 103, 107, 109, 113, 127, 131, 137,
2297 139, 149, 151, 157, 163, 167, 173, 179,
2298 181, 191, 193, 197, 199, 211, 223, 227,
2299 229, 233, 239, 241, 251, 257, 263, 269,
2300 271, 277, 281, 283, 293, 307, 311, 313,
2301 317, 331, 337, 347, 349, 353, 359, 367,
2302 373, 379, 383, 389, 397, 401, 409, 419,
2303 421, 431, 433, 439, 443, 449, 457, 461,
2304 463, 467, 479, 487, 491, 499, 503, 509,
2305 521, 523, 541, 547, 557, 563, 569, 571,
2306 577, 587, 593, 599, 601, 607, 613, 617,
2307 619, 631, 641, 643, 647, 653, 659, 661,
2308 673, 677, 683, 691, 701, 709, 719, 727,
2309 733, 739, 743, 751, 757, 761, 769, 773,
2310 787, 797, 809, 811, 821, 823, 827, 829,
2311 839, 853, 857, 859, 863, 877, 881, 883,
2312 887, 907, 911, 919, 929, 937, 941, 947,
2313 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002314};
2315
2316/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002317 * Small divisors test (X must be positive)
2318 *
2319 * Return values:
2320 * 0: no small factor (possible prime, more tests needed)
2321 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002323 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002325static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002326{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002327 int ret = 0;
2328 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002330
Gilles Peskine449bd832023-01-11 14:50:10 +01002331 if ((X->p[0] & 1) == 0) {
2332 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2333 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Gilles Peskine449bd832023-01-11 14:50:10 +01002335 for (i = 0; small_prime[i] > 0; i++) {
2336 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2337 return 1;
2338 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
Gilles Peskine449bd832023-01-11 14:50:10 +01002340 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Gilles Peskine449bd832023-01-11 14:50:10 +01002342 if (r == 0) {
2343 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2344 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002345 }
2346
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002347cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002348 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002349}
2350
2351/*
2352 * Miller-Rabin pseudo-primality test (HAC 4.24)
2353 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002354static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2355 int (*f_rng)(void *, unsigned char *, size_t),
2356 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002357{
Pascal Junodb99183d2015-03-11 16:49:45 +01002358 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002359 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002361
Gilles Peskine449bd832023-01-11 14:50:10 +01002362 MPI_VALIDATE_RET(X != NULL);
2363 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002364
Gilles Peskine449bd832023-01-11 14:50:10 +01002365 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2366 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2367 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002368
Paul Bakker5121ce52009-01-03 21:22:43 +00002369 /*
2370 * W = |X| - 1
2371 * R = W >> lsb( W )
2372 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002373 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2374 s = mbedtls_mpi_lsb(&W);
2375 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2376 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Gilles Peskine449bd832023-01-11 14:50:10 +01002378 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002379 /*
2380 * pick a random A, 1 < A < |X| - 1
2381 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002382 count = 0;
2383 do {
Gilles Peskine449bd832023-01-11 14:50:10 +01002384 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002385
Gilles Peskine449bd832023-01-11 14:50:10 +01002386 j = mbedtls_mpi_bitlen(&A);
2387 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002388 if (j > k) {
Gilles Peskine449bd832023-01-11 14:50:10 +01002389 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002390 }
2391
2392 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002393 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2394 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002395 }
2396
Gilles Peskine449bd832023-01-11 14:50:10 +01002397 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2398 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
2400 /*
2401 * A = A^R mod |X|
2402 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002403 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
Gilles Peskine449bd832023-01-11 14:50:10 +01002405 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2406 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01002408 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002409
2410 j = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002411 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002412 /*
2413 * A = A * A mod |X|
2414 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002415 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2416 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
Gilles Peskine449bd832023-01-11 14:50:10 +01002418 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002419 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01002420 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002421
2422 j++;
2423 }
2424
2425 /*
2426 * not prime if A != |X| - 1 or A == 1
2427 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002428 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2429 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002431 break;
2432 }
2433 }
2434
2435cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002436 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2437 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2438 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002439
Gilles Peskine449bd832023-01-11 14:50:10 +01002440 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002441}
2442
2443/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002444 * Pseudo-primality test: small factors, then Miller-Rabin
2445 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002446int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2447 int (*f_rng)(void *, unsigned char *, size_t),
2448 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002449{
Janos Follath24eed8d2019-11-22 13:21:35 +00002450 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 mbedtls_mpi XX;
Gilles Peskine449bd832023-01-11 14:50:10 +01002452 MPI_VALIDATE_RET(X != NULL);
2453 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002454
2455 XX.s = 1;
2456 XX.n = X->n;
2457 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002458
Gilles Peskine449bd832023-01-11 14:50:10 +01002459 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2460 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2461 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002462 }
2463
Gilles Peskine449bd832023-01-11 14:50:10 +01002464 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2465 return 0;
2466 }
2467
2468 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2469 if (ret == 1) {
2470 return 0;
2471 }
2472
2473 return ret;
2474 }
2475
2476 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002477}
2478
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002479/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002480 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002481 *
Janos Follathf301d232018-08-14 13:34:01 +01002482 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2483 * be either 1024 bits or 1536 bits long, and flags must contain
2484 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002485 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002486int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2487 int (*f_rng)(void *, unsigned char *, size_t),
2488 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002489{
Jethro Beekman66689272018-02-14 19:24:10 -08002490#ifdef MBEDTLS_HAVE_INT64
2491// ceil(2^63.5)
2492#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2493#else
2494// ceil(2^31.5)
2495#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2496#endif
2497 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002498 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002499 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500 mbedtls_mpi_uint r;
2501 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002502
Gilles Peskine449bd832023-01-11 14:50:10 +01002503 MPI_VALIDATE_RET(X != NULL);
2504 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002505
Gilles Peskine449bd832023-01-11 14:50:10 +01002506 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2507 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2508 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002509
Gilles Peskine449bd832023-01-11 14:50:10 +01002510 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002511
Gilles Peskine449bd832023-01-11 14:50:10 +01002512 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002513
Gilles Peskine449bd832023-01-11 14:50:10 +01002514 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002515 /*
2516 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2517 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002518 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2519 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2520 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2521 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002522 /*
2523 * 2^-100 error probability, number of rounds computed based on HAC,
2524 * fact 4.48
2525 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002526 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2527 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2528 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2529 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002530 }
2531
Gilles Peskine449bd832023-01-11 14:50:10 +01002532 while (1) {
2533 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002534 /* 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 +01002535 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2536 continue;
2537 }
Jethro Beekman66689272018-02-14 19:24:10 -08002538
2539 k = n * biL;
Gilles Peskine449bd832023-01-11 14:50:10 +01002540 if (k > nbits) {
2541 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2542 }
Jethro Beekman66689272018-02-14 19:24:10 -08002543 X->p[0] |= 1;
2544
Gilles Peskine449bd832023-01-11 14:50:10 +01002545 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2546 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002547
Gilles Peskine449bd832023-01-11 14:50:10 +01002548 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002549 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002550 }
2551 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002552 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002553 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002554 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2555 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002556 */
Jethro Beekman66689272018-02-14 19:24:10 -08002557
2558 X->p[0] |= 2;
2559
Gilles Peskine449bd832023-01-11 14:50:10 +01002560 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2561 if (r == 0) {
2562 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2563 } else if (r == 1) {
2564 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2565 }
Jethro Beekman66689272018-02-14 19:24:10 -08002566
2567 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine449bd832023-01-11 14:50:10 +01002568 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2569 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002570
Gilles Peskine449bd832023-01-11 14:50:10 +01002571 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002572 /*
2573 * First, check small factors for X and Y
2574 * before doing Miller-Rabin on any of them
2575 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002576 if ((ret = mpi_check_small_factors(X)) == 0 &&
2577 (ret = mpi_check_small_factors(&Y)) == 0 &&
2578 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2579 == 0 &&
2580 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2581 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002582 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002583 }
Jethro Beekman66689272018-02-14 19:24:10 -08002584
Gilles Peskine449bd832023-01-11 14:50:10 +01002585 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002586 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002587 }
Jethro Beekman66689272018-02-14 19:24:10 -08002588
2589 /*
2590 * Next candidates. We want to preserve Y = (X-1) / 2 and
2591 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2592 * so up Y by 6 and X by 12.
2593 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002594 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2595 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 }
2598 }
2599
2600cleanup:
2601
Gilles Peskine449bd832023-01-11 14:50:10 +01002602 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002603
Gilles Peskine449bd832023-01-11 14:50:10 +01002604 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002605}
2606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002607#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002608
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002609#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002610
Paul Bakker23986e52011-04-24 08:57:21 +00002611#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002612
2613static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2614{
2615 { 693, 609, 21 },
2616 { 1764, 868, 28 },
2617 { 768454923, 542167814, 1 }
2618};
2619
Paul Bakker5121ce52009-01-03 21:22:43 +00002620/*
2621 * Checkup routine
2622 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002623int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00002624{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002625 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002627
Gilles Peskine449bd832023-01-11 14:50:10 +01002628 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2629 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002630
Gilles Peskine449bd832023-01-11 14:50:10 +01002631 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2632 "EFE021C2645FD1DC586E69184AF4A31E" \
2633 "D5F53E93B5F123FA41680867BA110131" \
2634 "944FE7952E2517337780CB0DB80E61AA" \
2635 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002636
Gilles Peskine449bd832023-01-11 14:50:10 +01002637 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2638 "B2E7EFD37075B9F03FF989C7C5051C20" \
2639 "34D2A323810251127E7BF8625A4F49A5" \
2640 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2641 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002642
Gilles Peskine449bd832023-01-11 14:50:10 +01002643 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2644 "0066A198186C18C10B2F5ED9B522752A" \
2645 "9830B69916E535C8F047518A889A43A5" \
2646 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002647
Gilles Peskine449bd832023-01-11 14:50:10 +01002648 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002649
Gilles Peskine449bd832023-01-11 14:50:10 +01002650 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2651 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2652 "9E857EA95A03512E2BAE7391688D264A" \
2653 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2654 "8001B72E848A38CAE1C65F78E56ABDEF" \
2655 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2656 "ECF677152EF804370C1A305CAF3B5BF1" \
2657 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002658
Gilles Peskine449bd832023-01-11 14:50:10 +01002659 if (verbose != 0) {
2660 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2661 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002662
Gilles Peskine449bd832023-01-11 14:50:10 +01002663 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2664 if (verbose != 0) {
2665 mbedtls_printf("failed\n");
2666 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002667
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002668 ret = 1;
2669 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002670 }
2671
Gilles Peskine449bd832023-01-11 14:50:10 +01002672 if (verbose != 0) {
2673 mbedtls_printf("passed\n");
2674 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002675
Gilles Peskine449bd832023-01-11 14:50:10 +01002676 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002677
Gilles Peskine449bd832023-01-11 14:50:10 +01002678 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2679 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002680
Gilles Peskine449bd832023-01-11 14:50:10 +01002681 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2682 "6613F26162223DF488E9CD48CC132C7A" \
2683 "0AC93C701B001B092E4E5B9F73BCD27B" \
2684 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002685
Gilles Peskine449bd832023-01-11 14:50:10 +01002686 if (verbose != 0) {
2687 mbedtls_printf(" MPI test #2 (div_mpi): ");
2688 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002689
Gilles Peskine449bd832023-01-11 14:50:10 +01002690 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2691 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2692 if (verbose != 0) {
2693 mbedtls_printf("failed\n");
2694 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002695
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002696 ret = 1;
2697 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002698 }
2699
Gilles Peskine449bd832023-01-11 14:50:10 +01002700 if (verbose != 0) {
2701 mbedtls_printf("passed\n");
2702 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002703
Gilles Peskine449bd832023-01-11 14:50:10 +01002704 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00002705
Gilles Peskine449bd832023-01-11 14:50:10 +01002706 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2707 "36E139AEA55215609D2816998ED020BB" \
2708 "BD96C37890F65171D948E9BC7CBAA4D9" \
2709 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002710
Gilles Peskine449bd832023-01-11 14:50:10 +01002711 if (verbose != 0) {
2712 mbedtls_printf(" MPI test #3 (exp_mod): ");
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 if (verbose != 0) {
2717 mbedtls_printf("failed\n");
2718 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002719
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002720 ret = 1;
2721 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 }
2723
Gilles Peskine449bd832023-01-11 14:50:10 +01002724 if (verbose != 0) {
2725 mbedtls_printf("passed\n");
2726 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002727
Gilles Peskine449bd832023-01-11 14:50:10 +01002728 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002729
Gilles Peskine449bd832023-01-11 14:50:10 +01002730 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2731 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2732 "C3DBA76456363A10869622EAC2DD84EC" \
2733 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002734
Gilles Peskine449bd832023-01-11 14:50:10 +01002735 if (verbose != 0) {
2736 mbedtls_printf(" MPI test #4 (inv_mod): ");
2737 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002738
Gilles Peskine449bd832023-01-11 14:50:10 +01002739 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2740 if (verbose != 0) {
2741 mbedtls_printf("failed\n");
2742 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002743
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002744 ret = 1;
2745 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002746 }
2747
Gilles Peskine449bd832023-01-11 14:50:10 +01002748 if (verbose != 0) {
2749 mbedtls_printf("passed\n");
2750 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002751
Gilles Peskine449bd832023-01-11 14:50:10 +01002752 if (verbose != 0) {
2753 mbedtls_printf(" MPI test #5 (simple gcd): ");
2754 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002755
Gilles Peskine449bd832023-01-11 14:50:10 +01002756 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2757 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2758 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002759
Gilles Peskine449bd832023-01-11 14:50:10 +01002760 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002761
Gilles Peskine449bd832023-01-11 14:50:10 +01002762 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2763 if (verbose != 0) {
2764 mbedtls_printf("failed at %d\n", i);
2765 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002766
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002767 ret = 1;
2768 goto cleanup;
2769 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002770 }
2771
Gilles Peskine449bd832023-01-11 14:50:10 +01002772 if (verbose != 0) {
2773 mbedtls_printf("passed\n");
2774 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002775
Paul Bakker5121ce52009-01-03 21:22:43 +00002776cleanup:
2777
Gilles Peskine449bd832023-01-11 14:50:10 +01002778 if (ret != 0 && verbose != 0) {
2779 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2780 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002781
Gilles Peskine449bd832023-01-11 14:50:10 +01002782 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2783 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002784
Gilles Peskine449bd832023-01-11 14:50:10 +01002785 if (verbose != 0) {
2786 mbedtls_printf("\n");
2787 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002788
Gilles Peskine449bd832023-01-11 14:50:10 +01002789 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002790}
2791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002792#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002794#endif /* MBEDTLS_BIGNUM_C */