blob: 76910b1e6f3ef08ce77bf9739d8a66d3959bde2c [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{
64 size_t i;
65 /* The value of any of these variables is either 0 or 1 at all times. */
66 unsigned cond, done, X_is_negative, Y_is_negative;
67
68 MPI_VALIDATE_RET(X != NULL);
69 MPI_VALIDATE_RET(Y != NULL);
70 MPI_VALIDATE_RET(ret != NULL);
71
72 if (X->n != Y->n) {
73 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
74 }
75
76 /*
77 * Set sign_N to 1 if N >= 0, 0 if N < 0.
78 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
79 */
80 X_is_negative = (X->s & 2) >> 1;
81 Y_is_negative = (Y->s & 2) >> 1;
82
83 /*
84 * If the signs are different, then the positive operand is the bigger.
85 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
86 * is false if X is positive (X_is_negative == 0).
87 */
88 cond = (X_is_negative ^ Y_is_negative);
89 *ret = cond & X_is_negative;
90
91 /*
92 * This is a constant-time function. We might have the result, but we still
93 * need to go through the loop. Record if we have the result already.
94 */
95 done = cond;
96
97 for (i = X->n; i > 0; i--) {
98 /*
99 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
100 * X and Y are negative.
101 *
102 * Again even if we can make a decision, we just mark the result and
103 * the fact that we are done and continue looping.
104 */
105 cond = mbedtls_ct_mpi_uint_lt(Y->p[i - 1], X->p[i - 1]);
106 *ret |= cond & (1 - done) & X_is_negative;
107 done |= cond;
108
109 /*
110 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
111 * X and Y are positive.
112 *
113 * Again even if we can make a decision, we just mark the result and
114 * the fact that we are done and continue looping.
115 */
116 cond = mbedtls_ct_mpi_uint_lt(X->p[i - 1], Y->p[i - 1]);
117 *ret |= cond & (1 - done) & (1 - X_is_negative);
118 done |= cond;
119 }
120
121 return 0;
122}
123
124/*
125 * Conditionally assign X = Y, without leaking information
126 * about whether the assignment was made or not.
127 * (Leaking information about the respective sizes of X and Y is ok however.)
128 */
129#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
130/*
131 * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
132 * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
133 */
134__declspec(noinline)
135#endif
136int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
137 const mbedtls_mpi *Y,
138 unsigned char assign)
139{
140 int ret = 0;
141 MPI_VALIDATE_RET(X != NULL);
142 MPI_VALIDATE_RET(Y != NULL);
143
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100144 mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
145
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100146 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
147 mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(assign);
148
149 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
150
151 X->s = (int) mbedtls_ct_uint_if(assign, Y->s, X->s);
152
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100153 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100154
155 for (size_t i = Y->n; i < X->n; i++) {
156 X->p[i] &= ~limb_mask;
157 }
158
159cleanup:
160 return ret;
161}
162
163/*
164 * Conditionally swap X and Y, without leaking information
165 * about whether the swap was made or not.
166 * Here it is not ok to simply swap the pointers, which would lead to
167 * different memory access patterns when X and Y are used afterwards.
168 */
169int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
170 mbedtls_mpi *Y,
171 unsigned char swap)
172{
173 int ret = 0;
174 int s;
175 MPI_VALIDATE_RET(X != NULL);
176 MPI_VALIDATE_RET(Y != NULL);
177
178 if (X == Y) {
179 return 0;
180 }
181
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100182 mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
183
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100184 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
185 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
186
187 s = X->s;
188 X->s = (int) mbedtls_ct_uint_if(swap, Y->s, X->s);
189 Y->s = (int) mbedtls_ct_uint_if(swap, s, Y->s);
190
Dave Rodgmancd2e38b2023-05-17 13:31:55 +0100191 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
Dave Rodgman7d4f0192023-05-09 14:01:05 +0100192
193cleanup:
194 return ret;
195}
196
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500197/* Implementation that should never be optimized out by the compiler */
Gilles Peskine449bd832023-01-11 14:50:10 +0100198static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -0500199{
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 mbedtls_platform_zeroize(v, ciL * n);
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500201}
202
Paul Bakker5121ce52009-01-03 21:22:43 +0000203/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000204 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000205 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100206void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000207{
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000209
Paul Bakker6c591fa2011-05-05 11:49:20 +0000210 X->s = 1;
211 X->n = 0;
212 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000213}
214
215/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000216 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000217 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100218void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000219{
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +0000221 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 if (X->p != NULL) {
225 mbedtls_mpi_zeroize(X->p, X->n);
226 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 }
228
Paul Bakker6c591fa2011-05-05 11:49:20 +0000229 X->s = 1;
230 X->n = 0;
231 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000232}
233
234/*
235 * Enlarge to the specified number of limbs
236 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100237int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +0000238{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 mbedtls_mpi_uint *p;
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000241
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
243 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
244 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000245
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 if (X->n < nblimbs) {
247 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
248 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
249 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000250
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 if (X->p != NULL) {
252 memcpy(p, X->p, X->n * ciL);
253 mbedtls_mpi_zeroize(X->p, X->n);
254 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000255 }
256
257 X->n = nblimbs;
258 X->p = p;
259 }
260
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000262}
263
264/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100265 * Resize down as much as possible,
266 * while keeping at least the specified number of limbs
267 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100268int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100269{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100271 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000273
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
275 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
276 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100277
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100278 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 if (X->n <= nblimbs) {
280 return mbedtls_mpi_grow(X, nblimbs);
281 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100282 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 for (i = X->n - 1; i > 0; i--) {
285 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100286 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 }
288 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100289 i++;
290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100292 i = nblimbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
296 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
297 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100298
Gilles Peskine449bd832023-01-11 14:50:10 +0100299 if (X->p != NULL) {
300 memcpy(p, X->p, i * ciL);
301 mbedtls_mpi_zeroize(X->p, X->n);
302 mbedtls_free(X->p);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100303 }
304
305 X->n = i;
306 X->p = p;
307
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100309}
310
Gilles Peskineed32b572021-06-02 22:17:52 +0200311/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100312static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200313{
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 if (limbs == 0) {
315 mbedtls_mpi_free(X);
316 return 0;
317 } else if (X->n == limbs) {
318 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200319 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 return 0;
321 } else {
322 mbedtls_mpi_free(X);
323 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200324 }
325}
326
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100327/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200328 * Copy the contents of Y into X.
329 *
330 * This function is not constant-time. Leading zeros in Y may be removed.
331 *
332 * Ensure that X does not shrink. This is not guaranteed by the public API,
333 * but some code in the bignum module relies on this property, for example
334 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000335 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100336int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000337{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100338 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000339 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 MPI_VALIDATE_RET(X != NULL);
341 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000342
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 if (X == Y) {
344 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200345 }
346
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 if (Y->n == 0) {
348 if (X->n != 0) {
349 X->s = 1;
350 memset(X->p, 0, X->n * ciL);
351 }
352 return 0;
353 }
354
355 for (i = Y->n - 1; i > 0; i--) {
356 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000357 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 }
359 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000360 i++;
361
362 X->s = Y->s;
363
Gilles Peskine449bd832023-01-11 14:50:10 +0100364 if (X->n < i) {
365 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
366 } else {
367 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100368 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000369
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000371
372cleanup:
373
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000375}
376
377/*
378 * Swap the contents of X and Y
379 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100380void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 MPI_VALIDATE(X != NULL);
384 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000385
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 memcpy(&T, X, sizeof(mbedtls_mpi));
387 memcpy(X, Y, sizeof(mbedtls_mpi));
388 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000389}
390
Gilles Peskine449bd832023-01-11 14:50:10 +0100391static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100392{
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 if (z >= 0) {
394 return z;
395 }
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100396 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
397 * A naive -z would have undefined behavior.
398 * Write this in a way that makes popular compilers happy (GCC, Clang,
399 * MSVC). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100401}
402
Paul Bakker5121ce52009-01-03 21:22:43 +0000403/*
404 * Set value from integer
405 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100406int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000407{
Janos Follath24eed8d2019-11-22 13:21:35 +0000408 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
412 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000413
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 X->p[0] = mpi_sint_abs(z);
415 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000416
417cleanup:
418
Gilles Peskine449bd832023-01-11 14:50:10 +0100419 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000420}
421
422/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000423 * Get a specific bit
424 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100425int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000426{
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 if (X->n * biL <= pos) {
430 return 0;
431 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000432
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000434}
435
436/*
437 * Set a bit to a specific value of 0 or 1
438 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100439int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000440{
441 int ret = 0;
442 size_t off = pos / biL;
443 size_t idx = pos % biL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000445
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 if (val != 0 && val != 1) {
447 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000448 }
449
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 if (X->n * biL <= pos) {
451 if (val == 0) {
452 return 0;
453 }
454
455 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
456 }
457
458 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000460
461cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200462
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000464}
465
466/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200467 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000468 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100469size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000470{
Paul Bakker23986e52011-04-24 08:57:21 +0000471 size_t i, j, count = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000473
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 for (i = 0; i < X->n; i++) {
475 for (j = 0; j < biL; j++, count++) {
476 if (((X->p[i] >> j) & 1) != 0) {
477 return count;
478 }
479 }
480 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
Gilles Peskine449bd832023-01-11 14:50:10 +0100482 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000483}
484
485/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200486 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100488size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000489{
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 return mbedtls_mpi_core_bitlen(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000491}
492
493/*
494 * Return the total size in bytes
495 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100496size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000497{
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000499}
500
501/*
502 * Convert an ASCII character to digit value
503 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100504static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000505{
506 *d = 255;
507
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 if (c >= 0x30 && c <= 0x39) {
509 *d = c - 0x30;
510 }
511 if (c >= 0x41 && c <= 0x46) {
512 *d = c - 0x37;
513 }
514 if (c >= 0x61 && c <= 0x66) {
515 *d = c - 0x57;
516 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000517
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 if (*d >= (mbedtls_mpi_uint) radix) {
519 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
520 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000521
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000523}
524
525/*
526 * Import from an ASCII string
527 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100528int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000529{
Janos Follath24eed8d2019-11-22 13:21:35 +0000530 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000531 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200532 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 mbedtls_mpi_uint d;
534 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100535 MPI_VALIDATE_RET(X != NULL);
536 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000537
Gilles Peskine449bd832023-01-11 14:50:10 +0100538 if (radix < 2 || radix > 16) {
539 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200540 }
541
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 mbedtls_mpi_init(&T);
543
544 if (s[0] == 0) {
545 mbedtls_mpi_free(X);
546 return 0;
547 }
548
549 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200550 ++s;
551 sign = -1;
552 }
553
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000555
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 if (radix == 16) {
Dave Rodgman68ef1d62023-05-18 20:49:03 +0100557 if (slen > SIZE_MAX >> 2) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100558 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000559 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Gilles Peskine449bd832023-01-11 14:50:10 +0100561 n = BITS_TO_LIMBS(slen << 2);
562
563 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
564 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
565
566 for (i = slen, j = 0; i > 0; i--, j++) {
567 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
568 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
569 }
570 } else {
571 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
572
573 for (i = 0; i < slen; i++) {
574 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
575 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
576 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000577 }
578 }
579
Gilles Peskine449bd832023-01-11 14:50:10 +0100580 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200581 X->s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200583
Paul Bakker5121ce52009-01-03 21:22:43 +0000584cleanup:
585
Gilles Peskine449bd832023-01-11 14:50:10 +0100586 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000589}
590
591/*
Ron Eldora16fa292018-11-20 14:07:01 +0200592 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000593 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100594static int mpi_write_hlp(mbedtls_mpi *X, int radix,
595 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000596{
Janos Follath24eed8d2019-11-22 13:21:35 +0000597 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200599 size_t length = 0;
600 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000601
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 do {
603 if (length >= buflen) {
604 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200605 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000606
Gilles Peskine449bd832023-01-11 14:50:10 +0100607 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
608 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200609 /*
610 * Write the residue in the current position, as an ASCII character.
611 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 if (r < 0xA) {
613 *(--p_end) = (char) ('0' + r);
614 } else {
615 *(--p_end) = (char) ('A' + (r - 0xA));
616 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
Ron Eldora16fa292018-11-20 14:07:01 +0200618 length++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000620
Gilles Peskine449bd832023-01-11 14:50:10 +0100621 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200622 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
624cleanup:
625
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000627}
628
629/*
630 * Export into an ASCII string
631 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100632int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
633 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000634{
Paul Bakker23986e52011-04-24 08:57:21 +0000635 int ret = 0;
636 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000637 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 MPI_VALIDATE_RET(X != NULL);
640 MPI_VALIDATE_RET(olen != NULL);
641 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 if (radix < 2 || radix > 16) {
644 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
645 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
Gilles Peskine449bd832023-01-11 14:50:10 +0100647 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
648 if (radix >= 4) {
649 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000650 * `n`. If radix > 4, this might be a strict
651 * overapproximation of the number of
652 * radix-adic digits needed to present `n`. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 }
654 if (radix >= 16) {
655 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000656 * present `n`. */
657
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 }
Janos Follath80470622019-03-06 13:43:02 +0000659 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000660 n += 1; /* Compensate for the divisions above, which round down `n`
661 * in case it's not even. */
662 n += 1; /* Potential '-'-sign. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100663 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000664 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
Gilles Peskine449bd832023-01-11 14:50:10 +0100666 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100667 *olen = n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 }
670
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100671 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100672 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
Gilles Peskine449bd832023-01-11 14:50:10 +0100674 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000675 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000676 buflen--;
677 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000680 int c;
681 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000682
Gilles Peskine449bd832023-01-11 14:50:10 +0100683 for (i = X->n, k = 0; i > 0; i--) {
684 for (j = ciL; j > 0; j--) {
685 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
Gilles Peskine449bd832023-01-11 14:50:10 +0100687 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000688 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100689 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000691 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000692 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000693 k = 1;
694 }
695 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100696 } else {
697 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000698
Gilles Peskine449bd832023-01-11 14:50:10 +0100699 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000700 T.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100701 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000702
Gilles Peskine449bd832023-01-11 14:50:10 +0100703 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000704 }
705
706 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100707 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
709cleanup:
710
Gilles Peskine449bd832023-01-11 14:50:10 +0100711 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000712
Gilles Peskine449bd832023-01-11 14:50:10 +0100713 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000714}
715
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000717/*
718 * Read X from an opened file
719 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100720int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000721{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000723 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000724 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000725 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000726 * Buffer should have space for (short) label and decimal formatted MPI,
727 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000728 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100729 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
Gilles Peskine449bd832023-01-11 14:50:10 +0100731 MPI_VALIDATE_RET(X != NULL);
732 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000733
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 if (radix < 2 || radix > 16) {
735 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
736 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000737
Gilles Peskine449bd832023-01-11 14:50:10 +0100738 memset(s, 0, sizeof(s));
739 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
740 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
741 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
Gilles Peskine449bd832023-01-11 14:50:10 +0100743 slen = strlen(s);
744 if (slen == sizeof(s) - 2) {
745 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
746 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000747
Gilles Peskine449bd832023-01-11 14:50:10 +0100748 if (slen > 0 && s[slen - 1] == '\n') {
749 slen--; s[slen] = '\0';
750 }
751 if (slen > 0 && s[slen - 1] == '\r') {
752 slen--; s[slen] = '\0';
753 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
755 p = s + slen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100756 while (p-- > s) {
757 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000758 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100759 }
760 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000761
Gilles Peskine449bd832023-01-11 14:50:10 +0100762 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000763}
764
765/*
766 * Write X into an opened file (or stdout if fout == NULL)
767 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100768int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000769{
Janos Follath24eed8d2019-11-22 13:21:35 +0000770 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000771 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000772 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000773 * Buffer should have space for (short) label and decimal formatted MPI,
774 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000775 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100776 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
777 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000778
Gilles Peskine449bd832023-01-11 14:50:10 +0100779 if (radix < 2 || radix > 16) {
780 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
781 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
Gilles Peskine449bd832023-01-11 14:50:10 +0100783 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000784
Gilles Peskine449bd832023-01-11 14:50:10 +0100785 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000786
Gilles Peskine449bd832023-01-11 14:50:10 +0100787 if (p == NULL) {
788 p = "";
789 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000790
Gilles Peskine449bd832023-01-11 14:50:10 +0100791 plen = strlen(p);
792 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000793 s[slen++] = '\r';
794 s[slen++] = '\n';
795
Gilles Peskine449bd832023-01-11 14:50:10 +0100796 if (fout != NULL) {
797 if (fwrite(p, 1, plen, fout) != plen ||
798 fwrite(s, 1, slen, fout) != slen) {
799 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
800 }
801 } else {
802 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000803 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000804
805cleanup:
806
Gilles Peskine449bd832023-01-11 14:50:10 +0100807 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000808}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200809#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000810
811/*
Janos Follatha778a942019-02-13 10:28:28 +0000812 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100813 *
814 * This function is guaranteed to return an MPI with exactly the necessary
815 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000816 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100817int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
818 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000819{
Janos Follath24eed8d2019-11-22 13:21:35 +0000820 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100821 const size_t limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000822
823 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100824 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000825
Gilles Peskine449bd832023-01-11 14:50:10 +0100826 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Janos Follatha778a942019-02-13 10:28:28 +0000827
828cleanup:
829
Janos Follath171a7ef2019-02-15 16:17:45 +0000830 /*
831 * This function is also used to import keys. However, wiping the buffers
832 * upon failure is not necessary because failure only can happen before any
833 * input is copied.
834 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100835 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000836}
837
838/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100840 *
841 * This function is guaranteed to return an MPI with exactly the necessary
842 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000843 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100844int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000845{
Janos Follath24eed8d2019-11-22 13:21:35 +0000846 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100847 const size_t limbs = CHARS_TO_LIMBS(buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000848
Gilles Peskine449bd832023-01-11 14:50:10 +0100849 MPI_VALIDATE_RET(X != NULL);
850 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000851
Hanno Becker073c1992017-10-17 15:17:27 +0100852 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100853 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000854
Gilles Peskine449bd832023-01-11 14:50:10 +0100855 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000856
857cleanup:
858
Janos Follath171a7ef2019-02-15 16:17:45 +0000859 /*
860 * This function is also used to import keys. However, wiping the buffers
861 * upon failure is not necessary because failure only can happen before any
862 * input is copied.
863 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100864 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000865}
866
867/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000868 * Export X into unsigned binary data, little endian
869 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100870int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
871 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000872{
Gilles Peskine449bd832023-01-11 14:50:10 +0100873 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Janos Follathe344d0f2019-02-19 16:17:40 +0000874}
875
876/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000877 * Export X into unsigned binary data, big endian
878 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100879int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
880 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000881{
Gilles Peskine449bd832023-01-11 14:50:10 +0100882 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000883}
884
885/*
886 * Left-shift: X <<= count
887 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100888int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000889{
Janos Follath24eed8d2019-11-22 13:21:35 +0000890 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Minos Galanakis0144b352023-05-02 14:02:32 +0100891 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100892 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000893
Gilles Peskine449bd832023-01-11 14:50:10 +0100894 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000895
Gilles Peskine449bd832023-01-11 14:50:10 +0100896 if (X->n * biL < i) {
897 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
898 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000899
900 ret = 0;
901
Minos Galanakis0144b352023-05-02 14:02:32 +0100902 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Paul Bakker5121ce52009-01-03 21:22:43 +0000903cleanup:
904
Gilles Peskine449bd832023-01-11 14:50:10 +0100905 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000906}
907
908/*
909 * Right-shift: X >>= count
910 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100911int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000912{
Gilles Peskine449bd832023-01-11 14:50:10 +0100913 MPI_VALIDATE_RET(X != NULL);
914 if (X->n != 0) {
915 mbedtls_mpi_core_shift_r(X->p, X->n, count);
916 }
917 return 0;
Gilles Peskine66414202022-09-21 15:36:16 +0200918}
919
Paul Bakker5121ce52009-01-03 21:22:43 +0000920/*
921 * Compare unsigned values
922 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100923int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000924{
Paul Bakker23986e52011-04-24 08:57:21 +0000925 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100926 MPI_VALIDATE_RET(X != NULL);
927 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000928
Gilles Peskine449bd832023-01-11 14:50:10 +0100929 for (i = X->n; i > 0; i--) {
930 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000931 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100932 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 }
934
Gilles Peskine449bd832023-01-11 14:50:10 +0100935 for (j = Y->n; j > 0; j--) {
936 if (Y->p[j - 1] != 0) {
937 break;
938 }
939 }
940
941 if (i == 0 && j == 0) {
942 return 0;
943 }
944
945 if (i > j) {
946 return 1;
947 }
948 if (j > i) {
949 return -1;
950 }
951
952 for (; i > 0; i--) {
953 if (X->p[i - 1] > Y->p[i - 1]) {
954 return 1;
955 }
956 if (X->p[i - 1] < Y->p[i - 1]) {
957 return -1;
958 }
959 }
960
961 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000962}
963
964/*
965 * Compare signed values
966 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100967int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000968{
Paul Bakker23986e52011-04-24 08:57:21 +0000969 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100970 MPI_VALIDATE_RET(X != NULL);
971 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
Gilles Peskine449bd832023-01-11 14:50:10 +0100973 for (i = X->n; i > 0; i--) {
974 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000975 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100976 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000977 }
978
Gilles Peskine449bd832023-01-11 14:50:10 +0100979 for (j = Y->n; j > 0; j--) {
980 if (Y->p[j - 1] != 0) {
981 break;
982 }
983 }
984
985 if (i == 0 && j == 0) {
986 return 0;
987 }
988
989 if (i > j) {
990 return X->s;
991 }
992 if (j > i) {
993 return -Y->s;
994 }
995
996 if (X->s > 0 && Y->s < 0) {
997 return 1;
998 }
999 if (Y->s > 0 && X->s < 0) {
1000 return -1;
1001 }
1002
1003 for (; i > 0; i--) {
1004 if (X->p[i - 1] > Y->p[i - 1]) {
1005 return X->s;
1006 }
1007 if (X->p[i - 1] < Y->p[i - 1]) {
1008 return -X->s;
1009 }
1010 }
1011
1012 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001013}
1014
Janos Follathee6abce2019-09-05 14:47:19 +01001015/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 * Compare signed values
1017 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001018int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +00001019{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020 mbedtls_mpi Y;
1021 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001022 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001023
Gilles Peskine449bd832023-01-11 14:50:10 +01001024 *p = mpi_sint_abs(z);
1025 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001026 Y.n = 1;
1027 Y.p = p;
1028
Gilles Peskine449bd832023-01-11 14:50:10 +01001029 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00001030}
1031
1032/*
1033 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1034 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001035int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001036{
Janos Follath24eed8d2019-11-22 13:21:35 +00001037 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001038 size_t j;
Gilles Peskine449bd832023-01-11 14:50:10 +01001039 MPI_VALIDATE_RET(X != NULL);
1040 MPI_VALIDATE_RET(A != NULL);
1041 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001045 }
1046
Gilles Peskine449bd832023-01-11 14:50:10 +01001047 if (X != A) {
1048 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1049 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001050
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001051 /*
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001052 * X must always be positive as a result of unsigned additions.
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001053 */
1054 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001055
Gilles Peskine449bd832023-01-11 14:50:10 +01001056 for (j = B->n; j > 0; j--) {
1057 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001059 }
1060 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001061
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001062 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1063 * and B is 0 (of any size). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001064 if (j == 0) {
1065 return 0;
1066 }
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001067
Gilles Peskine449bd832023-01-11 14:50:10 +01001068 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001069
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001070 /* j is the number of non-zero limbs of B. Add those to X. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001071
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001072 mbedtls_mpi_uint *p = X->p;
1073
Gilles Peskine449bd832023-01-11 14:50:10 +01001074 mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j);
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001075
1076 p += j;
1077
1078 /* Now propagate any carry */
Paul Bakker5121ce52009-01-03 21:22:43 +00001079
Gilles Peskine449bd832023-01-11 14:50:10 +01001080 while (c != 0) {
1081 if (j >= X->n) {
1082 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001083 p = X->p + j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001084 }
1085
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 *p += c; c = (*p < c); j++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001087 }
1088
1089cleanup:
1090
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001092}
1093
Paul Bakker5121ce52009-01-03 21:22:43 +00001094/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001095 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001096 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001097int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001098{
Janos Follath24eed8d2019-11-22 13:21:35 +00001099 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001100 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001101 mbedtls_mpi_uint carry;
Gilles Peskine449bd832023-01-11 14:50:10 +01001102 MPI_VALIDATE_RET(X != NULL);
1103 MPI_VALIDATE_RET(A != NULL);
1104 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001105
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 for (n = B->n; n > 0; n--) {
1107 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001108 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001109 }
1110 }
1111 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001112 /* B >= (2^ciL)^n > A */
1113 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1114 goto cleanup;
1115 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001116
Gilles Peskine449bd832023-01-11 14:50:10 +01001117 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001118
1119 /* Set the high limbs of X to match A. Don't touch the lower limbs
1120 * because X might be aliased to B, and we must not overwrite the
1121 * significant digits of B. */
Aaron M. Uckoaf67d2c2023-01-17 11:52:22 -05001122 if (A->n > n && A != X) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001123 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1124 }
1125 if (X->n > A->n) {
1126 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1127 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001128
Gilles Peskine449bd832023-01-11 14:50:10 +01001129 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1130 if (carry != 0) {
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001131 /* Propagate the carry through the rest of X. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001132 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001133
1134 /* If we have further carry/borrow, the result is negative. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001135 if (carry != 0) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001136 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1137 goto cleanup;
1138 }
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001139 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001140
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001141 /* X should always be positive as a result of unsigned subtractions. */
1142 X->s = 1;
1143
Paul Bakker5121ce52009-01-03 21:22:43 +00001144cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001145 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001146}
1147
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001148/* Common function for signed addition and subtraction.
1149 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001150 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001151static int add_sub_mpi(mbedtls_mpi *X,
1152 const mbedtls_mpi *A, const mbedtls_mpi *B,
1153 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001154{
Hanno Becker73d7d792018-12-11 10:35:51 +00001155 int ret, s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001156 MPI_VALIDATE_RET(X != NULL);
1157 MPI_VALIDATE_RET(A != NULL);
1158 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001159
Hanno Becker73d7d792018-12-11 10:35:51 +00001160 s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001161 if (A->s * B->s * flip_B < 0) {
1162 int cmp = mbedtls_mpi_cmp_abs(A, B);
1163 if (cmp >= 0) {
1164 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001165 /* If |A| = |B|, the result is 0 and we must set the sign bit
1166 * to +1 regardless of which of A or B was negative. Otherwise,
1167 * since |A| > |B|, the sign is the sign of A. */
1168 X->s = cmp == 0 ? 1 : s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001169 } else {
1170 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001171 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 X->s = -s;
1173 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001174 } else {
1175 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001176 X->s = s;
1177 }
1178
1179cleanup:
1180
Gilles Peskine449bd832023-01-11 14:50:10 +01001181 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001182}
1183
1184/*
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001185 * Signed addition: X = A + B
1186 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001187int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001188{
Gilles Peskine449bd832023-01-11 14:50:10 +01001189 return add_sub_mpi(X, A, B, 1);
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001190}
1191
1192/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001193 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001194 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001195int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001196{
Gilles Peskine449bd832023-01-11 14:50:10 +01001197 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001198}
1199
1200/*
1201 * Signed addition: X = A + b
1202 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001203int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001204{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001205 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001207 MPI_VALIDATE_RET(X != NULL);
1208 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
Gilles Peskine449bd832023-01-11 14:50:10 +01001210 p[0] = mpi_sint_abs(b);
1211 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001212 B.n = 1;
1213 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001214
Gilles Peskine449bd832023-01-11 14:50:10 +01001215 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001216}
1217
1218/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001219 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001221int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001222{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001223 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001225 MPI_VALIDATE_RET(X != NULL);
1226 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001227
Gilles Peskine449bd832023-01-11 14:50:10 +01001228 p[0] = mpi_sint_abs(b);
1229 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001230 B.n = 1;
1231 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001232
Gilles Peskine449bd832023-01-11 14:50:10 +01001233 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001234}
1235
Paul Bakker5121ce52009-01-03 21:22:43 +00001236/*
1237 * Baseline multiplication: X = A * B (HAC 14.12)
1238 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001239int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001240{
Janos Follath24eed8d2019-11-22 13:21:35 +00001241 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001242 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001243 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001244 int result_is_zero = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001245 MPI_VALIDATE_RET(X != NULL);
1246 MPI_VALIDATE_RET(A != NULL);
1247 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001248
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001249 mbedtls_mpi_init(&TA);
1250 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001251
Gilles Peskine449bd832023-01-11 14:50:10 +01001252 if (X == A) {
1253 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1254 }
1255 if (X == B) {
1256 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1257 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001258
Gilles Peskine449bd832023-01-11 14:50:10 +01001259 for (i = A->n; i > 0; i--) {
1260 if (A->p[i - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001261 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001262 }
1263 }
1264 if (i == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001265 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001266 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001267
Gilles Peskine449bd832023-01-11 14:50:10 +01001268 for (j = B->n; j > 0; j--) {
1269 if (B->p[j - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001270 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001271 }
1272 }
1273 if (j == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001274 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001275 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001276
Gilles Peskine449bd832023-01-11 14:50:10 +01001277 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1278 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001279
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001280 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Paul Bakker5121ce52009-01-03 21:22:43 +00001281
Hanno Beckerda763de2022-04-13 06:50:02 +01001282 /* If the result is 0, we don't shortcut the operation, which reduces
1283 * but does not eliminate side channels leaking the zero-ness. We do
1284 * need to take care to set the sign bit properly since the library does
1285 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001286 if (result_is_zero) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001287 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001288 } else {
Hanno Beckerda763de2022-04-13 06:50:02 +01001289 X->s = A->s * B->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001290 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001291
1292cleanup:
1293
Gilles Peskine449bd832023-01-11 14:50:10 +01001294 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001295
Gilles Peskine449bd832023-01-11 14:50:10 +01001296 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001297}
1298
1299/*
1300 * Baseline multiplication: X = A * b
1301 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001302int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001303{
Gilles Peskine449bd832023-01-11 14:50:10 +01001304 MPI_VALIDATE_RET(X != NULL);
1305 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001306
Hanno Becker35771312022-04-14 11:52:11 +01001307 size_t n = A->n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001308 while (n > 0 && A->p[n - 1] == 0) {
Hanno Becker35771312022-04-14 11:52:11 +01001309 --n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001310 }
Hanno Becker35771312022-04-14 11:52:11 +01001311
Hanno Becker74a11a32022-04-06 06:27:00 +01001312 /* The general method below doesn't work if b==0. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001313 if (b == 0 || n == 0) {
1314 return mbedtls_mpi_lset(X, 0);
1315 }
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001316
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001317 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001318 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001319 /* In general, A * b requires 1 limb more than b. If
1320 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1321 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001322 * copy() will take care of the growth if needed. However, experimentally,
1323 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001324 * calls to calloc() in ECP code, presumably because it reuses the
1325 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001326 * grow to its final size.
1327 *
1328 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1329 * A,X can be the same. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001330 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1331 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1332 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001333
1334cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001335 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001336}
1337
1338/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001339 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1340 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001341 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001342static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1343 mbedtls_mpi_uint u0,
1344 mbedtls_mpi_uint d,
1345 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001346{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001347#if defined(MBEDTLS_HAVE_UDBL)
1348 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001349#else
Simon Butcher9803d072016-01-03 00:24:34 +00001350 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001351 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001352 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1353 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001354 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001355#endif
1356
Simon Butcher15b15d12015-11-26 19:35:03 +00001357 /*
1358 * Check for overflow
1359 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001360 if (0 == d || u1 >= d) {
1361 if (r != NULL) {
1362 *r = ~(mbedtls_mpi_uint) 0u;
1363 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001364
Gilles Peskine449bd832023-01-11 14:50:10 +01001365 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001366 }
1367
1368#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001369 dividend = (mbedtls_t_udbl) u1 << biL;
1370 dividend |= (mbedtls_t_udbl) u0;
1371 quotient = dividend / d;
Gilles Peskine449bd832023-01-11 14:50:10 +01001372 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1373 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1374 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001375
Gilles Peskine449bd832023-01-11 14:50:10 +01001376 if (r != NULL) {
1377 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1378 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001379
1380 return (mbedtls_mpi_uint) quotient;
1381#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001382
1383 /*
1384 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1385 * Vol. 2 - Seminumerical Algorithms, Knuth
1386 */
1387
1388 /*
1389 * Normalize the divisor, d, and dividend, u0, u1
1390 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001391 s = mbedtls_mpi_core_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001392 d = d << s;
1393
1394 u1 = u1 << s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001395 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001396 u0 = u0 << s;
1397
1398 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001399 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001400
1401 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001402 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001403
1404 /*
1405 * Find the first quotient and remainder
1406 */
1407 q1 = u1 / d1;
1408 r0 = u1 - d1 * q1;
1409
Gilles Peskine449bd832023-01-11 14:50:10 +01001410 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001411 q1 -= 1;
1412 r0 += d1;
1413
Gilles Peskine449bd832023-01-11 14:50:10 +01001414 if (r0 >= radix) {
1415 break;
1416 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001417 }
1418
Gilles Peskine449bd832023-01-11 14:50:10 +01001419 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001420 q0 = rAX / d1;
1421 r0 = rAX - q0 * d1;
1422
Gilles Peskine449bd832023-01-11 14:50:10 +01001423 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001424 q0 -= 1;
1425 r0 += d1;
1426
Gilles Peskine449bd832023-01-11 14:50:10 +01001427 if (r0 >= radix) {
1428 break;
1429 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001430 }
1431
Gilles Peskine449bd832023-01-11 14:50:10 +01001432 if (r != NULL) {
1433 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1434 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001435
1436 quotient = q1 * radix + q0;
1437
1438 return quotient;
1439#endif
1440}
1441
1442/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001444 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001445int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1446 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001447{
Janos Follath24eed8d2019-11-22 13:21:35 +00001448 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001449 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001450 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001451 mbedtls_mpi_uint TP2[3];
Gilles Peskine449bd832023-01-11 14:50:10 +01001452 MPI_VALIDATE_RET(A != NULL);
1453 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001454
Gilles Peskine449bd832023-01-11 14:50:10 +01001455 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1456 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1457 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001458
Gilles Peskine449bd832023-01-11 14:50:10 +01001459 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1460 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001461 /*
1462 * Avoid dynamic memory allocations for constant-size T2.
1463 *
1464 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1465 * so nobody increase the size of the MPI and we're safe to use an on-stack
1466 * buffer.
1467 */
Alexander K35d6d462019-10-31 14:46:45 +03001468 T2.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001469 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001470 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
Gilles Peskine449bd832023-01-11 14:50:10 +01001472 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1473 if (Q != NULL) {
1474 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1475 }
1476 if (R != NULL) {
1477 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1478 }
1479 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001480 }
1481
Gilles Peskine449bd832023-01-11 14:50:10 +01001482 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1483 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001484 X.s = Y.s = 1;
1485
Gilles Peskine449bd832023-01-11 14:50:10 +01001486 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1487 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1488 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
Gilles Peskine449bd832023-01-11 14:50:10 +01001490 k = mbedtls_mpi_bitlen(&Y) % biL;
1491 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001492 k = biL - 1 - k;
Gilles Peskine449bd832023-01-11 14:50:10 +01001493 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1494 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1495 } else {
1496 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001498
1499 n = X.n - 1;
1500 t = Y.n - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001501 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001502
Gilles Peskine449bd832023-01-11 14:50:10 +01001503 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 Z.p[n - t]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001505 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001507 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
Gilles Peskine449bd832023-01-11 14:50:10 +01001509 for (i = n; i > t; i--) {
1510 if (X.p[i] >= Y.p[t]) {
1511 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1512 } else {
1513 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1514 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001515 }
1516
Gilles Peskine449bd832023-01-11 14:50:10 +01001517 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1518 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001519 T2.p[2] = X.p[i];
1520
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 Z.p[i - t - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001522 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001523 Z.p[i - t - 1]--;
1524
Gilles Peskine449bd832023-01-11 14:50:10 +01001525 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1526 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001527 T1.p[1] = Y.p[t];
Gilles Peskine449bd832023-01-11 14:50:10 +01001528 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1529 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001530
Gilles Peskine449bd832023-01-11 14:50:10 +01001531 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1532 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1533 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001534
Gilles Peskine449bd832023-01-11 14:50:10 +01001535 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1536 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1537 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1538 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001539 Z.p[i - t - 1]--;
1540 }
1541 }
1542
Gilles Peskine449bd832023-01-11 14:50:10 +01001543 if (Q != NULL) {
1544 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001545 Q->s = A->s * B->s;
1546 }
1547
Gilles Peskine449bd832023-01-11 14:50:10 +01001548 if (R != NULL) {
1549 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001550 X.s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001551 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001552
Gilles Peskine449bd832023-01-11 14:50:10 +01001553 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001554 R->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001555 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001556 }
1557
1558cleanup:
1559
Gilles Peskine449bd832023-01-11 14:50:10 +01001560 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1561 mbedtls_mpi_free(&T1);
1562 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001563
Gilles Peskine449bd832023-01-11 14:50:10 +01001564 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001565}
1566
1567/*
1568 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001569 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001570int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1571 const mbedtls_mpi *A,
1572 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001573{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001574 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001575 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001576 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001577
Gilles Peskine449bd832023-01-11 14:50:10 +01001578 p[0] = mpi_sint_abs(b);
1579 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001580 B.n = 1;
1581 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
Gilles Peskine449bd832023-01-11 14:50:10 +01001583 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001584}
1585
1586/*
1587 * Modulo: R = A mod B
1588 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001589int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001590{
Janos Follath24eed8d2019-11-22 13:21:35 +00001591 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01001592 MPI_VALIDATE_RET(R != NULL);
1593 MPI_VALIDATE_RET(A != NULL);
1594 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001595
Gilles Peskine449bd832023-01-11 14:50:10 +01001596 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1597 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1598 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001599
Gilles Peskine449bd832023-01-11 14:50:10 +01001600 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Gilles Peskine449bd832023-01-11 14:50:10 +01001602 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1603 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1604 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001605
Gilles Peskine449bd832023-01-11 14:50:10 +01001606 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1607 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1608 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
1610cleanup:
1611
Gilles Peskine449bd832023-01-11 14:50:10 +01001612 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001613}
1614
1615/*
1616 * Modulo: r = A mod b
1617 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001618int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001619{
Paul Bakker23986e52011-04-24 08:57:21 +00001620 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 mbedtls_mpi_uint x, y, z;
Gilles Peskine449bd832023-01-11 14:50:10 +01001622 MPI_VALIDATE_RET(r != NULL);
1623 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
Gilles Peskine449bd832023-01-11 14:50:10 +01001625 if (b == 0) {
1626 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1627 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001628
Gilles Peskine449bd832023-01-11 14:50:10 +01001629 if (b < 0) {
1630 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1631 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001632
1633 /*
1634 * handle trivial cases
1635 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001636 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001637 *r = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001638 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001639 }
1640
Gilles Peskine449bd832023-01-11 14:50:10 +01001641 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001642 *r = A->p[0] & 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001643 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001644 }
1645
1646 /*
1647 * general case
1648 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001649 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001650 x = A->p[i - 1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001651 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001652 z = y / b;
1653 y -= z * b;
1654
1655 x <<= biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001656 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001657 z = y / b;
1658 y -= z * b;
1659 }
1660
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001661 /*
1662 * If A is negative, then the current y represents a negative value.
1663 * Flipping it to the positive side.
1664 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001665 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001666 y = b - y;
Gilles Peskine449bd832023-01-11 14:50:10 +01001667 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001668
Paul Bakker5121ce52009-01-03 21:22:43 +00001669 *r = y;
1670
Gilles Peskine449bd832023-01-11 14:50:10 +01001671 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001672}
1673
Gilles Peskine449bd832023-01-11 14:50:10 +01001674static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001675{
Gilles Peskine449bd832023-01-11 14:50:10 +01001676 *mm = mbedtls_mpi_core_montmul_init(N->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001677}
1678
Tom Cosgrove93842842022-08-05 16:59:43 +01001679/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1680 *
1681 * \param[in,out] A One of the numbers to multiply.
1682 * It must have at least as many limbs as N
1683 * (A->n >= N->n), and any limbs beyond n are ignored.
1684 * On successful completion, A contains the result of
1685 * the multiplication A * B * R^-1 mod N where
1686 * R = (2^ciL)^n.
1687 * \param[in] B One of the numbers to multiply.
1688 * It must be nonzero and must not have more limbs than N
1689 * (B->n <= N->n).
Tom Cosgrove40d22942022-08-17 06:42:44 +01001690 * \param[in] N The modulus. \p N must be odd.
Tom Cosgrove93842842022-08-05 16:59:43 +01001691 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1692 * This is -N^-1 mod 2^ciL.
1693 * \param[in,out] T A bignum for temporary storage.
1694 * It must be at least twice the limb size of N plus 1
1695 * (T->n >= 2 * N->n + 1).
1696 * Its initial content is unused and
1697 * its final content is indeterminate.
Tom Cosgrove5dd97e62022-08-30 14:31:49 +01001698 * It does not get reallocated.
Tom Cosgrove93842842022-08-05 16:59:43 +01001699 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001700static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1701 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1702 mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001703{
Gilles Peskine449bd832023-01-11 14:50:10 +01001704 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 +00001705}
1706
1707/*
1708 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001709 *
Tom Cosgrove93842842022-08-05 16:59:43 +01001710 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001711 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001712static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1713 mbedtls_mpi_uint mm, mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001714{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 mbedtls_mpi_uint z = 1;
1716 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001717
Paul Bakker8ddb6452013-02-27 14:56:33 +01001718 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001719 U.p = &z;
1720
Gilles Peskine449bd832023-01-11 14:50:10 +01001721 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001722}
1723
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001724/**
1725 * Select an MPI from a table without leaking the index.
1726 *
1727 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1728 * reads the entire table in order to avoid leaking the value of idx to an
1729 * attacker able to observe memory access patterns.
1730 *
1731 * \param[out] R Where to write the selected MPI.
1732 * \param[in] T The table to read from.
1733 * \param[in] T_size The number of elements in the table.
1734 * \param[in] idx The index of the element to select;
1735 * this must satisfy 0 <= idx < T_size.
1736 *
1737 * \return \c 0 on success, or a negative error code.
1738 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001739static 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 +01001740{
1741 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1742
Gilles Peskine449bd832023-01-11 14:50:10 +01001743 for (size_t i = 0; i < T_size; i++) {
1744 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
1745 (unsigned char) mbedtls_ct_size_bool_eq(i,
1746 idx)));
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001747 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001748
1749cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001750 return ret;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001751}
1752
Paul Bakker5121ce52009-01-03 21:22:43 +00001753/*
1754 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1755 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001756int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1757 const mbedtls_mpi *E, const mbedtls_mpi *N,
1758 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00001759{
Janos Follath24eed8d2019-11-22 13:21:35 +00001760 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath74601202022-11-21 15:54:20 +00001761 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00001762 size_t i, j, nblimbs;
1763 size_t bufsize, nbits;
Paul Elliott1748de12023-02-13 15:35:35 +00001764 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine449bd832023-01-11 14:50:10 +01001766 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001767 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
Gilles Peskine449bd832023-01-11 14:50:10 +01001769 MPI_VALIDATE_RET(X != NULL);
1770 MPI_VALIDATE_RET(A != NULL);
1771 MPI_VALIDATE_RET(E != NULL);
1772 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001773
Gilles Peskine449bd832023-01-11 14:50:10 +01001774 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1775 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1776 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001777
Gilles Peskine449bd832023-01-11 14:50:10 +01001778 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1779 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1780 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00001781
Gilles Peskine449bd832023-01-11 14:50:10 +01001782 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1783 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1784 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1785 }
Chris Jones9246d042020-11-25 15:12:39 +00001786
Paul Bakkerf6198c12012-05-16 08:02:29 +00001787 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001788 * Init temps and window size
1789 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001790 mpi_montg_init(&mm, N);
1791 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
1792 mbedtls_mpi_init(&Apos);
1793 mbedtls_mpi_init(&WW);
1794 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00001795
Gilles Peskine449bd832023-01-11 14:50:10 +01001796 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
Gilles Peskine449bd832023-01-11 14:50:10 +01001798 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1799 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001800
Gilles Peskine449bd832023-01-11 14:50:10 +01001801#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
1802 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath7fa11b82022-11-21 14:48:02 +00001803 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +01001804 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001805#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001806
Janos Follathc8d66d52022-11-22 10:47:10 +00001807 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath06000952022-11-22 10:18:06 +00001808
Paul Bakker5121ce52009-01-03 21:22:43 +00001809 /*
Janos Follathbe54ca72022-11-21 16:14:54 +00001810 * This function is not constant-trace: its memory accesses depend on the
1811 * exponent value. To defend against timing attacks, callers (such as RSA
1812 * and DHM) should use exponent blinding. However this is not enough if the
1813 * adversary can find the exponent in a single trace, so this function
1814 * takes extra precautions against adversaries who can observe memory
1815 * access patterns.
Janos Follathf08b40e2022-11-11 15:56:38 +00001816 *
Janos Follathbe54ca72022-11-21 16:14:54 +00001817 * This function performs a series of multiplications by table elements and
1818 * squarings, and we want the prevent the adversary from finding out which
1819 * table element was used, and from distinguishing between multiplications
1820 * and squarings. Firstly, when multiplying by an element of the window
1821 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
1822 * squarings as having a different memory access patterns from other
1823 * multiplications. So secondly, we put the accumulator X in the table as
1824 * well, and also do a constant-trace table lookup to multiply by X.
1825 *
1826 * This way, all multiplications take the form of a lookup-and-multiply.
1827 * The number of lookup-and-multiply operations inside each iteration of
1828 * the main loop still depends on the bits of the exponent, but since the
1829 * other operations in the loop don't have an easily recognizable memory
1830 * trace, an adversary is unlikely to be able to observe the exact
1831 * patterns.
1832 *
1833 * An adversary may still be able to recover the exponent if they can
1834 * observe both memory accesses and branches. However, branch prediction
1835 * exploitation typically requires many traces of execution over the same
1836 * data, which is defeated by randomized blinding.
Janos Follath84461482022-11-21 14:31:22 +00001837 *
1838 * To achieve this, we make a copy of X and we use the table entry in each
1839 * calculation from this point on.
Janos Follath8e7d6a02022-10-04 13:27:40 +01001840 */
Janos Follathc8d66d52022-11-22 10:47:10 +00001841 const size_t x_index = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001842 mbedtls_mpi_init(&W[x_index]);
1843 mbedtls_mpi_copy(&W[x_index], X);
Janos Follath84461482022-11-21 14:31:22 +00001844
Paul Bakker5121ce52009-01-03 21:22:43 +00001845 j = N->n + 1;
Tom Cosgrove93842842022-08-05 16:59:43 +01001846 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 * and mpi_montred() calls later. Here we ensure that W[1] and X are
1848 * large enough, and later we'll grow other W[i] to the same length.
1849 * They must not be shrunk midway through this function!
1850 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001851 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1852 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
1853 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
1855 /*
Paul Bakker50546922012-05-19 08:40:49 +00001856 * Compensate for negative A (and correct at the end)
1857 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001858 neg = (A->s == -1);
1859 if (neg) {
1860 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00001861 Apos.s = 1;
1862 A = &Apos;
1863 }
1864
1865 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001866 * If 1st call, pre-compute R^2 mod N
1867 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001868 if (prec_RR == NULL || prec_RR->p == NULL) {
1869 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
1870 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
1871 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001872
Gilles Peskine449bd832023-01-11 14:50:10 +01001873 if (prec_RR != NULL) {
1874 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
1875 }
1876 } else {
1877 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001879
1880 /*
1881 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1882 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001883 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1884 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001885 /* This should be a no-op because W[1] is already that large before
1886 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Tom Cosgrove93842842022-08-05 16:59:43 +01001887 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001888 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
1889 } else {
1890 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001891 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001893 /* Note that this is safe because W[1] always has at least N->n limbs
1894 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001895 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
1897 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001898 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001899 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001900 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1901 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
Janos Follathc8d66d52022-11-22 10:47:10 +00001903
Gilles Peskine449bd832023-01-11 14:50:10 +01001904 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001905 /*
Janos Follath74601202022-11-21 15:54:20 +00001906 * W[i] = W[1] ^ i
1907 *
1908 * The first bit of the sliding window is always 1 and therefore we
1909 * only need to store the second half of the table.
Janos Follathc8d66d52022-11-22 10:47:10 +00001910 *
1911 * (There are two special elements in the table: W[0] for the
1912 * accumulator/result and W[1] for A in Montgomery form. Both of these
1913 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00001914 */
Janos Follath74601202022-11-21 15:54:20 +00001915 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001916
Gilles Peskine449bd832023-01-11 14:50:10 +01001917 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1918 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001919
Gilles Peskine449bd832023-01-11 14:50:10 +01001920 for (i = 0; i < window_bitsize - 1; i++) {
1921 mpi_montmul(&W[j], &W[j], N, mm, &T);
1922 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01001923
Paul Bakker5121ce52009-01-03 21:22:43 +00001924 /*
1925 * W[i] = W[i - 1] * W[1]
1926 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001927 for (i = j + 1; i < w_table_used_size; i++) {
1928 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1929 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
Gilles Peskine449bd832023-01-11 14:50:10 +01001931 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001932 }
1933 }
1934
1935 nblimbs = E->n;
1936 bufsize = 0;
1937 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001938 state = 0;
1939
Gilles Peskine449bd832023-01-11 14:50:10 +01001940 while (1) {
1941 if (bufsize == 0) {
1942 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001944 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Paul Bakker0d7702c2013-10-29 16:18:35 +01001946 nblimbs--;
1947
Gilles Peskine449bd832023-01-11 14:50:10 +01001948 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001949 }
1950
1951 bufsize--;
1952
1953 ei = (E->p[nblimbs] >> bufsize) & 1;
1954
1955 /*
1956 * skip leading 0s
1957 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001958 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001959 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01001960 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
Gilles Peskine449bd832023-01-11 14:50:10 +01001962 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001963 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001964 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00001965 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001966 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1967 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001968 continue;
1969 }
1970
1971 /*
1972 * add ei to current window
1973 */
1974 state = 2;
1975
1976 nbits++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001977 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
Gilles Peskine449bd832023-01-11 14:50:10 +01001979 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001981 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001982 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001983 for (i = 0; i < window_bitsize; i++) {
1984 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1985 x_index));
1986 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001987 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001988
1989 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001990 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001991 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001992 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1993 exponent_bits_in_window));
1994 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
1996 state--;
1997 nbits = 0;
Janos Follath7fa11b82022-11-21 14:48:02 +00001998 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001999 }
2000 }
2001
2002 /*
2003 * process the remaining bits
2004 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002005 for (i = 0; i < nbits; i++) {
2006 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
2007 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
Janos Follath7fa11b82022-11-21 14:48:02 +00002009 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002010
Gilles Peskine449bd832023-01-11 14:50:10 +01002011 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
2012 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
2013 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01002014 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002015 }
2016
2017 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01002018 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002019 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002020 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002021
Gilles Peskine449bd832023-01-11 14:50:10 +01002022 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath8e7d6a02022-10-04 13:27:40 +01002023 W[x_index].s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002024 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00002025 }
2026
Janos Follath8e7d6a02022-10-04 13:27:40 +01002027 /*
2028 * Load the result in the output variable.
2029 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002030 mbedtls_mpi_copy(X, &W[x_index]);
Janos Follath8e7d6a02022-10-04 13:27:40 +01002031
Paul Bakker5121ce52009-01-03 21:22:43 +00002032cleanup:
2033
Janos Follathb2c2fca2022-11-21 15:05:31 +00002034 /* The first bit of the sliding window is always 1 and therefore the first
2035 * half of the table was unused. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002036 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
2037 mbedtls_mpi_free(&W[i]);
2038 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
Gilles Peskine449bd832023-01-11 14:50:10 +01002040 mbedtls_mpi_free(&W[x_index]);
2041 mbedtls_mpi_free(&W[1]);
2042 mbedtls_mpi_free(&T);
2043 mbedtls_mpi_free(&Apos);
2044 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00002045
Gilles Peskine449bd832023-01-11 14:50:10 +01002046 if (prec_RR == NULL || prec_RR->p == NULL) {
2047 mbedtls_mpi_free(&RR);
2048 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
Gilles Peskine449bd832023-01-11 14:50:10 +01002050 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002051}
2052
Paul Bakker5121ce52009-01-03 21:22:43 +00002053/*
2054 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2055 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002056int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002057{
Janos Follath24eed8d2019-11-22 13:21:35 +00002058 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002059 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002060 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002061
Gilles Peskine449bd832023-01-11 14:50:10 +01002062 MPI_VALIDATE_RET(G != NULL);
2063 MPI_VALIDATE_RET(A != NULL);
2064 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002065
Gilles Peskine449bd832023-01-11 14:50:10 +01002066 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
Gilles Peskine449bd832023-01-11 14:50:10 +01002068 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2069 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
Gilles Peskine449bd832023-01-11 14:50:10 +01002071 lz = mbedtls_mpi_lsb(&TA);
2072 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002073
Gilles Peskine27253bc2021-06-09 13:26:43 +02002074 /* The loop below gives the correct result when A==0 but not when B==0.
2075 * So have a special case for B==0. Leverage the fact that we just
2076 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2077 * slightly more efficient than cmp_int(). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002078 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
2079 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02002080 goto cleanup;
2081 }
2082
Gilles Peskine449bd832023-01-11 14:50:10 +01002083 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002084 lz = lzt;
Gilles Peskine449bd832023-01-11 14:50:10 +01002085 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002086
Paul Bakker5121ce52009-01-03 21:22:43 +00002087 TA.s = TB.s = 1;
2088
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002089 /* We mostly follow the procedure described in HAC 14.54, but with some
2090 * minor differences:
2091 * - Sequences of multiplications or divisions by 2 are grouped into a
2092 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002093 * - The procedure in HAC assumes that 0 < TB <= TA.
2094 * - The condition TB <= TA is not actually necessary for correctness.
2095 * TA and TB have symmetric roles except for the loop termination
2096 * condition, and the shifts at the beginning of the loop body
2097 * remove any significance from the ordering of TA vs TB before
2098 * the shifts.
2099 * - If TA = 0, the loop goes through 0 iterations and the result is
2100 * correctly TB.
2101 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002102 *
2103 * For the correctness proof below, decompose the original values of
2104 * A and B as
2105 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2106 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2107 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2108 * and gcd(A',B') is odd or 0.
2109 *
2110 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2111 * The code maintains the following invariant:
2112 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002113 */
2114
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002115 /* Proof that the loop terminates:
2116 * At each iteration, either the right-shift by 1 is made on a nonzero
2117 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2118 * by at least 1, or the right-shift by 1 is made on zero and then
2119 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2120 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2121 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002122 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002123 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002124 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2125 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002126
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002127 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2128 * TA-TB is even so the division by 2 has an integer result.
2129 * Invariant (I) is preserved since any odd divisor of both TA and TB
2130 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08002131 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002132 * divides TA.
2133 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002134 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2135 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2136 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2137 } else {
2138 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2139 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002140 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002141 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002142 }
2143
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002144 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2145 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2146 * - If there was at least one loop iteration, then one of TA or TB is odd,
2147 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2148 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2149 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002150 * 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 +02002151 */
2152
Gilles Peskine449bd832023-01-11 14:50:10 +01002153 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2154 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
2156cleanup:
2157
Gilles Peskine449bd832023-01-11 14:50:10 +01002158 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
Gilles Peskine449bd832023-01-11 14:50:10 +01002160 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002161}
2162
Paul Bakker33dc46b2014-04-30 16:11:39 +02002163/*
2164 * Fill X with size bytes of random.
Gilles Peskine22cdd0c2022-10-27 20:15:13 +02002165 * The bytes returned from the RNG are used in a specific order which
2166 * is suitable for deterministic ECDSA (see the specification of
2167 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Paul Bakker33dc46b2014-04-30 16:11:39 +02002168 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002169int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2170 int (*f_rng)(void *, unsigned char *, size_t),
2171 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002172{
Janos Follath24eed8d2019-11-22 13:21:35 +00002173 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01002174 const size_t limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002175
Gilles Peskine449bd832023-01-11 14:50:10 +01002176 MPI_VALIDATE_RET(X != NULL);
2177 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002178
Hanno Beckerda1655a2017-10-18 14:21:44 +01002179 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +01002180 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2181 if (size == 0) {
2182 return 0;
2183 }
Paul Bakker287781a2011-03-26 13:18:49 +00002184
Gilles Peskine449bd832023-01-11 14:50:10 +01002185 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002186
2187cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002188 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002189}
2190
Gilles Peskine449bd832023-01-11 14:50:10 +01002191int mbedtls_mpi_random(mbedtls_mpi *X,
2192 mbedtls_mpi_sint min,
2193 const mbedtls_mpi *N,
2194 int (*f_rng)(void *, unsigned char *, size_t),
2195 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002196{
Gilles Peskine449bd832023-01-11 14:50:10 +01002197 if (min < 0) {
2198 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2199 }
2200 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2201 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2202 }
Gilles Peskine1e918f42021-03-29 22:14:51 +02002203
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002204 /* Ensure that target MPI has exactly the same number of limbs
2205 * as the upper bound, even if the upper bound has leading zeros.
Gilles Peskine6b7ce962022-12-15 15:04:33 +01002206 * This is necessary for mbedtls_mpi_core_random. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002207 int ret = mbedtls_mpi_resize_clear(X, N->n);
2208 if (ret != 0) {
2209 return ret;
2210 }
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002211
Gilles Peskine449bd832023-01-11 14:50:10 +01002212 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002213}
2214
Paul Bakker5121ce52009-01-03 21:22:43 +00002215/*
2216 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2217 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002218int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002219{
Janos Follath24eed8d2019-11-22 13:21:35 +00002220 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine449bd832023-01-11 14:50:10 +01002222 MPI_VALIDATE_RET(X != NULL);
2223 MPI_VALIDATE_RET(A != NULL);
2224 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002225
Gilles Peskine449bd832023-01-11 14:50:10 +01002226 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2227 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2228 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002229
Gilles Peskine449bd832023-01-11 14:50:10 +01002230 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2231 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2232 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
Gilles Peskine449bd832023-01-11 14:50:10 +01002234 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002235
Gilles Peskine449bd832023-01-11 14:50:10 +01002236 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002238 goto cleanup;
2239 }
2240
Gilles Peskine449bd832023-01-11 14:50:10 +01002241 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2242 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2243 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2244 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002245
Gilles Peskine449bd832023-01-11 14:50:10 +01002246 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2247 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2248 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2249 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
Gilles Peskine449bd832023-01-11 14:50:10 +01002251 do {
2252 while ((TU.p[0] & 1) == 0) {
2253 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
Gilles Peskine449bd832023-01-11 14:50:10 +01002255 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2256 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2257 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002258 }
2259
Gilles Peskine449bd832023-01-11 14:50:10 +01002260 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2261 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 }
2263
Gilles Peskine449bd832023-01-11 14:50:10 +01002264 while ((TV.p[0] & 1) == 0) {
2265 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
Gilles Peskine449bd832023-01-11 14:50:10 +01002267 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2268 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2269 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 }
2271
Gilles Peskine449bd832023-01-11 14:50:10 +01002272 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2273 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002274 }
2275
Gilles Peskine449bd832023-01-11 14:50:10 +01002276 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2277 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2278 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2279 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2280 } else {
2281 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2282 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2283 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002284 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002285 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2286
2287 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2288 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
Gilles Peskine449bd832023-01-11 14:50:10 +01002291 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2292 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2293 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002294
Gilles Peskine449bd832023-01-11 14:50:10 +01002295 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002296
2297cleanup:
2298
Gilles Peskine449bd832023-01-11 14:50:10 +01002299 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2300 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2301 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
Gilles Peskine449bd832023-01-11 14:50:10 +01002303 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002304}
2305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002307
Paul Bakker5121ce52009-01-03 21:22:43 +00002308static const int small_prime[] =
2309{
Gilles Peskine449bd832023-01-11 14:50:10 +01002310 3, 5, 7, 11, 13, 17, 19, 23,
2311 29, 31, 37, 41, 43, 47, 53, 59,
2312 61, 67, 71, 73, 79, 83, 89, 97,
2313 101, 103, 107, 109, 113, 127, 131, 137,
2314 139, 149, 151, 157, 163, 167, 173, 179,
2315 181, 191, 193, 197, 199, 211, 223, 227,
2316 229, 233, 239, 241, 251, 257, 263, 269,
2317 271, 277, 281, 283, 293, 307, 311, 313,
2318 317, 331, 337, 347, 349, 353, 359, 367,
2319 373, 379, 383, 389, 397, 401, 409, 419,
2320 421, 431, 433, 439, 443, 449, 457, 461,
2321 463, 467, 479, 487, 491, 499, 503, 509,
2322 521, 523, 541, 547, 557, 563, 569, 571,
2323 577, 587, 593, 599, 601, 607, 613, 617,
2324 619, 631, 641, 643, 647, 653, 659, 661,
2325 673, 677, 683, 691, 701, 709, 719, 727,
2326 733, 739, 743, 751, 757, 761, 769, 773,
2327 787, 797, 809, 811, 821, 823, 827, 829,
2328 839, 853, 857, 859, 863, 877, 881, 883,
2329 887, 907, 911, 919, 929, 937, 941, 947,
2330 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002331};
2332
2333/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002334 * Small divisors test (X must be positive)
2335 *
2336 * Return values:
2337 * 0: no small factor (possible prime, more tests needed)
2338 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002340 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002341 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002342static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002343{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002344 int ret = 0;
2345 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002347
Gilles Peskine449bd832023-01-11 14:50:10 +01002348 if ((X->p[0] & 1) == 0) {
2349 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2350 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
Gilles Peskine449bd832023-01-11 14:50:10 +01002352 for (i = 0; small_prime[i] > 0; i++) {
2353 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2354 return 1;
2355 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
Gilles Peskine449bd832023-01-11 14:50:10 +01002357 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002358
Gilles Peskine449bd832023-01-11 14:50:10 +01002359 if (r == 0) {
2360 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2361 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 }
2363
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002364cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002365 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002366}
2367
2368/*
2369 * Miller-Rabin pseudo-primality test (HAC 4.24)
2370 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002371static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2372 int (*f_rng)(void *, unsigned char *, size_t),
2373 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002374{
Pascal Junodb99183d2015-03-11 16:49:45 +01002375 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002376 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002377 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002378
Gilles Peskine449bd832023-01-11 14:50:10 +01002379 MPI_VALIDATE_RET(X != NULL);
2380 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002381
Gilles Peskine449bd832023-01-11 14:50:10 +01002382 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2383 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2384 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002385
Paul Bakker5121ce52009-01-03 21:22:43 +00002386 /*
2387 * W = |X| - 1
2388 * R = W >> lsb( W )
2389 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002390 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2391 s = mbedtls_mpi_lsb(&W);
2392 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2393 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
Gilles Peskine449bd832023-01-11 14:50:10 +01002395 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 /*
2397 * pick a random A, 1 < A < |X| - 1
2398 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002399 count = 0;
2400 do {
Gilles Peskine449bd832023-01-11 14:50:10 +01002401 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002402
Gilles Peskine449bd832023-01-11 14:50:10 +01002403 j = mbedtls_mpi_bitlen(&A);
2404 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002405 if (j > k) {
Gilles Peskine449bd832023-01-11 14:50:10 +01002406 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002407 }
2408
2409 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002410 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2411 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002412 }
2413
Gilles Peskine449bd832023-01-11 14:50:10 +01002414 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2415 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002416
2417 /*
2418 * A = A^R mod |X|
2419 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002420 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002421
Gilles Peskine449bd832023-01-11 14:50:10 +01002422 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2423 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002424 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01002425 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002426
2427 j = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002428 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002429 /*
2430 * A = A * A mod |X|
2431 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002432 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2433 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002434
Gilles Peskine449bd832023-01-11 14:50:10 +01002435 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002436 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01002437 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002438
2439 j++;
2440 }
2441
2442 /*
2443 * not prime if A != |X| - 1 or A == 1
2444 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002445 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2446 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 break;
2449 }
2450 }
2451
2452cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002453 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2454 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2455 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002456
Gilles Peskine449bd832023-01-11 14:50:10 +01002457 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002458}
2459
2460/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002461 * Pseudo-primality test: small factors, then Miller-Rabin
2462 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002463int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2464 int (*f_rng)(void *, unsigned char *, size_t),
2465 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002466{
Janos Follath24eed8d2019-11-22 13:21:35 +00002467 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 mbedtls_mpi XX;
Gilles Peskine449bd832023-01-11 14:50:10 +01002469 MPI_VALIDATE_RET(X != NULL);
2470 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002471
2472 XX.s = 1;
2473 XX.n = X->n;
2474 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002475
Gilles Peskine449bd832023-01-11 14:50:10 +01002476 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2477 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2478 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002479 }
2480
Gilles Peskine449bd832023-01-11 14:50:10 +01002481 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2482 return 0;
2483 }
2484
2485 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2486 if (ret == 1) {
2487 return 0;
2488 }
2489
2490 return ret;
2491 }
2492
2493 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002494}
2495
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002496/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002497 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002498 *
Janos Follathf301d232018-08-14 13:34:01 +01002499 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2500 * be either 1024 bits or 1536 bits long, and flags must contain
2501 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002502 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002503int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2504 int (*f_rng)(void *, unsigned char *, size_t),
2505 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002506{
Jethro Beekman66689272018-02-14 19:24:10 -08002507#ifdef MBEDTLS_HAVE_INT64
2508// ceil(2^63.5)
2509#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2510#else
2511// ceil(2^31.5)
2512#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2513#endif
2514 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002515 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002516 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517 mbedtls_mpi_uint r;
2518 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002519
Gilles Peskine449bd832023-01-11 14:50:10 +01002520 MPI_VALIDATE_RET(X != NULL);
2521 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002522
Gilles Peskine449bd832023-01-11 14:50:10 +01002523 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2524 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2525 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002526
Gilles Peskine449bd832023-01-11 14:50:10 +01002527 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002528
Gilles Peskine449bd832023-01-11 14:50:10 +01002529 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002530
Gilles Peskine449bd832023-01-11 14:50:10 +01002531 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002532 /*
2533 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2534 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002535 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2536 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2537 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2538 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002539 /*
2540 * 2^-100 error probability, number of rounds computed based on HAC,
2541 * fact 4.48
2542 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002543 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2544 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2545 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2546 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002547 }
2548
Gilles Peskine449bd832023-01-11 14:50:10 +01002549 while (1) {
2550 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002551 /* 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 +01002552 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2553 continue;
2554 }
Jethro Beekman66689272018-02-14 19:24:10 -08002555
2556 k = n * biL;
Gilles Peskine449bd832023-01-11 14:50:10 +01002557 if (k > nbits) {
2558 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2559 }
Jethro Beekman66689272018-02-14 19:24:10 -08002560 X->p[0] |= 1;
2561
Gilles Peskine449bd832023-01-11 14:50:10 +01002562 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2563 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002564
Gilles Peskine449bd832023-01-11 14:50:10 +01002565 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002566 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002567 }
2568 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002569 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002570 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002571 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2572 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002573 */
Jethro Beekman66689272018-02-14 19:24:10 -08002574
2575 X->p[0] |= 2;
2576
Gilles Peskine449bd832023-01-11 14:50:10 +01002577 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2578 if (r == 0) {
2579 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2580 } else if (r == 1) {
2581 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2582 }
Jethro Beekman66689272018-02-14 19:24:10 -08002583
2584 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine449bd832023-01-11 14:50:10 +01002585 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2586 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002587
Gilles Peskine449bd832023-01-11 14:50:10 +01002588 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002589 /*
2590 * First, check small factors for X and Y
2591 * before doing Miller-Rabin on any of them
2592 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002593 if ((ret = mpi_check_small_factors(X)) == 0 &&
2594 (ret = mpi_check_small_factors(&Y)) == 0 &&
2595 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2596 == 0 &&
2597 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2598 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002599 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002600 }
Jethro Beekman66689272018-02-14 19:24:10 -08002601
Gilles Peskine449bd832023-01-11 14:50:10 +01002602 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002603 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002604 }
Jethro Beekman66689272018-02-14 19:24:10 -08002605
2606 /*
2607 * Next candidates. We want to preserve Y = (X-1) / 2 and
2608 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2609 * so up Y by 6 and X by 12.
2610 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002611 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2612 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002613 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002614 }
2615 }
2616
2617cleanup:
2618
Gilles Peskine449bd832023-01-11 14:50:10 +01002619 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002620
Gilles Peskine449bd832023-01-11 14:50:10 +01002621 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002622}
2623
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002627
Paul Bakker23986e52011-04-24 08:57:21 +00002628#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002629
2630static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2631{
2632 { 693, 609, 21 },
2633 { 1764, 868, 28 },
2634 { 768454923, 542167814, 1 }
2635};
2636
Paul Bakker5121ce52009-01-03 21:22:43 +00002637/*
2638 * Checkup routine
2639 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002640int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00002641{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002642 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002644
Gilles Peskine449bd832023-01-11 14:50:10 +01002645 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2646 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002647
Gilles Peskine449bd832023-01-11 14:50:10 +01002648 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2649 "EFE021C2645FD1DC586E69184AF4A31E" \
2650 "D5F53E93B5F123FA41680867BA110131" \
2651 "944FE7952E2517337780CB0DB80E61AA" \
2652 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002653
Gilles Peskine449bd832023-01-11 14:50:10 +01002654 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2655 "B2E7EFD37075B9F03FF989C7C5051C20" \
2656 "34D2A323810251127E7BF8625A4F49A5" \
2657 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2658 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002659
Gilles Peskine449bd832023-01-11 14:50:10 +01002660 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2661 "0066A198186C18C10B2F5ED9B522752A" \
2662 "9830B69916E535C8F047518A889A43A5" \
2663 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002664
Gilles Peskine449bd832023-01-11 14:50:10 +01002665 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002666
Gilles Peskine449bd832023-01-11 14:50:10 +01002667 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2668 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2669 "9E857EA95A03512E2BAE7391688D264A" \
2670 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2671 "8001B72E848A38CAE1C65F78E56ABDEF" \
2672 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2673 "ECF677152EF804370C1A305CAF3B5BF1" \
2674 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002675
Gilles Peskine449bd832023-01-11 14:50:10 +01002676 if (verbose != 0) {
2677 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2678 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002679
Gilles Peskine449bd832023-01-11 14:50:10 +01002680 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2681 if (verbose != 0) {
2682 mbedtls_printf("failed\n");
2683 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002684
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002685 ret = 1;
2686 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002687 }
2688
Gilles Peskine449bd832023-01-11 14:50:10 +01002689 if (verbose != 0) {
2690 mbedtls_printf("passed\n");
2691 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002692
Gilles Peskine449bd832023-01-11 14:50:10 +01002693 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002694
Gilles Peskine449bd832023-01-11 14:50:10 +01002695 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2696 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002697
Gilles Peskine449bd832023-01-11 14:50:10 +01002698 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2699 "6613F26162223DF488E9CD48CC132C7A" \
2700 "0AC93C701B001B092E4E5B9F73BCD27B" \
2701 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002702
Gilles Peskine449bd832023-01-11 14:50:10 +01002703 if (verbose != 0) {
2704 mbedtls_printf(" MPI test #2 (div_mpi): ");
2705 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002706
Gilles Peskine449bd832023-01-11 14:50:10 +01002707 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2708 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2709 if (verbose != 0) {
2710 mbedtls_printf("failed\n");
2711 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002712
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002713 ret = 1;
2714 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002715 }
2716
Gilles Peskine449bd832023-01-11 14:50:10 +01002717 if (verbose != 0) {
2718 mbedtls_printf("passed\n");
2719 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002720
Gilles Peskine449bd832023-01-11 14:50:10 +01002721 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00002722
Gilles Peskine449bd832023-01-11 14:50:10 +01002723 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2724 "36E139AEA55215609D2816998ED020BB" \
2725 "BD96C37890F65171D948E9BC7CBAA4D9" \
2726 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002727
Gilles Peskine449bd832023-01-11 14:50:10 +01002728 if (verbose != 0) {
2729 mbedtls_printf(" MPI test #3 (exp_mod): ");
2730 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002731
Gilles Peskine449bd832023-01-11 14:50:10 +01002732 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2733 if (verbose != 0) {
2734 mbedtls_printf("failed\n");
2735 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002736
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002737 ret = 1;
2738 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002739 }
2740
Gilles Peskine449bd832023-01-11 14:50:10 +01002741 if (verbose != 0) {
2742 mbedtls_printf("passed\n");
2743 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002744
Gilles Peskine449bd832023-01-11 14:50:10 +01002745 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002746
Gilles Peskine449bd832023-01-11 14:50:10 +01002747 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2748 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2749 "C3DBA76456363A10869622EAC2DD84EC" \
2750 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002751
Gilles Peskine449bd832023-01-11 14:50:10 +01002752 if (verbose != 0) {
2753 mbedtls_printf(" MPI test #4 (inv_mod): ");
2754 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002755
Gilles Peskine449bd832023-01-11 14:50:10 +01002756 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2757 if (verbose != 0) {
2758 mbedtls_printf("failed\n");
2759 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002760
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002761 ret = 1;
2762 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002763 }
2764
Gilles Peskine449bd832023-01-11 14:50:10 +01002765 if (verbose != 0) {
2766 mbedtls_printf("passed\n");
2767 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002768
Gilles Peskine449bd832023-01-11 14:50:10 +01002769 if (verbose != 0) {
2770 mbedtls_printf(" MPI test #5 (simple gcd): ");
2771 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002772
Gilles Peskine449bd832023-01-11 14:50:10 +01002773 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2774 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2775 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002776
Gilles Peskine449bd832023-01-11 14:50:10 +01002777 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002778
Gilles Peskine449bd832023-01-11 14:50:10 +01002779 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2780 if (verbose != 0) {
2781 mbedtls_printf("failed at %d\n", i);
2782 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002783
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002784 ret = 1;
2785 goto cleanup;
2786 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002787 }
2788
Gilles Peskine449bd832023-01-11 14:50:10 +01002789 if (verbose != 0) {
2790 mbedtls_printf("passed\n");
2791 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002792
Paul Bakker5121ce52009-01-03 21:22:43 +00002793cleanup:
2794
Gilles Peskine449bd832023-01-11 14:50:10 +01002795 if (ret != 0 && verbose != 0) {
2796 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2797 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002798
Gilles Peskine449bd832023-01-11 14:50:10 +01002799 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2800 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002801
Gilles Peskine449bd832023-01-11 14:50:10 +01002802 if (verbose != 0) {
2803 mbedtls_printf("\n");
2804 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002805
Gilles Peskine449bd832023-01-11 14:50:10 +01002806 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002807}
2808
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002809#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002810
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811#endif /* MBEDTLS_BIGNUM_C */