blob: b62f3f2c370506c04a5d3b4a162daf2a0b7045e4 [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
144 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
145 mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(assign);
146
147 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
148
149 X->s = (int) mbedtls_ct_uint_if(assign, Y->s, X->s);
150
151 mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, assign);
152
153 for (size_t i = Y->n; i < X->n; i++) {
154 X->p[i] &= ~limb_mask;
155 }
156
157cleanup:
158 return ret;
159}
160
161/*
162 * Conditionally swap X and Y, without leaking information
163 * about whether the swap was made or not.
164 * Here it is not ok to simply swap the pointers, which would lead to
165 * different memory access patterns when X and Y are used afterwards.
166 */
167int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
168 mbedtls_mpi *Y,
169 unsigned char swap)
170{
171 int ret = 0;
172 int s;
173 MPI_VALIDATE_RET(X != NULL);
174 MPI_VALIDATE_RET(Y != NULL);
175
176 if (X == Y) {
177 return 0;
178 }
179
180 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
181 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
182
183 s = X->s;
184 X->s = (int) mbedtls_ct_uint_if(swap, Y->s, X->s);
185 Y->s = (int) mbedtls_ct_uint_if(swap, s, Y->s);
186
187 mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, swap);
188
189cleanup:
190 return ret;
191}
192
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500193/* Implementation that should never be optimized out by the compiler */
Gilles Peskine449bd832023-01-11 14:50:10 +0100194static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -0500195{
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 mbedtls_platform_zeroize(v, ciL * n);
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500197}
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000200 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000201 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100202void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000203{
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000205
Paul Bakker6c591fa2011-05-05 11:49:20 +0000206 X->s = 1;
207 X->n = 0;
208 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000209}
210
211/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000212 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000213 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100214void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000215{
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +0000217 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000219
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 if (X->p != NULL) {
221 mbedtls_mpi_zeroize(X->p, X->n);
222 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 }
224
Paul Bakker6c591fa2011-05-05 11:49:20 +0000225 X->s = 1;
226 X->n = 0;
227 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000228}
229
230/*
231 * Enlarge to the specified number of limbs
232 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100233int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi_uint *p;
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000237
Gilles Peskine449bd832023-01-11 14:50:10 +0100238 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
239 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
240 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000241
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 if (X->n < nblimbs) {
243 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
244 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
245 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000246
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 if (X->p != NULL) {
248 memcpy(p, X->p, X->n * ciL);
249 mbedtls_mpi_zeroize(X->p, X->n);
250 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000251 }
252
253 X->n = nblimbs;
254 X->p = p;
255 }
256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000258}
259
260/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100261 * Resize down as much as possible,
262 * while keeping at least the specified number of limbs
263 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100264int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100265{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100267 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000269
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
271 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
272 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100273
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100274 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 if (X->n <= nblimbs) {
276 return mbedtls_mpi_grow(X, nblimbs);
277 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100278 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100279
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 for (i = X->n - 1; i > 0; i--) {
281 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100282 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 }
284 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100285 i++;
286
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100288 i = nblimbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
292 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
293 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 if (X->p != NULL) {
296 memcpy(p, X->p, i * ciL);
297 mbedtls_mpi_zeroize(X->p, X->n);
298 mbedtls_free(X->p);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100299 }
300
301 X->n = i;
302 X->p = p;
303
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100305}
306
Gilles Peskineed32b572021-06-02 22:17:52 +0200307/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100308static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200309{
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 if (limbs == 0) {
311 mbedtls_mpi_free(X);
312 return 0;
313 } else if (X->n == limbs) {
314 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200315 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 return 0;
317 } else {
318 mbedtls_mpi_free(X);
319 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200320 }
321}
322
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100323/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200324 * Copy the contents of Y into X.
325 *
326 * This function is not constant-time. Leading zeros in Y may be removed.
327 *
328 * Ensure that X does not shrink. This is not guaranteed by the public API,
329 * but some code in the bignum module relies on this property, for example
330 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000331 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100332int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000333{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100334 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000335 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 MPI_VALIDATE_RET(X != NULL);
337 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000338
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 if (X == Y) {
340 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200341 }
342
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 if (Y->n == 0) {
344 if (X->n != 0) {
345 X->s = 1;
346 memset(X->p, 0, X->n * ciL);
347 }
348 return 0;
349 }
350
351 for (i = Y->n - 1; i > 0; i--) {
352 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 }
355 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000356 i++;
357
358 X->s = Y->s;
359
Gilles Peskine449bd832023-01-11 14:50:10 +0100360 if (X->n < i) {
361 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
362 } else {
363 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100364 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000367
368cleanup:
369
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000371}
372
373/*
374 * Swap the contents of X and Y
375 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100376void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000377{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 MPI_VALIDATE(X != NULL);
380 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000381
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 memcpy(&T, X, sizeof(mbedtls_mpi));
383 memcpy(X, Y, sizeof(mbedtls_mpi));
384 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000385}
386
Gilles Peskine449bd832023-01-11 14:50:10 +0100387static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100388{
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 if (z >= 0) {
390 return z;
391 }
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100392 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
393 * A naive -z would have undefined behavior.
394 * Write this in a way that makes popular compilers happy (GCC, Clang,
395 * MSVC). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100397}
398
Paul Bakker5121ce52009-01-03 21:22:43 +0000399/*
400 * Set value from integer
401 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100402int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000403{
Janos Follath24eed8d2019-11-22 13:21:35 +0000404 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000406
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
408 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000409
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 X->p[0] = mpi_sint_abs(z);
411 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000412
413cleanup:
414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000416}
417
418/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000419 * Get a specific bit
420 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100421int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000422{
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000424
Gilles Peskine449bd832023-01-11 14:50:10 +0100425 if (X->n * biL <= pos) {
426 return 0;
427 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000430}
431
432/*
433 * Set a bit to a specific value of 0 or 1
434 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100435int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000436{
437 int ret = 0;
438 size_t off = pos / biL;
439 size_t idx = pos % biL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 if (val != 0 && val != 1) {
443 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000444 }
445
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 if (X->n * biL <= pos) {
447 if (val == 0) {
448 return 0;
449 }
450
451 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
452 }
453
454 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000456
457cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000460}
461
462/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200463 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000464 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100465size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000466{
Paul Bakker23986e52011-04-24 08:57:21 +0000467 size_t i, j, count = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 for (i = 0; i < X->n; i++) {
471 for (j = 0; j < biL; j++, count++) {
472 if (((X->p[i] >> j) & 1) != 0) {
473 return count;
474 }
475 }
476 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000477
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000479}
480
481/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200482 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000483 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100484size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000485{
Gilles Peskine449bd832023-01-11 14:50:10 +0100486 return mbedtls_mpi_core_bitlen(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000487}
488
489/*
490 * Return the total size in bytes
491 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100492size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000493{
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000495}
496
497/*
498 * Convert an ASCII character to digit value
499 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100500static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000501{
502 *d = 255;
503
Gilles Peskine449bd832023-01-11 14:50:10 +0100504 if (c >= 0x30 && c <= 0x39) {
505 *d = c - 0x30;
506 }
507 if (c >= 0x41 && c <= 0x46) {
508 *d = c - 0x37;
509 }
510 if (c >= 0x61 && c <= 0x66) {
511 *d = c - 0x57;
512 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000513
Gilles Peskine449bd832023-01-11 14:50:10 +0100514 if (*d >= (mbedtls_mpi_uint) radix) {
515 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
516 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000517
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000519}
520
521/*
522 * Import from an ASCII string
523 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100524int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000525{
Janos Follath24eed8d2019-11-22 13:21:35 +0000526 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000527 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200528 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 mbedtls_mpi_uint d;
530 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100531 MPI_VALIDATE_RET(X != NULL);
532 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000533
Gilles Peskine449bd832023-01-11 14:50:10 +0100534 if (radix < 2 || radix > 16) {
535 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200536 }
537
Gilles Peskine449bd832023-01-11 14:50:10 +0100538 mbedtls_mpi_init(&T);
539
540 if (s[0] == 0) {
541 mbedtls_mpi_free(X);
542 return 0;
543 }
544
545 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200546 ++s;
547 sign = -1;
548 }
549
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000551
Gilles Peskine449bd832023-01-11 14:50:10 +0100552 if (radix == 16) {
Dave Rodgman68ef1d62023-05-18 20:49:03 +0100553 if (slen > SIZE_MAX >> 2) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000555 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Gilles Peskine449bd832023-01-11 14:50:10 +0100557 n = BITS_TO_LIMBS(slen << 2);
558
559 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
560 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
561
562 for (i = slen, j = 0; i > 0; i--, j++) {
563 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
564 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
565 }
566 } else {
567 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
568
569 for (i = 0; i < slen; i++) {
570 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
571 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
572 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000573 }
574 }
575
Gilles Peskine449bd832023-01-11 14:50:10 +0100576 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200577 X->s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100578 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200579
Paul Bakker5121ce52009-01-03 21:22:43 +0000580cleanup:
581
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000585}
586
587/*
Ron Eldora16fa292018-11-20 14:07:01 +0200588 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100590static int mpi_write_hlp(mbedtls_mpi *X, int radix,
591 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000592{
Janos Follath24eed8d2019-11-22 13:21:35 +0000593 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200595 size_t length = 0;
596 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000597
Gilles Peskine449bd832023-01-11 14:50:10 +0100598 do {
599 if (length >= buflen) {
600 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200601 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000602
Gilles Peskine449bd832023-01-11 14:50:10 +0100603 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
604 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200605 /*
606 * Write the residue in the current position, as an ASCII character.
607 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 if (r < 0xA) {
609 *(--p_end) = (char) ('0' + r);
610 } else {
611 *(--p_end) = (char) ('A' + (r - 0xA));
612 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
Ron Eldora16fa292018-11-20 14:07:01 +0200614 length++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
Gilles Peskine449bd832023-01-11 14:50:10 +0100617 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200618 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
620cleanup:
621
Gilles Peskine449bd832023-01-11 14:50:10 +0100622 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000623}
624
625/*
626 * Export into an ASCII string
627 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100628int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
629 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000630{
Paul Bakker23986e52011-04-24 08:57:21 +0000631 int ret = 0;
632 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100635 MPI_VALIDATE_RET(X != NULL);
636 MPI_VALIDATE_RET(olen != NULL);
637 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 if (radix < 2 || radix > 16) {
640 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
641 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
644 if (radix >= 4) {
645 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000646 * `n`. If radix > 4, this might be a strict
647 * overapproximation of the number of
648 * radix-adic digits needed to present `n`. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100649 }
650 if (radix >= 16) {
651 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000652 * present `n`. */
653
Gilles Peskine449bd832023-01-11 14:50:10 +0100654 }
Janos Follath80470622019-03-06 13:43:02 +0000655 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000656 n += 1; /* Compensate for the divisions above, which round down `n`
657 * in case it's not even. */
658 n += 1; /* Potential '-'-sign. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100659 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000660 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Gilles Peskine449bd832023-01-11 14:50:10 +0100662 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100663 *olen = n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100664 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000665 }
666
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100667 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
Gilles Peskine449bd832023-01-11 14:50:10 +0100670 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000671 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000672 buflen--;
673 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000674
Gilles Peskine449bd832023-01-11 14:50:10 +0100675 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000676 int c;
677 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 for (i = X->n, k = 0; i > 0; i--) {
680 for (j = ciL; j > 0; j--) {
681 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000682
Gilles Peskine449bd832023-01-11 14:50:10 +0100683 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000684 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100685 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000687 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000688 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 k = 1;
690 }
691 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100692 } else {
693 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000694
Gilles Peskine449bd832023-01-11 14:50:10 +0100695 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000696 T.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000698
Gilles Peskine449bd832023-01-11 14:50:10 +0100699 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000700 }
701
702 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100703 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
705cleanup:
706
Gilles Peskine449bd832023-01-11 14:50:10 +0100707 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
Gilles Peskine449bd832023-01-11 14:50:10 +0100709 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000710}
711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000713/*
714 * Read X from an opened file
715 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100716int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000717{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000719 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000720 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000721 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000722 * Buffer should have space for (short) label and decimal formatted MPI,
723 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000724 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100725 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000726
Gilles Peskine449bd832023-01-11 14:50:10 +0100727 MPI_VALIDATE_RET(X != NULL);
728 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000729
Gilles Peskine449bd832023-01-11 14:50:10 +0100730 if (radix < 2 || radix > 16) {
731 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
732 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000733
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 memset(s, 0, sizeof(s));
735 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
736 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
737 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
Gilles Peskine449bd832023-01-11 14:50:10 +0100739 slen = strlen(s);
740 if (slen == sizeof(s) - 2) {
741 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
742 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000743
Gilles Peskine449bd832023-01-11 14:50:10 +0100744 if (slen > 0 && s[slen - 1] == '\n') {
745 slen--; s[slen] = '\0';
746 }
747 if (slen > 0 && s[slen - 1] == '\r') {
748 slen--; s[slen] = '\0';
749 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000750
751 p = s + slen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100752 while (p-- > s) {
753 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000754 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100755 }
756 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
Gilles Peskine449bd832023-01-11 14:50:10 +0100758 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000759}
760
761/*
762 * Write X into an opened file (or stdout if fout == NULL)
763 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100764int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000765{
Janos Follath24eed8d2019-11-22 13:21:35 +0000766 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000767 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000768 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000769 * Buffer should have space for (short) label and decimal formatted MPI,
770 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000771 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100772 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
773 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000774
Gilles Peskine449bd832023-01-11 14:50:10 +0100775 if (radix < 2 || radix > 16) {
776 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
777 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000778
Gilles Peskine449bd832023-01-11 14:50:10 +0100779 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
Gilles Peskine449bd832023-01-11 14:50:10 +0100781 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
Gilles Peskine449bd832023-01-11 14:50:10 +0100783 if (p == NULL) {
784 p = "";
785 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000786
Gilles Peskine449bd832023-01-11 14:50:10 +0100787 plen = strlen(p);
788 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000789 s[slen++] = '\r';
790 s[slen++] = '\n';
791
Gilles Peskine449bd832023-01-11 14:50:10 +0100792 if (fout != NULL) {
793 if (fwrite(p, 1, plen, fout) != plen ||
794 fwrite(s, 1, slen, fout) != slen) {
795 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
796 }
797 } else {
798 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000799 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000800
801cleanup:
802
Gilles Peskine449bd832023-01-11 14:50:10 +0100803 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000804}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
807/*
Janos Follatha778a942019-02-13 10:28:28 +0000808 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100809 *
810 * This function is guaranteed to return an MPI with exactly the necessary
811 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000812 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100813int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
814 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000815{
Janos Follath24eed8d2019-11-22 13:21:35 +0000816 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100817 const size_t limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000818
819 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100820 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000821
Gilles Peskine449bd832023-01-11 14:50:10 +0100822 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Janos Follatha778a942019-02-13 10:28:28 +0000823
824cleanup:
825
Janos Follath171a7ef2019-02-15 16:17:45 +0000826 /*
827 * This function is also used to import keys. However, wiping the buffers
828 * upon failure is not necessary because failure only can happen before any
829 * input is copied.
830 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100831 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000832}
833
834/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000835 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100836 *
837 * This function is guaranteed to return an MPI with exactly the necessary
838 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000839 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100840int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000841{
Janos Follath24eed8d2019-11-22 13:21:35 +0000842 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100843 const size_t limbs = CHARS_TO_LIMBS(buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000844
Gilles Peskine449bd832023-01-11 14:50:10 +0100845 MPI_VALIDATE_RET(X != NULL);
846 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000847
Hanno Becker073c1992017-10-17 15:17:27 +0100848 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100849 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
Gilles Peskine449bd832023-01-11 14:50:10 +0100851 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000852
853cleanup:
854
Janos Follath171a7ef2019-02-15 16:17:45 +0000855 /*
856 * This function is also used to import keys. However, wiping the buffers
857 * upon failure is not necessary because failure only can happen before any
858 * input is copied.
859 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100860 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000861}
862
863/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000864 * Export X into unsigned binary data, little endian
865 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100866int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
867 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000868{
Gilles Peskine449bd832023-01-11 14:50:10 +0100869 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Janos Follathe344d0f2019-02-19 16:17:40 +0000870}
871
872/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000873 * Export X into unsigned binary data, big endian
874 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100875int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
876 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000877{
Gilles Peskine449bd832023-01-11 14:50:10 +0100878 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000879}
880
881/*
882 * Left-shift: X <<= count
883 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100884int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000885{
Janos Follath24eed8d2019-11-22 13:21:35 +0000886 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Minos Galanakis0144b352023-05-02 14:02:32 +0100887 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100888 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000889
Gilles Peskine449bd832023-01-11 14:50:10 +0100890 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000891
Gilles Peskine449bd832023-01-11 14:50:10 +0100892 if (X->n * biL < i) {
893 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
894 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000895
896 ret = 0;
897
Minos Galanakis0144b352023-05-02 14:02:32 +0100898 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Paul Bakker5121ce52009-01-03 21:22:43 +0000899cleanup:
900
Gilles Peskine449bd832023-01-11 14:50:10 +0100901 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000902}
903
904/*
905 * Right-shift: X >>= count
906 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100907int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000908{
Gilles Peskine449bd832023-01-11 14:50:10 +0100909 MPI_VALIDATE_RET(X != NULL);
910 if (X->n != 0) {
911 mbedtls_mpi_core_shift_r(X->p, X->n, count);
912 }
913 return 0;
Gilles Peskine66414202022-09-21 15:36:16 +0200914}
915
Paul Bakker5121ce52009-01-03 21:22:43 +0000916/*
917 * Compare unsigned values
918 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100919int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000920{
Paul Bakker23986e52011-04-24 08:57:21 +0000921 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100922 MPI_VALIDATE_RET(X != NULL);
923 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000924
Gilles Peskine449bd832023-01-11 14:50:10 +0100925 for (i = X->n; i > 0; i--) {
926 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000927 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100928 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000929 }
930
Gilles Peskine449bd832023-01-11 14:50:10 +0100931 for (j = Y->n; j > 0; j--) {
932 if (Y->p[j - 1] != 0) {
933 break;
934 }
935 }
936
937 if (i == 0 && j == 0) {
938 return 0;
939 }
940
941 if (i > j) {
942 return 1;
943 }
944 if (j > i) {
945 return -1;
946 }
947
948 for (; i > 0; i--) {
949 if (X->p[i - 1] > Y->p[i - 1]) {
950 return 1;
951 }
952 if (X->p[i - 1] < Y->p[i - 1]) {
953 return -1;
954 }
955 }
956
957 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000958}
959
960/*
961 * Compare signed values
962 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100963int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000964{
Paul Bakker23986e52011-04-24 08:57:21 +0000965 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100966 MPI_VALIDATE_RET(X != NULL);
967 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000968
Gilles Peskine449bd832023-01-11 14:50:10 +0100969 for (i = X->n; i > 0; i--) {
970 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000971 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100972 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000973 }
974
Gilles Peskine449bd832023-01-11 14:50:10 +0100975 for (j = Y->n; j > 0; j--) {
976 if (Y->p[j - 1] != 0) {
977 break;
978 }
979 }
980
981 if (i == 0 && j == 0) {
982 return 0;
983 }
984
985 if (i > j) {
986 return X->s;
987 }
988 if (j > i) {
989 return -Y->s;
990 }
991
992 if (X->s > 0 && Y->s < 0) {
993 return 1;
994 }
995 if (Y->s > 0 && X->s < 0) {
996 return -1;
997 }
998
999 for (; i > 0; i--) {
1000 if (X->p[i - 1] > Y->p[i - 1]) {
1001 return X->s;
1002 }
1003 if (X->p[i - 1] < Y->p[i - 1]) {
1004 return -X->s;
1005 }
1006 }
1007
1008 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001009}
1010
Janos Follathee6abce2019-09-05 14:47:19 +01001011/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 * Compare signed values
1013 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001014int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +00001015{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 mbedtls_mpi Y;
1017 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001018 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001019
Gilles Peskine449bd832023-01-11 14:50:10 +01001020 *p = mpi_sint_abs(z);
1021 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 Y.n = 1;
1023 Y.p = p;
1024
Gilles Peskine449bd832023-01-11 14:50:10 +01001025 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00001026}
1027
1028/*
1029 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1030 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001031int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001032{
Janos Follath24eed8d2019-11-22 13:21:35 +00001033 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001034 size_t j;
Gilles Peskine449bd832023-01-11 14:50:10 +01001035 MPI_VALIDATE_RET(X != NULL);
1036 MPI_VALIDATE_RET(A != NULL);
1037 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001038
Gilles Peskine449bd832023-01-11 14:50:10 +01001039 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001041 }
1042
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 if (X != A) {
1044 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1045 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001046
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001047 /*
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001048 * X must always be positive as a result of unsigned additions.
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001049 */
1050 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001051
Gilles Peskine449bd832023-01-11 14:50:10 +01001052 for (j = B->n; j > 0; j--) {
1053 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001054 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001055 }
1056 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001057
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001058 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1059 * and B is 0 (of any size). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001060 if (j == 0) {
1061 return 0;
1062 }
Gilles Peskinedb14a9d2022-11-15 22:59:00 +01001063
Gilles Peskine449bd832023-01-11 14:50:10 +01001064 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001065
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001066 /* j is the number of non-zero limbs of B. Add those to X. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001067
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001068 mbedtls_mpi_uint *p = X->p;
1069
Gilles Peskine449bd832023-01-11 14:50:10 +01001070 mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j);
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001071
1072 p += j;
1073
1074 /* Now propagate any carry */
Paul Bakker5121ce52009-01-03 21:22:43 +00001075
Gilles Peskine449bd832023-01-11 14:50:10 +01001076 while (c != 0) {
1077 if (j >= X->n) {
1078 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +01001079 p = X->p + j;
Paul Bakker5121ce52009-01-03 21:22:43 +00001080 }
1081
Gilles Peskine449bd832023-01-11 14:50:10 +01001082 *p += c; c = (*p < c); j++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001083 }
1084
1085cleanup:
1086
Gilles Peskine449bd832023-01-11 14:50:10 +01001087 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001088}
1089
Paul Bakker5121ce52009-01-03 21:22:43 +00001090/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001091 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001092 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001093int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001094{
Janos Follath24eed8d2019-11-22 13:21:35 +00001095 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001096 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001097 mbedtls_mpi_uint carry;
Gilles Peskine449bd832023-01-11 14:50:10 +01001098 MPI_VALIDATE_RET(X != NULL);
1099 MPI_VALIDATE_RET(A != NULL);
1100 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001101
Gilles Peskine449bd832023-01-11 14:50:10 +01001102 for (n = B->n; n > 0; n--) {
1103 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001104 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001105 }
1106 }
1107 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001108 /* B >= (2^ciL)^n > A */
1109 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1110 goto cleanup;
1111 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001112
Gilles Peskine449bd832023-01-11 14:50:10 +01001113 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001114
1115 /* Set the high limbs of X to match A. Don't touch the lower limbs
1116 * because X might be aliased to B, and we must not overwrite the
1117 * significant digits of B. */
Aaron M. Uckoaf67d2c2023-01-17 11:52:22 -05001118 if (A->n > n && A != X) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001119 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1120 }
1121 if (X->n > A->n) {
1122 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1123 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001124
Gilles Peskine449bd832023-01-11 14:50:10 +01001125 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1126 if (carry != 0) {
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001127 /* Propagate the carry through the rest of X. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001128 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001129
1130 /* If we have further carry/borrow, the result is negative. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001131 if (carry != 0) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001132 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1133 goto cleanup;
1134 }
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001135 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001136
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001137 /* X should always be positive as a result of unsigned subtractions. */
1138 X->s = 1;
1139
Paul Bakker5121ce52009-01-03 21:22:43 +00001140cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001141 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001142}
1143
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001144/* Common function for signed addition and subtraction.
1145 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001146 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001147static int add_sub_mpi(mbedtls_mpi *X,
1148 const mbedtls_mpi *A, const mbedtls_mpi *B,
1149 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001150{
Hanno Becker73d7d792018-12-11 10:35:51 +00001151 int ret, s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001152 MPI_VALIDATE_RET(X != NULL);
1153 MPI_VALIDATE_RET(A != NULL);
1154 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001155
Hanno Becker73d7d792018-12-11 10:35:51 +00001156 s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001157 if (A->s * B->s * flip_B < 0) {
1158 int cmp = mbedtls_mpi_cmp_abs(A, B);
1159 if (cmp >= 0) {
1160 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001161 /* If |A| = |B|, the result is 0 and we must set the sign bit
1162 * to +1 regardless of which of A or B was negative. Otherwise,
1163 * since |A| > |B|, the sign is the sign of A. */
1164 X->s = cmp == 0 ? 1 : s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001165 } else {
1166 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001167 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 X->s = -s;
1169 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001170 } else {
1171 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 X->s = s;
1173 }
1174
1175cleanup:
1176
Gilles Peskine449bd832023-01-11 14:50:10 +01001177 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001178}
1179
1180/*
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001181 * Signed addition: X = A + B
1182 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001183int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001184{
Gilles Peskine449bd832023-01-11 14:50:10 +01001185 return add_sub_mpi(X, A, B, 1);
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001186}
1187
1188/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001189 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001191int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001192{
Gilles Peskine449bd832023-01-11 14:50:10 +01001193 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001194}
1195
1196/*
1197 * Signed addition: X = A + b
1198 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001199int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001200{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001201 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001203 MPI_VALIDATE_RET(X != NULL);
1204 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
Gilles Peskine449bd832023-01-11 14:50:10 +01001206 p[0] = mpi_sint_abs(b);
1207 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001208 B.n = 1;
1209 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001210
Gilles Peskine449bd832023-01-11 14:50:10 +01001211 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001212}
1213
1214/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001215 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001216 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001217int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001218{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001219 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001221 MPI_VALIDATE_RET(X != NULL);
1222 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001223
Gilles Peskine449bd832023-01-11 14:50:10 +01001224 p[0] = mpi_sint_abs(b);
1225 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001226 B.n = 1;
1227 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001228
Gilles Peskine449bd832023-01-11 14:50:10 +01001229 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001230}
1231
Paul Bakker5121ce52009-01-03 21:22:43 +00001232/*
1233 * Baseline multiplication: X = A * B (HAC 14.12)
1234 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001235int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001236{
Janos Follath24eed8d2019-11-22 13:21:35 +00001237 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001238 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001240 int result_is_zero = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001241 MPI_VALIDATE_RET(X != NULL);
1242 MPI_VALIDATE_RET(A != NULL);
1243 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001244
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001245 mbedtls_mpi_init(&TA);
1246 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001247
Gilles Peskine449bd832023-01-11 14:50:10 +01001248 if (X == A) {
1249 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1250 }
1251 if (X == B) {
1252 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1253 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001254
Gilles Peskine449bd832023-01-11 14:50:10 +01001255 for (i = A->n; i > 0; i--) {
1256 if (A->p[i - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001257 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001258 }
1259 }
1260 if (i == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001261 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001262 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001263
Gilles Peskine449bd832023-01-11 14:50:10 +01001264 for (j = B->n; j > 0; j--) {
1265 if (B->p[j - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001266 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001267 }
1268 }
1269 if (j == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001270 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001271 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001272
Gilles Peskine449bd832023-01-11 14:50:10 +01001273 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1274 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001275
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001276 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
Hanno Beckerda763de2022-04-13 06:50:02 +01001278 /* If the result is 0, we don't shortcut the operation, which reduces
1279 * but does not eliminate side channels leaking the zero-ness. We do
1280 * need to take care to set the sign bit properly since the library does
1281 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001282 if (result_is_zero) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001283 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001284 } else {
Hanno Beckerda763de2022-04-13 06:50:02 +01001285 X->s = A->s * B->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001286 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001287
1288cleanup:
1289
Gilles Peskine449bd832023-01-11 14:50:10 +01001290 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001291
Gilles Peskine449bd832023-01-11 14:50:10 +01001292 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001293}
1294
1295/*
1296 * Baseline multiplication: X = A * b
1297 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001298int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001299{
Gilles Peskine449bd832023-01-11 14:50:10 +01001300 MPI_VALIDATE_RET(X != NULL);
1301 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001302
Hanno Becker35771312022-04-14 11:52:11 +01001303 size_t n = A->n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001304 while (n > 0 && A->p[n - 1] == 0) {
Hanno Becker35771312022-04-14 11:52:11 +01001305 --n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001306 }
Hanno Becker35771312022-04-14 11:52:11 +01001307
Hanno Becker74a11a32022-04-06 06:27:00 +01001308 /* The general method below doesn't work if b==0. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001309 if (b == 0 || n == 0) {
1310 return mbedtls_mpi_lset(X, 0);
1311 }
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001312
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001313 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001314 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001315 /* In general, A * b requires 1 limb more than b. If
1316 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1317 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001318 * copy() will take care of the growth if needed. However, experimentally,
1319 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001320 * calls to calloc() in ECP code, presumably because it reuses the
1321 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001322 * grow to its final size.
1323 *
1324 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1325 * A,X can be the same. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001326 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1327 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1328 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001329
1330cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001331 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001332}
1333
1334/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001335 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1336 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001337 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001338static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1339 mbedtls_mpi_uint u0,
1340 mbedtls_mpi_uint d,
1341 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001342{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001343#if defined(MBEDTLS_HAVE_UDBL)
1344 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001345#else
Simon Butcher9803d072016-01-03 00:24:34 +00001346 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001347 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001348 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1349 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001350 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001351#endif
1352
Simon Butcher15b15d12015-11-26 19:35:03 +00001353 /*
1354 * Check for overflow
1355 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001356 if (0 == d || u1 >= d) {
1357 if (r != NULL) {
1358 *r = ~(mbedtls_mpi_uint) 0u;
1359 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001360
Gilles Peskine449bd832023-01-11 14:50:10 +01001361 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001362 }
1363
1364#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001365 dividend = (mbedtls_t_udbl) u1 << biL;
1366 dividend |= (mbedtls_t_udbl) u0;
1367 quotient = dividend / d;
Gilles Peskine449bd832023-01-11 14:50:10 +01001368 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1369 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1370 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001371
Gilles Peskine449bd832023-01-11 14:50:10 +01001372 if (r != NULL) {
1373 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1374 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001375
1376 return (mbedtls_mpi_uint) quotient;
1377#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001378
1379 /*
1380 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1381 * Vol. 2 - Seminumerical Algorithms, Knuth
1382 */
1383
1384 /*
1385 * Normalize the divisor, d, and dividend, u0, u1
1386 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001387 s = mbedtls_mpi_core_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001388 d = d << s;
1389
1390 u1 = u1 << s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001391 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001392 u0 = u0 << s;
1393
1394 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001395 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001396
1397 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001398 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001399
1400 /*
1401 * Find the first quotient and remainder
1402 */
1403 q1 = u1 / d1;
1404 r0 = u1 - d1 * q1;
1405
Gilles Peskine449bd832023-01-11 14:50:10 +01001406 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001407 q1 -= 1;
1408 r0 += d1;
1409
Gilles Peskine449bd832023-01-11 14:50:10 +01001410 if (r0 >= radix) {
1411 break;
1412 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001413 }
1414
Gilles Peskine449bd832023-01-11 14:50:10 +01001415 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001416 q0 = rAX / d1;
1417 r0 = rAX - q0 * d1;
1418
Gilles Peskine449bd832023-01-11 14:50:10 +01001419 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001420 q0 -= 1;
1421 r0 += d1;
1422
Gilles Peskine449bd832023-01-11 14:50:10 +01001423 if (r0 >= radix) {
1424 break;
1425 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001426 }
1427
Gilles Peskine449bd832023-01-11 14:50:10 +01001428 if (r != NULL) {
1429 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1430 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001431
1432 quotient = q1 * radix + q0;
1433
1434 return quotient;
1435#endif
1436}
1437
1438/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001441int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1442 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001443{
Janos Follath24eed8d2019-11-22 13:21:35 +00001444 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001445 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001447 mbedtls_mpi_uint TP2[3];
Gilles Peskine449bd832023-01-11 14:50:10 +01001448 MPI_VALIDATE_RET(A != NULL);
1449 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001450
Gilles Peskine449bd832023-01-11 14:50:10 +01001451 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1452 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1453 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001454
Gilles Peskine449bd832023-01-11 14:50:10 +01001455 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1456 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001457 /*
1458 * Avoid dynamic memory allocations for constant-size T2.
1459 *
1460 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1461 * so nobody increase the size of the MPI and we're safe to use an on-stack
1462 * buffer.
1463 */
Alexander K35d6d462019-10-31 14:46:45 +03001464 T2.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001465 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001466 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
Gilles Peskine449bd832023-01-11 14:50:10 +01001468 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1469 if (Q != NULL) {
1470 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1471 }
1472 if (R != NULL) {
1473 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1474 }
1475 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001476 }
1477
Gilles Peskine449bd832023-01-11 14:50:10 +01001478 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1479 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001480 X.s = Y.s = 1;
1481
Gilles Peskine449bd832023-01-11 14:50:10 +01001482 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1483 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1484 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001485
Gilles Peskine449bd832023-01-11 14:50:10 +01001486 k = mbedtls_mpi_bitlen(&Y) % biL;
1487 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001488 k = biL - 1 - k;
Gilles Peskine449bd832023-01-11 14:50:10 +01001489 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1490 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1491 } else {
1492 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001493 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001494
1495 n = X.n - 1;
1496 t = Y.n - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001497 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001498
Gilles Peskine449bd832023-01-11 14:50:10 +01001499 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 Z.p[n - t]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001501 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001503 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001504
Gilles Peskine449bd832023-01-11 14:50:10 +01001505 for (i = n; i > t; i--) {
1506 if (X.p[i] >= Y.p[t]) {
1507 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1508 } else {
1509 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1510 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001511 }
1512
Gilles Peskine449bd832023-01-11 14:50:10 +01001513 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1514 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001515 T2.p[2] = X.p[i];
1516
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 Z.p[i - t - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001518 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001519 Z.p[i - t - 1]--;
1520
Gilles Peskine449bd832023-01-11 14:50:10 +01001521 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1522 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001523 T1.p[1] = Y.p[t];
Gilles Peskine449bd832023-01-11 14:50:10 +01001524 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1525 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
Gilles Peskine449bd832023-01-11 14:50:10 +01001527 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1528 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1529 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001530
Gilles Peskine449bd832023-01-11 14:50:10 +01001531 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1532 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1533 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1534 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001535 Z.p[i - t - 1]--;
1536 }
1537 }
1538
Gilles Peskine449bd832023-01-11 14:50:10 +01001539 if (Q != NULL) {
1540 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001541 Q->s = A->s * B->s;
1542 }
1543
Gilles Peskine449bd832023-01-11 14:50:10 +01001544 if (R != NULL) {
1545 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001546 X.s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001547 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001548
Gilles Peskine449bd832023-01-11 14:50:10 +01001549 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 R->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001551 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001552 }
1553
1554cleanup:
1555
Gilles Peskine449bd832023-01-11 14:50:10 +01001556 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1557 mbedtls_mpi_free(&T1);
1558 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
Gilles Peskine449bd832023-01-11 14:50:10 +01001560 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001561}
1562
1563/*
1564 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001565 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001566int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1567 const mbedtls_mpi *A,
1568 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001569{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001570 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001572 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001573
Gilles Peskine449bd832023-01-11 14:50:10 +01001574 p[0] = mpi_sint_abs(b);
1575 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001576 B.n = 1;
1577 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001578
Gilles Peskine449bd832023-01-11 14:50:10 +01001579 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001580}
1581
1582/*
1583 * Modulo: R = A mod B
1584 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001585int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001586{
Janos Follath24eed8d2019-11-22 13:21:35 +00001587 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01001588 MPI_VALIDATE_RET(R != NULL);
1589 MPI_VALIDATE_RET(A != NULL);
1590 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001591
Gilles Peskine449bd832023-01-11 14:50:10 +01001592 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1593 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1594 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001595
Gilles Peskine449bd832023-01-11 14:50:10 +01001596 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001597
Gilles Peskine449bd832023-01-11 14:50:10 +01001598 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1599 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1600 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Gilles Peskine449bd832023-01-11 14:50:10 +01001602 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1603 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1604 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001605
1606cleanup:
1607
Gilles Peskine449bd832023-01-11 14:50:10 +01001608 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001609}
1610
1611/*
1612 * Modulo: r = A mod b
1613 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001614int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001615{
Paul Bakker23986e52011-04-24 08:57:21 +00001616 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 mbedtls_mpi_uint x, y, z;
Gilles Peskine449bd832023-01-11 14:50:10 +01001618 MPI_VALIDATE_RET(r != NULL);
1619 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Gilles Peskine449bd832023-01-11 14:50:10 +01001621 if (b == 0) {
1622 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1623 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
Gilles Peskine449bd832023-01-11 14:50:10 +01001625 if (b < 0) {
1626 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1627 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001628
1629 /*
1630 * handle trivial cases
1631 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001632 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 *r = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001634 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001635 }
1636
Gilles Peskine449bd832023-01-11 14:50:10 +01001637 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001638 *r = A->p[0] & 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001639 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 }
1641
1642 /*
1643 * general case
1644 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001645 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001646 x = A->p[i - 1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001647 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 z = y / b;
1649 y -= z * b;
1650
1651 x <<= biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001652 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 z = y / b;
1654 y -= z * b;
1655 }
1656
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001657 /*
1658 * If A is negative, then the current y represents a negative value.
1659 * Flipping it to the positive side.
1660 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001661 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001662 y = b - y;
Gilles Peskine449bd832023-01-11 14:50:10 +01001663 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001664
Paul Bakker5121ce52009-01-03 21:22:43 +00001665 *r = y;
1666
Gilles Peskine449bd832023-01-11 14:50:10 +01001667 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001668}
1669
Gilles Peskine449bd832023-01-11 14:50:10 +01001670static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001671{
Gilles Peskine449bd832023-01-11 14:50:10 +01001672 *mm = mbedtls_mpi_core_montmul_init(N->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001673}
1674
Tom Cosgrove93842842022-08-05 16:59:43 +01001675/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1676 *
1677 * \param[in,out] A One of the numbers to multiply.
1678 * It must have at least as many limbs as N
1679 * (A->n >= N->n), and any limbs beyond n are ignored.
1680 * On successful completion, A contains the result of
1681 * the multiplication A * B * R^-1 mod N where
1682 * R = (2^ciL)^n.
1683 * \param[in] B One of the numbers to multiply.
1684 * It must be nonzero and must not have more limbs than N
1685 * (B->n <= N->n).
Tom Cosgrove40d22942022-08-17 06:42:44 +01001686 * \param[in] N The modulus. \p N must be odd.
Tom Cosgrove93842842022-08-05 16:59:43 +01001687 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1688 * This is -N^-1 mod 2^ciL.
1689 * \param[in,out] T A bignum for temporary storage.
1690 * It must be at least twice the limb size of N plus 1
1691 * (T->n >= 2 * N->n + 1).
1692 * Its initial content is unused and
1693 * its final content is indeterminate.
Tom Cosgrove5dd97e62022-08-30 14:31:49 +01001694 * It does not get reallocated.
Tom Cosgrove93842842022-08-05 16:59:43 +01001695 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001696static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1697 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1698 mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001699{
Gilles Peskine449bd832023-01-11 14:50:10 +01001700 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 +00001701}
1702
1703/*
1704 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001705 *
Tom Cosgrove93842842022-08-05 16:59:43 +01001706 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001707 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001708static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1709 mbedtls_mpi_uint mm, mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001710{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001711 mbedtls_mpi_uint z = 1;
1712 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001713
Paul Bakker8ddb6452013-02-27 14:56:33 +01001714 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001715 U.p = &z;
1716
Gilles Peskine449bd832023-01-11 14:50:10 +01001717 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001718}
1719
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001720/**
1721 * Select an MPI from a table without leaking the index.
1722 *
1723 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1724 * reads the entire table in order to avoid leaking the value of idx to an
1725 * attacker able to observe memory access patterns.
1726 *
1727 * \param[out] R Where to write the selected MPI.
1728 * \param[in] T The table to read from.
1729 * \param[in] T_size The number of elements in the table.
1730 * \param[in] idx The index of the element to select;
1731 * this must satisfy 0 <= idx < T_size.
1732 *
1733 * \return \c 0 on success, or a negative error code.
1734 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001735static 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 +01001736{
1737 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1738
Gilles Peskine449bd832023-01-11 14:50:10 +01001739 for (size_t i = 0; i < T_size; i++) {
1740 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
1741 (unsigned char) mbedtls_ct_size_bool_eq(i,
1742 idx)));
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001743 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001744
1745cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001746 return ret;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001747}
1748
Paul Bakker5121ce52009-01-03 21:22:43 +00001749/*
1750 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1751 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001752int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1753 const mbedtls_mpi *E, const mbedtls_mpi *N,
1754 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00001755{
Janos Follath24eed8d2019-11-22 13:21:35 +00001756 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath74601202022-11-21 15:54:20 +00001757 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00001758 size_t i, j, nblimbs;
1759 size_t bufsize, nbits;
Paul Elliott1748de12023-02-13 15:35:35 +00001760 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine449bd832023-01-11 14:50:10 +01001762 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001763 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001764
Gilles Peskine449bd832023-01-11 14:50:10 +01001765 MPI_VALIDATE_RET(X != NULL);
1766 MPI_VALIDATE_RET(A != NULL);
1767 MPI_VALIDATE_RET(E != NULL);
1768 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001769
Gilles Peskine449bd832023-01-11 14:50:10 +01001770 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1771 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1772 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001773
Gilles Peskine449bd832023-01-11 14:50:10 +01001774 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1775 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1776 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00001777
Gilles Peskine449bd832023-01-11 14:50:10 +01001778 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1779 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1780 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1781 }
Chris Jones9246d042020-11-25 15:12:39 +00001782
Paul Bakkerf6198c12012-05-16 08:02:29 +00001783 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001784 * Init temps and window size
1785 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001786 mpi_montg_init(&mm, N);
1787 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
1788 mbedtls_mpi_init(&Apos);
1789 mbedtls_mpi_init(&WW);
1790 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00001791
Gilles Peskine449bd832023-01-11 14:50:10 +01001792 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00001793
Gilles Peskine449bd832023-01-11 14:50:10 +01001794 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1795 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Gilles Peskine449bd832023-01-11 14:50:10 +01001797#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
1798 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath7fa11b82022-11-21 14:48:02 +00001799 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +01001800 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001801#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001802
Janos Follathc8d66d52022-11-22 10:47:10 +00001803 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath06000952022-11-22 10:18:06 +00001804
Paul Bakker5121ce52009-01-03 21:22:43 +00001805 /*
Janos Follathbe54ca72022-11-21 16:14:54 +00001806 * This function is not constant-trace: its memory accesses depend on the
1807 * exponent value. To defend against timing attacks, callers (such as RSA
1808 * and DHM) should use exponent blinding. However this is not enough if the
1809 * adversary can find the exponent in a single trace, so this function
1810 * takes extra precautions against adversaries who can observe memory
1811 * access patterns.
Janos Follathf08b40e2022-11-11 15:56:38 +00001812 *
Janos Follathbe54ca72022-11-21 16:14:54 +00001813 * This function performs a series of multiplications by table elements and
1814 * squarings, and we want the prevent the adversary from finding out which
1815 * table element was used, and from distinguishing between multiplications
1816 * and squarings. Firstly, when multiplying by an element of the window
1817 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
1818 * squarings as having a different memory access patterns from other
1819 * multiplications. So secondly, we put the accumulator X in the table as
1820 * well, and also do a constant-trace table lookup to multiply by X.
1821 *
1822 * This way, all multiplications take the form of a lookup-and-multiply.
1823 * The number of lookup-and-multiply operations inside each iteration of
1824 * the main loop still depends on the bits of the exponent, but since the
1825 * other operations in the loop don't have an easily recognizable memory
1826 * trace, an adversary is unlikely to be able to observe the exact
1827 * patterns.
1828 *
1829 * An adversary may still be able to recover the exponent if they can
1830 * observe both memory accesses and branches. However, branch prediction
1831 * exploitation typically requires many traces of execution over the same
1832 * data, which is defeated by randomized blinding.
Janos Follath84461482022-11-21 14:31:22 +00001833 *
1834 * To achieve this, we make a copy of X and we use the table entry in each
1835 * calculation from this point on.
Janos Follath8e7d6a02022-10-04 13:27:40 +01001836 */
Janos Follathc8d66d52022-11-22 10:47:10 +00001837 const size_t x_index = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001838 mbedtls_mpi_init(&W[x_index]);
1839 mbedtls_mpi_copy(&W[x_index], X);
Janos Follath84461482022-11-21 14:31:22 +00001840
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 j = N->n + 1;
Tom Cosgrove93842842022-08-05 16:59:43 +01001842 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 * and mpi_montred() calls later. Here we ensure that W[1] and X are
1844 * large enough, and later we'll grow other W[i] to the same length.
1845 * They must not be shrunk midway through this function!
1846 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001847 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1848 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
1849 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001850
1851 /*
Paul Bakker50546922012-05-19 08:40:49 +00001852 * Compensate for negative A (and correct at the end)
1853 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001854 neg = (A->s == -1);
1855 if (neg) {
1856 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00001857 Apos.s = 1;
1858 A = &Apos;
1859 }
1860
1861 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 * If 1st call, pre-compute R^2 mod N
1863 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001864 if (prec_RR == NULL || prec_RR->p == NULL) {
1865 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
1866 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
1867 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001868
Gilles Peskine449bd832023-01-11 14:50:10 +01001869 if (prec_RR != NULL) {
1870 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
1871 }
1872 } else {
1873 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
1876 /*
1877 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1878 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001879 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1880 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001881 /* This should be a no-op because W[1] is already that large before
1882 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Tom Cosgrove93842842022-08-05 16:59:43 +01001883 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001884 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
1885 } else {
1886 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001887 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001889 /* Note that this is safe because W[1] always has at least N->n limbs
1890 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001891 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
1893 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001894 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001895 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001896 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1897 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
Janos Follathc8d66d52022-11-22 10:47:10 +00001899
Gilles Peskine449bd832023-01-11 14:50:10 +01001900 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001901 /*
Janos Follath74601202022-11-21 15:54:20 +00001902 * W[i] = W[1] ^ i
1903 *
1904 * The first bit of the sliding window is always 1 and therefore we
1905 * only need to store the second half of the table.
Janos Follathc8d66d52022-11-22 10:47:10 +00001906 *
1907 * (There are two special elements in the table: W[0] for the
1908 * accumulator/result and W[1] for A in Montgomery form. Both of these
1909 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00001910 */
Janos Follath74601202022-11-21 15:54:20 +00001911 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001912
Gilles Peskine449bd832023-01-11 14:50:10 +01001913 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1914 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
Gilles Peskine449bd832023-01-11 14:50:10 +01001916 for (i = 0; i < window_bitsize - 1; i++) {
1917 mpi_montmul(&W[j], &W[j], N, mm, &T);
1918 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01001919
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 /*
1921 * W[i] = W[i - 1] * W[1]
1922 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001923 for (i = j + 1; i < w_table_used_size; i++) {
1924 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1925 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001926
Gilles Peskine449bd832023-01-11 14:50:10 +01001927 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 }
1929 }
1930
1931 nblimbs = E->n;
1932 bufsize = 0;
1933 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001934 state = 0;
1935
Gilles Peskine449bd832023-01-11 14:50:10 +01001936 while (1) {
1937 if (bufsize == 0) {
1938 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001940 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
Paul Bakker0d7702c2013-10-29 16:18:35 +01001942 nblimbs--;
1943
Gilles Peskine449bd832023-01-11 14:50:10 +01001944 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001945 }
1946
1947 bufsize--;
1948
1949 ei = (E->p[nblimbs] >> bufsize) & 1;
1950
1951 /*
1952 * skip leading 0s
1953 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001954 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001955 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01001956 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001957
Gilles Peskine449bd832023-01-11 14:50:10 +01001958 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001959 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001960 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00001961 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001962 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1963 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001964 continue;
1965 }
1966
1967 /*
1968 * add ei to current window
1969 */
1970 state = 2;
1971
1972 nbits++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001973 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
Gilles Peskine449bd832023-01-11 14:50:10 +01001975 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001976 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001977 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001979 for (i = 0; i < window_bitsize; i++) {
1980 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1981 x_index));
1982 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001983 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
1985 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001986 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001988 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1989 exponent_bits_in_window));
1990 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
1992 state--;
1993 nbits = 0;
Janos Follath7fa11b82022-11-21 14:48:02 +00001994 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001995 }
1996 }
1997
1998 /*
1999 * process the remaining bits
2000 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002001 for (i = 0; i < nbits; i++) {
2002 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
2003 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002004
Janos Follath7fa11b82022-11-21 14:48:02 +00002005 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Gilles Peskine449bd832023-01-11 14:50:10 +01002007 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
2008 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
2009 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01002010 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002011 }
2012
2013 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01002014 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002015 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002016 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
Gilles Peskine449bd832023-01-11 14:50:10 +01002018 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath8e7d6a02022-10-04 13:27:40 +01002019 W[x_index].s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002020 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00002021 }
2022
Janos Follath8e7d6a02022-10-04 13:27:40 +01002023 /*
2024 * Load the result in the output variable.
2025 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002026 mbedtls_mpi_copy(X, &W[x_index]);
Janos Follath8e7d6a02022-10-04 13:27:40 +01002027
Paul Bakker5121ce52009-01-03 21:22:43 +00002028cleanup:
2029
Janos Follathb2c2fca2022-11-21 15:05:31 +00002030 /* The first bit of the sliding window is always 1 and therefore the first
2031 * half of the table was unused. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002032 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
2033 mbedtls_mpi_free(&W[i]);
2034 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002035
Gilles Peskine449bd832023-01-11 14:50:10 +01002036 mbedtls_mpi_free(&W[x_index]);
2037 mbedtls_mpi_free(&W[1]);
2038 mbedtls_mpi_free(&T);
2039 mbedtls_mpi_free(&Apos);
2040 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00002041
Gilles Peskine449bd832023-01-11 14:50:10 +01002042 if (prec_RR == NULL || prec_RR->p == NULL) {
2043 mbedtls_mpi_free(&RR);
2044 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
Gilles Peskine449bd832023-01-11 14:50:10 +01002046 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002047}
2048
Paul Bakker5121ce52009-01-03 21:22:43 +00002049/*
2050 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2051 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002052int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002053{
Janos Follath24eed8d2019-11-22 13:21:35 +00002054 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002055 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002056 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002057
Gilles Peskine449bd832023-01-11 14:50:10 +01002058 MPI_VALIDATE_RET(G != NULL);
2059 MPI_VALIDATE_RET(A != NULL);
2060 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002061
Gilles Peskine449bd832023-01-11 14:50:10 +01002062 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002063
Gilles Peskine449bd832023-01-11 14:50:10 +01002064 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2065 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002066
Gilles Peskine449bd832023-01-11 14:50:10 +01002067 lz = mbedtls_mpi_lsb(&TA);
2068 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002069
Gilles Peskine27253bc2021-06-09 13:26:43 +02002070 /* The loop below gives the correct result when A==0 but not when B==0.
2071 * So have a special case for B==0. Leverage the fact that we just
2072 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2073 * slightly more efficient than cmp_int(). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002074 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
2075 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02002076 goto cleanup;
2077 }
2078
Gilles Peskine449bd832023-01-11 14:50:10 +01002079 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002080 lz = lzt;
Gilles Peskine449bd832023-01-11 14:50:10 +01002081 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002082
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 TA.s = TB.s = 1;
2084
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002085 /* We mostly follow the procedure described in HAC 14.54, but with some
2086 * minor differences:
2087 * - Sequences of multiplications or divisions by 2 are grouped into a
2088 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002089 * - The procedure in HAC assumes that 0 < TB <= TA.
2090 * - The condition TB <= TA is not actually necessary for correctness.
2091 * TA and TB have symmetric roles except for the loop termination
2092 * condition, and the shifts at the beginning of the loop body
2093 * remove any significance from the ordering of TA vs TB before
2094 * the shifts.
2095 * - If TA = 0, the loop goes through 0 iterations and the result is
2096 * correctly TB.
2097 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002098 *
2099 * For the correctness proof below, decompose the original values of
2100 * A and B as
2101 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2102 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2103 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2104 * and gcd(A',B') is odd or 0.
2105 *
2106 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2107 * The code maintains the following invariant:
2108 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002109 */
2110
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002111 /* Proof that the loop terminates:
2112 * At each iteration, either the right-shift by 1 is made on a nonzero
2113 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2114 * by at least 1, or the right-shift by 1 is made on zero and then
2115 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2116 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2117 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002118 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002119 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002120 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2121 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002123 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2124 * TA-TB is even so the division by 2 has an integer result.
2125 * Invariant (I) is preserved since any odd divisor of both TA and TB
2126 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08002127 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002128 * divides TA.
2129 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002130 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2131 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2132 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2133 } else {
2134 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2135 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002136 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002137 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002138 }
2139
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002140 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2141 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2142 * - If there was at least one loop iteration, then one of TA or TB is odd,
2143 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2144 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2145 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002146 * 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 +02002147 */
2148
Gilles Peskine449bd832023-01-11 14:50:10 +01002149 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2150 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002151
2152cleanup:
2153
Gilles Peskine449bd832023-01-11 14:50:10 +01002154 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
Gilles Peskine449bd832023-01-11 14:50:10 +01002156 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002157}
2158
Paul Bakker33dc46b2014-04-30 16:11:39 +02002159/*
2160 * Fill X with size bytes of random.
Gilles Peskine22cdd0c2022-10-27 20:15:13 +02002161 * The bytes returned from the RNG are used in a specific order which
2162 * is suitable for deterministic ECDSA (see the specification of
2163 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Paul Bakker33dc46b2014-04-30 16:11:39 +02002164 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002165int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2166 int (*f_rng)(void *, unsigned char *, size_t),
2167 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002168{
Janos Follath24eed8d2019-11-22 13:21:35 +00002169 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01002170 const size_t limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002171
Gilles Peskine449bd832023-01-11 14:50:10 +01002172 MPI_VALIDATE_RET(X != NULL);
2173 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002174
Hanno Beckerda1655a2017-10-18 14:21:44 +01002175 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +01002176 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2177 if (size == 0) {
2178 return 0;
2179 }
Paul Bakker287781a2011-03-26 13:18:49 +00002180
Gilles Peskine449bd832023-01-11 14:50:10 +01002181 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002182
2183cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002184 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002185}
2186
Gilles Peskine449bd832023-01-11 14:50:10 +01002187int mbedtls_mpi_random(mbedtls_mpi *X,
2188 mbedtls_mpi_sint min,
2189 const mbedtls_mpi *N,
2190 int (*f_rng)(void *, unsigned char *, size_t),
2191 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002192{
Gilles Peskine449bd832023-01-11 14:50:10 +01002193 if (min < 0) {
2194 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2195 }
2196 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2197 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2198 }
Gilles Peskine1e918f42021-03-29 22:14:51 +02002199
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002200 /* Ensure that target MPI has exactly the same number of limbs
2201 * as the upper bound, even if the upper bound has leading zeros.
Gilles Peskine6b7ce962022-12-15 15:04:33 +01002202 * This is necessary for mbedtls_mpi_core_random. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002203 int ret = mbedtls_mpi_resize_clear(X, N->n);
2204 if (ret != 0) {
2205 return ret;
2206 }
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002207
Gilles Peskine449bd832023-01-11 14:50:10 +01002208 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002209}
2210
Paul Bakker5121ce52009-01-03 21:22:43 +00002211/*
2212 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2213 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002214int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002215{
Janos Follath24eed8d2019-11-22 13:21:35 +00002216 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine449bd832023-01-11 14:50:10 +01002218 MPI_VALIDATE_RET(X != NULL);
2219 MPI_VALIDATE_RET(A != NULL);
2220 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002221
Gilles Peskine449bd832023-01-11 14:50:10 +01002222 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2223 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2224 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002225
Gilles Peskine449bd832023-01-11 14:50:10 +01002226 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2227 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2228 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002229
Gilles Peskine449bd832023-01-11 14:50:10 +01002230 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
Gilles Peskine449bd832023-01-11 14:50:10 +01002232 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002233 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002234 goto cleanup;
2235 }
2236
Gilles Peskine449bd832023-01-11 14:50:10 +01002237 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2238 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2239 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2240 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002241
Gilles Peskine449bd832023-01-11 14:50:10 +01002242 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2243 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2244 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2245 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002246
Gilles Peskine449bd832023-01-11 14:50:10 +01002247 do {
2248 while ((TU.p[0] & 1) == 0) {
2249 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
Gilles Peskine449bd832023-01-11 14:50:10 +01002251 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2252 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2253 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002254 }
2255
Gilles Peskine449bd832023-01-11 14:50:10 +01002256 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2257 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002258 }
2259
Gilles Peskine449bd832023-01-11 14:50:10 +01002260 while ((TV.p[0] & 1) == 0) {
2261 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
Gilles Peskine449bd832023-01-11 14:50:10 +01002263 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2264 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2265 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002266 }
2267
Gilles Peskine449bd832023-01-11 14:50:10 +01002268 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2269 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 }
2271
Gilles Peskine449bd832023-01-11 14:50:10 +01002272 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2273 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2274 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2275 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2276 } else {
2277 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2278 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2279 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002280 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002281 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2282
2283 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2284 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002285 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
Gilles Peskine449bd832023-01-11 14:50:10 +01002287 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2288 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2289 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
Gilles Peskine449bd832023-01-11 14:50:10 +01002291 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
2293cleanup:
2294
Gilles Peskine449bd832023-01-11 14:50:10 +01002295 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2296 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2297 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
Gilles Peskine449bd832023-01-11 14:50:10 +01002299 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002300}
2301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002303
Paul Bakker5121ce52009-01-03 21:22:43 +00002304static const int small_prime[] =
2305{
Gilles Peskine449bd832023-01-11 14:50:10 +01002306 3, 5, 7, 11, 13, 17, 19, 23,
2307 29, 31, 37, 41, 43, 47, 53, 59,
2308 61, 67, 71, 73, 79, 83, 89, 97,
2309 101, 103, 107, 109, 113, 127, 131, 137,
2310 139, 149, 151, 157, 163, 167, 173, 179,
2311 181, 191, 193, 197, 199, 211, 223, 227,
2312 229, 233, 239, 241, 251, 257, 263, 269,
2313 271, 277, 281, 283, 293, 307, 311, 313,
2314 317, 331, 337, 347, 349, 353, 359, 367,
2315 373, 379, 383, 389, 397, 401, 409, 419,
2316 421, 431, 433, 439, 443, 449, 457, 461,
2317 463, 467, 479, 487, 491, 499, 503, 509,
2318 521, 523, 541, 547, 557, 563, 569, 571,
2319 577, 587, 593, 599, 601, 607, 613, 617,
2320 619, 631, 641, 643, 647, 653, 659, 661,
2321 673, 677, 683, 691, 701, 709, 719, 727,
2322 733, 739, 743, 751, 757, 761, 769, 773,
2323 787, 797, 809, 811, 821, 823, 827, 829,
2324 839, 853, 857, 859, 863, 877, 881, 883,
2325 887, 907, 911, 919, 929, 937, 941, 947,
2326 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002327};
2328
2329/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002330 * Small divisors test (X must be positive)
2331 *
2332 * Return values:
2333 * 0: no small factor (possible prime, more tests needed)
2334 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002336 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002337 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002338static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002339{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002340 int ret = 0;
2341 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Gilles Peskine449bd832023-01-11 14:50:10 +01002344 if ((X->p[0] & 1) == 0) {
2345 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2346 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002347
Gilles Peskine449bd832023-01-11 14:50:10 +01002348 for (i = 0; small_prime[i] > 0; i++) {
2349 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2350 return 1;
2351 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002352
Gilles Peskine449bd832023-01-11 14:50:10 +01002353 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
Gilles Peskine449bd832023-01-11 14:50:10 +01002355 if (r == 0) {
2356 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2357 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002358 }
2359
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002360cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002361 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002362}
2363
2364/*
2365 * Miller-Rabin pseudo-primality test (HAC 4.24)
2366 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002367static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2368 int (*f_rng)(void *, unsigned char *, size_t),
2369 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002370{
Pascal Junodb99183d2015-03-11 16:49:45 +01002371 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002372 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002374
Gilles Peskine449bd832023-01-11 14:50:10 +01002375 MPI_VALIDATE_RET(X != NULL);
2376 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002377
Gilles Peskine449bd832023-01-11 14:50:10 +01002378 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2379 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2380 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002381
Paul Bakker5121ce52009-01-03 21:22:43 +00002382 /*
2383 * W = |X| - 1
2384 * R = W >> lsb( W )
2385 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002386 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2387 s = mbedtls_mpi_lsb(&W);
2388 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2389 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
Gilles Peskine449bd832023-01-11 14:50:10 +01002391 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002392 /*
2393 * pick a random A, 1 < A < |X| - 1
2394 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002395 count = 0;
2396 do {
Gilles Peskine449bd832023-01-11 14:50:10 +01002397 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002398
Gilles Peskine449bd832023-01-11 14:50:10 +01002399 j = mbedtls_mpi_bitlen(&A);
2400 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002401 if (j > k) {
Gilles Peskine449bd832023-01-11 14:50:10 +01002402 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002403 }
2404
2405 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002406 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2407 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002408 }
2409
Gilles Peskine449bd832023-01-11 14:50:10 +01002410 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2411 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
2413 /*
2414 * A = A^R mod |X|
2415 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002416 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
Gilles Peskine449bd832023-01-11 14:50:10 +01002418 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2419 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002420 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01002421 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
2423 j = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002424 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002425 /*
2426 * A = A * A mod |X|
2427 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002428 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2429 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
Gilles Peskine449bd832023-01-11 14:50:10 +01002431 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002432 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01002433 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002434
2435 j++;
2436 }
2437
2438 /*
2439 * not prime if A != |X| - 1 or A == 1
2440 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002441 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2442 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002444 break;
2445 }
2446 }
2447
2448cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002449 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2450 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2451 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
Gilles Peskine449bd832023-01-11 14:50:10 +01002453 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002454}
2455
2456/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002457 * Pseudo-primality test: small factors, then Miller-Rabin
2458 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002459int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2460 int (*f_rng)(void *, unsigned char *, size_t),
2461 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002462{
Janos Follath24eed8d2019-11-22 13:21:35 +00002463 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002464 mbedtls_mpi XX;
Gilles Peskine449bd832023-01-11 14:50:10 +01002465 MPI_VALIDATE_RET(X != NULL);
2466 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002467
2468 XX.s = 1;
2469 XX.n = X->n;
2470 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002471
Gilles Peskine449bd832023-01-11 14:50:10 +01002472 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2473 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2474 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002475 }
2476
Gilles Peskine449bd832023-01-11 14:50:10 +01002477 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2478 return 0;
2479 }
2480
2481 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2482 if (ret == 1) {
2483 return 0;
2484 }
2485
2486 return ret;
2487 }
2488
2489 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002490}
2491
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002492/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002493 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002494 *
Janos Follathf301d232018-08-14 13:34:01 +01002495 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2496 * be either 1024 bits or 1536 bits long, and flags must contain
2497 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002498 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002499int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2500 int (*f_rng)(void *, unsigned char *, size_t),
2501 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002502{
Jethro Beekman66689272018-02-14 19:24:10 -08002503#ifdef MBEDTLS_HAVE_INT64
2504// ceil(2^63.5)
2505#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2506#else
2507// ceil(2^31.5)
2508#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2509#endif
2510 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002511 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002512 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002513 mbedtls_mpi_uint r;
2514 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002515
Gilles Peskine449bd832023-01-11 14:50:10 +01002516 MPI_VALIDATE_RET(X != NULL);
2517 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002518
Gilles Peskine449bd832023-01-11 14:50:10 +01002519 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2520 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2521 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002522
Gilles Peskine449bd832023-01-11 14:50:10 +01002523 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002524
Gilles Peskine449bd832023-01-11 14:50:10 +01002525 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002526
Gilles Peskine449bd832023-01-11 14:50:10 +01002527 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002528 /*
2529 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2530 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002531 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2532 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2533 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2534 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002535 /*
2536 * 2^-100 error probability, number of rounds computed based on HAC,
2537 * fact 4.48
2538 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002539 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2540 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2541 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2542 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002543 }
2544
Gilles Peskine449bd832023-01-11 14:50:10 +01002545 while (1) {
2546 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002547 /* 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 +01002548 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2549 continue;
2550 }
Jethro Beekman66689272018-02-14 19:24:10 -08002551
2552 k = n * biL;
Gilles Peskine449bd832023-01-11 14:50:10 +01002553 if (k > nbits) {
2554 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2555 }
Jethro Beekman66689272018-02-14 19:24:10 -08002556 X->p[0] |= 1;
2557
Gilles Peskine449bd832023-01-11 14:50:10 +01002558 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2559 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002560
Gilles Peskine449bd832023-01-11 14:50:10 +01002561 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002562 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002563 }
2564 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002565 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002566 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002567 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2568 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002569 */
Jethro Beekman66689272018-02-14 19:24:10 -08002570
2571 X->p[0] |= 2;
2572
Gilles Peskine449bd832023-01-11 14:50:10 +01002573 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2574 if (r == 0) {
2575 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2576 } else if (r == 1) {
2577 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2578 }
Jethro Beekman66689272018-02-14 19:24:10 -08002579
2580 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine449bd832023-01-11 14:50:10 +01002581 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2582 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002583
Gilles Peskine449bd832023-01-11 14:50:10 +01002584 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002585 /*
2586 * First, check small factors for X and Y
2587 * before doing Miller-Rabin on any of them
2588 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002589 if ((ret = mpi_check_small_factors(X)) == 0 &&
2590 (ret = mpi_check_small_factors(&Y)) == 0 &&
2591 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2592 == 0 &&
2593 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2594 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002595 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002596 }
Jethro Beekman66689272018-02-14 19:24:10 -08002597
Gilles Peskine449bd832023-01-11 14:50:10 +01002598 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
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
2602 /*
2603 * Next candidates. We want to preserve Y = (X-1) / 2 and
2604 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2605 * so up Y by 6 and X by 12.
2606 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002607 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2608 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002609 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002610 }
2611 }
2612
2613cleanup:
2614
Gilles Peskine449bd832023-01-11 14:50:10 +01002615 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002616
Gilles Peskine449bd832023-01-11 14:50:10 +01002617 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002618}
2619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002620#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002623
Paul Bakker23986e52011-04-24 08:57:21 +00002624#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002625
2626static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2627{
2628 { 693, 609, 21 },
2629 { 1764, 868, 28 },
2630 { 768454923, 542167814, 1 }
2631};
2632
Paul Bakker5121ce52009-01-03 21:22:43 +00002633/*
2634 * Checkup routine
2635 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002636int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00002637{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002638 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002639 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002640
Gilles Peskine449bd832023-01-11 14:50:10 +01002641 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2642 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002643
Gilles Peskine449bd832023-01-11 14:50:10 +01002644 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2645 "EFE021C2645FD1DC586E69184AF4A31E" \
2646 "D5F53E93B5F123FA41680867BA110131" \
2647 "944FE7952E2517337780CB0DB80E61AA" \
2648 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002649
Gilles Peskine449bd832023-01-11 14:50:10 +01002650 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2651 "B2E7EFD37075B9F03FF989C7C5051C20" \
2652 "34D2A323810251127E7BF8625A4F49A5" \
2653 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2654 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Gilles Peskine449bd832023-01-11 14:50:10 +01002656 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2657 "0066A198186C18C10B2F5ED9B522752A" \
2658 "9830B69916E535C8F047518A889A43A5" \
2659 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002660
Gilles Peskine449bd832023-01-11 14:50:10 +01002661 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002662
Gilles Peskine449bd832023-01-11 14:50:10 +01002663 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2664 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2665 "9E857EA95A03512E2BAE7391688D264A" \
2666 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2667 "8001B72E848A38CAE1C65F78E56ABDEF" \
2668 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2669 "ECF677152EF804370C1A305CAF3B5BF1" \
2670 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002671
Gilles Peskine449bd832023-01-11 14:50:10 +01002672 if (verbose != 0) {
2673 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2674 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002675
Gilles Peskine449bd832023-01-11 14:50:10 +01002676 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2677 if (verbose != 0) {
2678 mbedtls_printf("failed\n");
2679 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002680
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002681 ret = 1;
2682 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002683 }
2684
Gilles Peskine449bd832023-01-11 14:50:10 +01002685 if (verbose != 0) {
2686 mbedtls_printf("passed\n");
2687 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002688
Gilles Peskine449bd832023-01-11 14:50:10 +01002689 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
Gilles Peskine449bd832023-01-11 14:50:10 +01002691 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2692 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002693
Gilles Peskine449bd832023-01-11 14:50:10 +01002694 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2695 "6613F26162223DF488E9CD48CC132C7A" \
2696 "0AC93C701B001B092E4E5B9F73BCD27B" \
2697 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002698
Gilles Peskine449bd832023-01-11 14:50:10 +01002699 if (verbose != 0) {
2700 mbedtls_printf(" MPI test #2 (div_mpi): ");
2701 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002702
Gilles Peskine449bd832023-01-11 14:50:10 +01002703 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2704 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2705 if (verbose != 0) {
2706 mbedtls_printf("failed\n");
2707 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002708
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002709 ret = 1;
2710 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002711 }
2712
Gilles Peskine449bd832023-01-11 14:50:10 +01002713 if (verbose != 0) {
2714 mbedtls_printf("passed\n");
2715 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002716
Gilles Peskine449bd832023-01-11 14:50:10 +01002717 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00002718
Gilles Peskine449bd832023-01-11 14:50:10 +01002719 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2720 "36E139AEA55215609D2816998ED020BB" \
2721 "BD96C37890F65171D948E9BC7CBAA4D9" \
2722 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002723
Gilles Peskine449bd832023-01-11 14:50:10 +01002724 if (verbose != 0) {
2725 mbedtls_printf(" MPI test #3 (exp_mod): ");
2726 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002727
Gilles Peskine449bd832023-01-11 14:50:10 +01002728 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2729 if (verbose != 0) {
2730 mbedtls_printf("failed\n");
2731 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002732
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002733 ret = 1;
2734 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002735 }
2736
Gilles Peskine449bd832023-01-11 14:50:10 +01002737 if (verbose != 0) {
2738 mbedtls_printf("passed\n");
2739 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002740
Gilles Peskine449bd832023-01-11 14:50:10 +01002741 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002742
Gilles Peskine449bd832023-01-11 14:50:10 +01002743 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2744 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2745 "C3DBA76456363A10869622EAC2DD84EC" \
2746 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002747
Gilles Peskine449bd832023-01-11 14:50:10 +01002748 if (verbose != 0) {
2749 mbedtls_printf(" MPI test #4 (inv_mod): ");
2750 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002751
Gilles Peskine449bd832023-01-11 14:50:10 +01002752 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2753 if (verbose != 0) {
2754 mbedtls_printf("failed\n");
2755 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002756
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002757 ret = 1;
2758 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002759 }
2760
Gilles Peskine449bd832023-01-11 14:50:10 +01002761 if (verbose != 0) {
2762 mbedtls_printf("passed\n");
2763 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002764
Gilles Peskine449bd832023-01-11 14:50:10 +01002765 if (verbose != 0) {
2766 mbedtls_printf(" MPI test #5 (simple gcd): ");
2767 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002768
Gilles Peskine449bd832023-01-11 14:50:10 +01002769 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2770 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2771 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002772
Gilles Peskine449bd832023-01-11 14:50:10 +01002773 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002774
Gilles Peskine449bd832023-01-11 14:50:10 +01002775 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2776 if (verbose != 0) {
2777 mbedtls_printf("failed at %d\n", i);
2778 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002779
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002780 ret = 1;
2781 goto cleanup;
2782 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002783 }
2784
Gilles Peskine449bd832023-01-11 14:50:10 +01002785 if (verbose != 0) {
2786 mbedtls_printf("passed\n");
2787 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002788
Paul Bakker5121ce52009-01-03 21:22:43 +00002789cleanup:
2790
Gilles Peskine449bd832023-01-11 14:50:10 +01002791 if (ret != 0 && verbose != 0) {
2792 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2793 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002794
Gilles Peskine449bd832023-01-11 14:50:10 +01002795 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2796 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002797
Gilles Peskine449bd832023-01-11 14:50:10 +01002798 if (verbose != 0) {
2799 mbedtls_printf("\n");
2800 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002801
Gilles Peskine449bd832023-01-11 14:50:10 +01002802 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002803}
2804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002805#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807#endif /* MBEDTLS_BIGNUM_C */