blob: f02b1ac84168da6897951a40ad02d4e55a762372 [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
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050057/* Implementation that should never be optimized out by the compiler */
Tom Cosgrovebc345e82023-07-25 15:17:39 +010058#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050059
Paul Bakker5121ce52009-01-03 21:22:43 +000060/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000061 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000062 */
Gilles Peskine449bd832023-01-11 14:50:10 +010063void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000064{
Gilles Peskine449bd832023-01-11 14:50:10 +010065 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +000066
Paul Bakker6c591fa2011-05-05 11:49:20 +000067 X->s = 1;
68 X->n = 0;
69 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000070}
71
72/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000073 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000074 */
Gilles Peskine449bd832023-01-11 14:50:10 +010075void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000076{
Gilles Peskine449bd832023-01-11 14:50:10 +010077 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +000078 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010079 }
Paul Bakker5121ce52009-01-03 21:22:43 +000080
Gilles Peskine449bd832023-01-11 14:50:10 +010081 if (X->p != NULL) {
Tom Cosgrove46259f62023-07-18 16:44:14 +010082 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +000083 }
84
Paul Bakker6c591fa2011-05-05 11:49:20 +000085 X->s = 1;
86 X->n = 0;
87 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000088}
89
90/*
91 * Enlarge to the specified number of limbs
92 */
Gilles Peskine449bd832023-01-11 14:50:10 +010093int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +000094{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095 mbedtls_mpi_uint *p;
Gilles Peskine449bd832023-01-11 14:50:10 +010096 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +000097
Gilles Peskine449bd832023-01-11 14:50:10 +010098 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
99 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
100 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000101
Gilles Peskine449bd832023-01-11 14:50:10 +0100102 if (X->n < nblimbs) {
103 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
104 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
105 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
Gilles Peskine449bd832023-01-11 14:50:10 +0100107 if (X->p != NULL) {
108 memcpy(p, X->p, X->n * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100109 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Gilles Peskine053022f2023-06-29 19:26:48 +0200112 /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
113 * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
114 X->n = (unsigned short) nblimbs;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115 X->p = p;
116 }
117
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000119}
120
121/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100122 * Resize down as much as possible,
123 * while keeping at least the specified number of limbs
124 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100125int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100126{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100128 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000130
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
132 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
133 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100134
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100135 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 if (X->n <= nblimbs) {
137 return mbedtls_mpi_grow(X, nblimbs);
138 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100139 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100140
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 for (i = X->n - 1; i > 0; i--) {
142 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 }
145 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100146 i++;
147
Gilles Peskine449bd832023-01-11 14:50:10 +0100148 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149 i = nblimbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100151
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
153 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
154 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155
Gilles Peskine449bd832023-01-11 14:50:10 +0100156 if (X->p != NULL) {
157 memcpy(p, X->p, i * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100158 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159 }
160
Gilles Peskine053022f2023-06-29 19:26:48 +0200161 /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
162 * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
163 X->n = (unsigned short) i;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 X->p = p;
165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100167}
168
Gilles Peskineed32b572021-06-02 22:17:52 +0200169/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100170static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200171{
Gilles Peskine449bd832023-01-11 14:50:10 +0100172 if (limbs == 0) {
173 mbedtls_mpi_free(X);
174 return 0;
175 } else if (X->n == limbs) {
176 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200177 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 return 0;
179 } else {
180 mbedtls_mpi_free(X);
181 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200182 }
183}
184
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100185/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200186 * Copy the contents of Y into X.
187 *
188 * This function is not constant-time. Leading zeros in Y may be removed.
189 *
190 * Ensure that X does not shrink. This is not guaranteed by the public API,
191 * but some code in the bignum module relies on this property, for example
192 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000193 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100194int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000195{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100196 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000197 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 MPI_VALIDATE_RET(X != NULL);
199 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000200
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 if (X == Y) {
202 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200203 }
204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 if (Y->n == 0) {
206 if (X->n != 0) {
207 X->s = 1;
208 memset(X->p, 0, X->n * ciL);
209 }
210 return 0;
211 }
212
213 for (i = Y->n - 1; i > 0; i--) {
214 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000215 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 }
217 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000218 i++;
219
220 X->s = Y->s;
221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 if (X->n < i) {
223 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
224 } else {
225 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100226 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000227
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000229
230cleanup:
231
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000233}
234
235/*
236 * Swap the contents of X and Y
237 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100238void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000239{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 MPI_VALIDATE(X != NULL);
242 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000243
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 memcpy(&T, X, sizeof(mbedtls_mpi));
245 memcpy(X, Y, sizeof(mbedtls_mpi));
246 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000247}
248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100250{
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 if (z >= 0) {
252 return z;
253 }
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100254 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
255 * A naive -z would have undefined behavior.
256 * Write this in a way that makes popular compilers happy (GCC, Clang,
257 * MSVC). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100258 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100259}
260
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100261/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
262 * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
Dave Rodgman960eca92023-08-09 20:43:18 +0100263#define TO_SIGN(x) ((((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100264
Paul Bakker5121ce52009-01-03 21:22:43 +0000265/*
266 * Set value from integer
267 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100268int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000269{
Janos Follath24eed8d2019-11-22 13:21:35 +0000270 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000272
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
274 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000275
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 X->p[0] = mpi_sint_abs(z);
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100277 X->s = TO_SIGN(z);
Paul Bakker5121ce52009-01-03 21:22:43 +0000278
279cleanup:
280
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000282}
283
284/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000285 * Get a specific bit
286 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100287int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000288{
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 if (X->n * biL <= pos) {
292 return 0;
293 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000296}
297
298/*
299 * Set a bit to a specific value of 0 or 1
300 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100301int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000302{
303 int ret = 0;
304 size_t off = pos / biL;
305 size_t idx = pos % biL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100306 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000307
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 if (val != 0 && val != 1) {
309 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000310 }
311
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 if (X->n * biL <= pos) {
313 if (val == 0) {
314 return 0;
315 }
316
317 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
318 }
319
320 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000322
323cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200324
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000326}
327
328/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200329 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000330 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100331size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000332{
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100333 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000335
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100336#if defined(__has_builtin)
337#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
338 #define mbedtls_mpi_uint_ctz __builtin_ctz
339#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
340 #define mbedtls_mpi_uint_ctz __builtin_ctzl
341#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
342 #define mbedtls_mpi_uint_ctz __builtin_ctzll
343#endif
344#endif
345
346#if defined(mbedtls_mpi_uint_ctz)
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 for (i = 0; i < X->n; i++) {
Dave Rodgman960eca92023-08-09 20:43:18 +0100348 if (X->p[i] != 0) {
349 return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
350 }
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100351 }
352#else
353 size_t count = 0;
354 for (i = 0; i < X->n; i++) {
355 for (size_t j = 0; j < biL; j++, count++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 if (((X->p[i] >> j) & 1) != 0) {
357 return count;
358 }
359 }
360 }
Dave Rodgmanfa703e32023-08-09 18:56:07 +0100361#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000362
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000364}
365
366/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200367 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000368 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100369size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000370{
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 return mbedtls_mpi_core_bitlen(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000372}
373
374/*
375 * Return the total size in bytes
376 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100377size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000378{
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000380}
381
382/*
383 * Convert an ASCII character to digit value
384 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100385static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000386{
387 *d = 255;
388
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 if (c >= 0x30 && c <= 0x39) {
390 *d = c - 0x30;
391 }
392 if (c >= 0x41 && c <= 0x46) {
393 *d = c - 0x37;
394 }
395 if (c >= 0x61 && c <= 0x66) {
396 *d = c - 0x57;
397 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 if (*d >= (mbedtls_mpi_uint) radix) {
400 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
401 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000402
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000404}
405
406/*
407 * Import from an ASCII string
408 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100409int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000410{
Janos Follath24eed8d2019-11-22 13:21:35 +0000411 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000412 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200413 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200414 mbedtls_mpi_uint d;
415 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 MPI_VALIDATE_RET(X != NULL);
417 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000418
Gilles Peskine449bd832023-01-11 14:50:10 +0100419 if (radix < 2 || radix > 16) {
420 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200421 }
422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 mbedtls_mpi_init(&T);
424
425 if (s[0] == 0) {
426 mbedtls_mpi_free(X);
427 return 0;
428 }
429
430 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200431 ++s;
432 sign = -1;
433 }
434
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000436
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 if (radix == 16) {
Dave Rodgman68ef1d62023-05-18 20:49:03 +0100438 if (slen > SIZE_MAX >> 2) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000440 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 n = BITS_TO_LIMBS(slen << 2);
443
444 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
445 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
446
447 for (i = slen, j = 0; i > 0; i--, j++) {
448 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
449 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
450 }
451 } else {
452 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
453
454 for (i = 0; i < slen; i++) {
455 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
456 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
457 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 }
460
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200462 X->s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200464
Paul Bakker5121ce52009-01-03 21:22:43 +0000465cleanup:
466
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000470}
471
472/*
Ron Eldora16fa292018-11-20 14:07:01 +0200473 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100475static int mpi_write_hlp(mbedtls_mpi *X, int radix,
476 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000477{
Janos Follath24eed8d2019-11-22 13:21:35 +0000478 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200480 size_t length = 0;
481 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 do {
484 if (length >= buflen) {
485 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200486 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000487
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
489 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200490 /*
491 * Write the residue in the current position, as an ASCII character.
492 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 if (r < 0xA) {
494 *(--p_end) = (char) ('0' + r);
495 } else {
496 *(--p_end) = (char) ('A' + (r - 0xA));
497 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000498
Ron Eldora16fa292018-11-20 14:07:01 +0200499 length++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200503 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000504
505cleanup:
506
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000508}
509
510/*
511 * Export into an ASCII string
512 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100513int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
514 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000515{
Paul Bakker23986e52011-04-24 08:57:21 +0000516 int ret = 0;
517 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000518 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 MPI_VALIDATE_RET(X != NULL);
521 MPI_VALIDATE_RET(olen != NULL);
522 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000523
Gilles Peskine449bd832023-01-11 14:50:10 +0100524 if (radix < 2 || radix > 16) {
525 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
526 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000527
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
529 if (radix >= 4) {
530 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000531 * `n`. If radix > 4, this might be a strict
532 * overapproximation of the number of
533 * radix-adic digits needed to present `n`. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100534 }
535 if (radix >= 16) {
536 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000537 * present `n`. */
538
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 }
Janos Follath80470622019-03-06 13:43:02 +0000540 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000541 n += 1; /* Compensate for the divisions above, which round down `n`
542 * in case it's not even. */
543 n += 1; /* Potential '-'-sign. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100544 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000545 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100548 *olen = n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000550 }
551
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100552 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000554
Gilles Peskine449bd832023-01-11 14:50:10 +0100555 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000556 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000557 buflen--;
558 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Gilles Peskine449bd832023-01-11 14:50:10 +0100560 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000561 int c;
562 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 for (i = X->n, k = 0; i > 0; i--) {
565 for (j = ciL; j > 0; j--) {
566 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000567
Gilles Peskine449bd832023-01-11 14:50:10 +0100568 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000569 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000571
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000572 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000573 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 k = 1;
575 }
576 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100577 } else {
578 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000579
Gilles Peskine449bd832023-01-11 14:50:10 +0100580 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000581 T.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000583
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000585 }
586
587 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100588 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000589
590cleanup:
591
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000593
Gilles Peskine449bd832023-01-11 14:50:10 +0100594 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000595}
596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000598/*
599 * Read X from an opened file
600 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100601int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000602{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000604 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000606 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000607 * Buffer should have space for (short) label and decimal formatted MPI,
608 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000609 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100610 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 MPI_VALIDATE_RET(X != NULL);
613 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000614
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 if (radix < 2 || radix > 16) {
616 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
617 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000618
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 memset(s, 0, sizeof(s));
620 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
621 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
622 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
Gilles Peskine449bd832023-01-11 14:50:10 +0100624 slen = strlen(s);
625 if (slen == sizeof(s) - 2) {
626 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
627 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000628
Gilles Peskine449bd832023-01-11 14:50:10 +0100629 if (slen > 0 && s[slen - 1] == '\n') {
630 slen--; s[slen] = '\0';
631 }
632 if (slen > 0 && s[slen - 1] == '\r') {
633 slen--; s[slen] = '\0';
634 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000635
636 p = s + slen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100637 while (p-- > s) {
638 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000639 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100640 }
641 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000644}
645
646/*
647 * Write X into an opened file (or stdout if fout == NULL)
648 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100649int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000650{
Janos Follath24eed8d2019-11-22 13:21:35 +0000651 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000652 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000653 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000654 * Buffer should have space for (short) label and decimal formatted MPI,
655 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000656 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100657 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
658 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000659
Gilles Peskine449bd832023-01-11 14:50:10 +0100660 if (radix < 2 || radix > 16) {
661 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
662 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
Gilles Peskine449bd832023-01-11 14:50:10 +0100664 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
Gilles Peskine449bd832023-01-11 14:50:10 +0100666 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 if (p == NULL) {
669 p = "";
670 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
Gilles Peskine449bd832023-01-11 14:50:10 +0100672 plen = strlen(p);
673 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000674 s[slen++] = '\r';
675 s[slen++] = '\n';
676
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 if (fout != NULL) {
678 if (fwrite(p, 1, plen, fout) != plen ||
679 fwrite(s, 1, slen, fout) != slen) {
680 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
681 }
682 } else {
683 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000684 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000685
686cleanup:
687
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000689}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692/*
Janos Follatha778a942019-02-13 10:28:28 +0000693 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100694 *
695 * This function is guaranteed to return an MPI with exactly the necessary
696 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000697 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100698int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
699 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000700{
Janos Follath24eed8d2019-11-22 13:21:35 +0000701 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100702 const size_t limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000703
704 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100705 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000706
Gilles Peskine449bd832023-01-11 14:50:10 +0100707 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Janos Follatha778a942019-02-13 10:28:28 +0000708
709cleanup:
710
Janos Follath171a7ef2019-02-15 16:17:45 +0000711 /*
712 * This function is also used to import keys. However, wiping the buffers
713 * upon failure is not necessary because failure only can happen before any
714 * input is copied.
715 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000717}
718
719/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000720 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100721 *
722 * This function is guaranteed to return an MPI with exactly the necessary
723 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000724 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100725int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000726{
Janos Follath24eed8d2019-11-22 13:21:35 +0000727 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 const size_t limbs = CHARS_TO_LIMBS(buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Gilles Peskine449bd832023-01-11 14:50:10 +0100730 MPI_VALIDATE_RET(X != NULL);
731 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000732
Hanno Becker073c1992017-10-17 15:17:27 +0100733 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
Gilles Peskine449bd832023-01-11 14:50:10 +0100736 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
738cleanup:
739
Janos Follath171a7ef2019-02-15 16:17:45 +0000740 /*
741 * This function is also used to import keys. However, wiping the buffers
742 * upon failure is not necessary because failure only can happen before any
743 * input is copied.
744 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100745 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000746}
747
748/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000749 * Export X into unsigned binary data, little endian
750 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100751int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
752 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000753{
Gilles Peskine449bd832023-01-11 14:50:10 +0100754 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Janos Follathe344d0f2019-02-19 16:17:40 +0000755}
756
757/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000758 * Export X into unsigned binary data, big endian
759 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100760int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
761 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000762{
Gilles Peskine449bd832023-01-11 14:50:10 +0100763 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000764}
765
766/*
767 * Left-shift: X <<= count
768 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100769int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000770{
Janos Follath24eed8d2019-11-22 13:21:35 +0000771 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Minos Galanakis0144b352023-05-02 14:02:32 +0100772 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100773 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
Gilles Peskine449bd832023-01-11 14:50:10 +0100775 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000776
Gilles Peskine449bd832023-01-11 14:50:10 +0100777 if (X->n * biL < i) {
778 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
779 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
781 ret = 0;
782
Minos Galanakis0144b352023-05-02 14:02:32 +0100783 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Paul Bakker5121ce52009-01-03 21:22:43 +0000784cleanup:
785
Gilles Peskine449bd832023-01-11 14:50:10 +0100786 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000787}
788
789/*
790 * Right-shift: X >>= count
791 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100792int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000793{
Gilles Peskine449bd832023-01-11 14:50:10 +0100794 MPI_VALIDATE_RET(X != NULL);
795 if (X->n != 0) {
796 mbedtls_mpi_core_shift_r(X->p, X->n, count);
797 }
798 return 0;
Gilles Peskine66414202022-09-21 15:36:16 +0200799}
800
Paul Bakker5121ce52009-01-03 21:22:43 +0000801/*
802 * Compare unsigned values
803 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100804int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000805{
Paul Bakker23986e52011-04-24 08:57:21 +0000806 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100807 MPI_VALIDATE_RET(X != NULL);
808 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000809
Gilles Peskine449bd832023-01-11 14:50:10 +0100810 for (i = X->n; i > 0; i--) {
811 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000812 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100813 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000814 }
815
Gilles Peskine449bd832023-01-11 14:50:10 +0100816 for (j = Y->n; j > 0; j--) {
817 if (Y->p[j - 1] != 0) {
818 break;
819 }
820 }
821
Dave Rodgmanebcd7852023-08-09 18:56:42 +0100822 /* If i == j == 0, i.e. abs(X) == abs(Y),
823 * we end up returning 0 at the end of the function. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100824
825 if (i > j) {
826 return 1;
827 }
828 if (j > i) {
829 return -1;
830 }
831
832 for (; i > 0; i--) {
833 if (X->p[i - 1] > Y->p[i - 1]) {
834 return 1;
835 }
836 if (X->p[i - 1] < Y->p[i - 1]) {
837 return -1;
838 }
839 }
840
841 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000842}
843
844/*
845 * Compare signed values
846 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100847int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000848{
Paul Bakker23986e52011-04-24 08:57:21 +0000849 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100850 MPI_VALIDATE_RET(X != NULL);
851 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000852
Gilles Peskine449bd832023-01-11 14:50:10 +0100853 for (i = X->n; i > 0; i--) {
854 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100856 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000857 }
858
Gilles Peskine449bd832023-01-11 14:50:10 +0100859 for (j = Y->n; j > 0; j--) {
860 if (Y->p[j - 1] != 0) {
861 break;
862 }
863 }
864
865 if (i == 0 && j == 0) {
866 return 0;
867 }
868
869 if (i > j) {
870 return X->s;
871 }
872 if (j > i) {
873 return -Y->s;
874 }
875
876 if (X->s > 0 && Y->s < 0) {
877 return 1;
878 }
879 if (Y->s > 0 && X->s < 0) {
880 return -1;
881 }
882
883 for (; i > 0; i--) {
884 if (X->p[i - 1] > Y->p[i - 1]) {
885 return X->s;
886 }
887 if (X->p[i - 1] < Y->p[i - 1]) {
888 return -X->s;
889 }
890 }
891
892 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000893}
894
Janos Follathee6abce2019-09-05 14:47:19 +0100895/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 * Compare signed values
897 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100898int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000899{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200900 mbedtls_mpi Y;
901 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +0100902 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000903
Gilles Peskine449bd832023-01-11 14:50:10 +0100904 *p = mpi_sint_abs(z);
Dave Rodgmanf3df1052023-08-09 18:55:41 +0100905 Y.s = TO_SIGN(z);
Paul Bakker5121ce52009-01-03 21:22:43 +0000906 Y.n = 1;
907 Y.p = p;
908
Gilles Peskine449bd832023-01-11 14:50:10 +0100909 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +0000910}
911
912/*
913 * Unsigned addition: X = |A| + |B| (HAC 14.7)
914 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100915int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +0000916{
Janos Follath24eed8d2019-11-22 13:21:35 +0000917 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100918 size_t j;
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +0100919 mbedtls_mpi_uint *p;
920 mbedtls_mpi_uint c;
Gilles Peskine449bd832023-01-11 14:50:10 +0100921 MPI_VALIDATE_RET(X != NULL);
922 MPI_VALIDATE_RET(A != NULL);
923 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000924
Gilles Peskine449bd832023-01-11 14:50:10 +0100925 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200926 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000927 }
928
Gilles Peskine449bd832023-01-11 14:50:10 +0100929 if (X != A) {
930 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
931 }
Paul Bakker9af723c2014-05-01 13:03:14 +0200932
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000933 /*
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100934 * X must always be positive as a result of unsigned additions.
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000935 */
936 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000937
Gilles Peskine449bd832023-01-11 14:50:10 +0100938 for (j = B->n; j > 0; j--) {
939 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000940 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100941 }
942 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000943
Gilles Peskinedb14a9d2022-11-15 22:59:00 +0100944 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
945 * and B is 0 (of any size). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100946 if (j == 0) {
947 return 0;
948 }
Gilles Peskinedb14a9d2022-11-15 22:59:00 +0100949
Gilles Peskine449bd832023-01-11 14:50:10 +0100950 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100952 /* j is the number of non-zero limbs of B. Add those to X. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000953
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +0100954 p = X->p;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100955
Agathiyan Bragadeeshc99840a2023-07-12 11:15:46 +0100956 c = mbedtls_mpi_core_add(p, p, B->p, j);
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100957
958 p += j;
959
960 /* Now propagate any carry */
Paul Bakker5121ce52009-01-03 21:22:43 +0000961
Gilles Peskine449bd832023-01-11 14:50:10 +0100962 while (c != 0) {
963 if (j >= X->n) {
964 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100965 p = X->p + j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000966 }
967
Gilles Peskine449bd832023-01-11 14:50:10 +0100968 *p += c; c = (*p < c); j++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000969 }
970
971cleanup:
972
Gilles Peskine449bd832023-01-11 14:50:10 +0100973 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000974}
975
Paul Bakker5121ce52009-01-03 21:22:43 +0000976/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +0200977 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100979int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +0000980{
Janos Follath24eed8d2019-11-22 13:21:35 +0000981 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000982 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +0200983 mbedtls_mpi_uint carry;
Gilles Peskine449bd832023-01-11 14:50:10 +0100984 MPI_VALIDATE_RET(X != NULL);
985 MPI_VALIDATE_RET(A != NULL);
986 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000987
Gilles Peskine449bd832023-01-11 14:50:10 +0100988 for (n = B->n; n > 0; n--) {
989 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100991 }
992 }
993 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +0100994 /* B >= (2^ciL)^n > A */
995 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
996 goto cleanup;
997 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000998
Gilles Peskine449bd832023-01-11 14:50:10 +0100999 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001000
1001 /* Set the high limbs of X to match A. Don't touch the lower limbs
1002 * because X might be aliased to B, and we must not overwrite the
1003 * significant digits of B. */
Aaron M. Uckoaf67d2c2023-01-17 11:52:22 -05001004 if (A->n > n && A != X) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001005 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1006 }
1007 if (X->n > A->n) {
1008 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1009 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001010
Gilles Peskine449bd832023-01-11 14:50:10 +01001011 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
1012 if (carry != 0) {
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001013 /* Propagate the carry through the rest of X. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001014 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
Tom Cosgrove452c99c2022-08-25 10:07:07 +01001015
1016 /* If we have further carry/borrow, the result is negative. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001017 if (carry != 0) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001018 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1019 goto cleanup;
1020 }
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001021 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001022
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001023 /* X should always be positive as a result of unsigned subtractions. */
1024 X->s = 1;
1025
Paul Bakker5121ce52009-01-03 21:22:43 +00001026cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001027 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001028}
1029
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001030/* Common function for signed addition and subtraction.
1031 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001032 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001033static int add_sub_mpi(mbedtls_mpi *X,
1034 const mbedtls_mpi *A, const mbedtls_mpi *B,
1035 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001036{
Hanno Becker73d7d792018-12-11 10:35:51 +00001037 int ret, s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001038 MPI_VALIDATE_RET(X != NULL);
1039 MPI_VALIDATE_RET(A != NULL);
1040 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001041
Hanno Becker73d7d792018-12-11 10:35:51 +00001042 s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 if (A->s * B->s * flip_B < 0) {
1044 int cmp = mbedtls_mpi_cmp_abs(A, B);
1045 if (cmp >= 0) {
1046 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001047 /* If |A| = |B|, the result is 0 and we must set the sign bit
1048 * to +1 regardless of which of A or B was negative. Otherwise,
1049 * since |A| > |B|, the sign is the sign of A. */
1050 X->s = cmp == 0 ? 1 : s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001051 } else {
1052 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001053 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001054 X->s = -s;
1055 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001056 } else {
1057 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 X->s = s;
1059 }
1060
1061cleanup:
1062
Gilles Peskine449bd832023-01-11 14:50:10 +01001063 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001064}
1065
1066/*
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001067 * Signed addition: X = A + B
1068 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001069int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001070{
Gilles Peskine449bd832023-01-11 14:50:10 +01001071 return add_sub_mpi(X, A, B, 1);
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001072}
1073
1074/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001075 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001076 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001077int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001078{
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001080}
1081
1082/*
1083 * Signed addition: X = A + b
1084 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001085int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001086{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001087 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001089 MPI_VALIDATE_RET(X != NULL);
1090 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001091
Gilles Peskine449bd832023-01-11 14:50:10 +01001092 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001093 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001094 B.n = 1;
1095 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001096
Gilles Peskine449bd832023-01-11 14:50:10 +01001097 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001098}
1099
1100/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001101 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001102 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001103int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001104{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001105 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001107 MPI_VALIDATE_RET(X != NULL);
1108 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001109
Gilles Peskine449bd832023-01-11 14:50:10 +01001110 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001111 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001112 B.n = 1;
1113 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001114
Gilles Peskine449bd832023-01-11 14:50:10 +01001115 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001116}
1117
Paul Bakker5121ce52009-01-03 21:22:43 +00001118/*
1119 * Baseline multiplication: X = A * B (HAC 14.12)
1120 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001121int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001122{
Janos Follath24eed8d2019-11-22 13:21:35 +00001123 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001124 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001126 int result_is_zero = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001127 MPI_VALIDATE_RET(X != NULL);
1128 MPI_VALIDATE_RET(A != NULL);
1129 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001130
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001131 mbedtls_mpi_init(&TA);
1132 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 if (X == A) {
1135 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1136 }
1137 if (X == B) {
1138 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1139 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001140
Gilles Peskine449bd832023-01-11 14:50:10 +01001141 for (i = A->n; i > 0; i--) {
1142 if (A->p[i - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001143 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001144 }
1145 }
1146 if (i == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001147 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001148 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001149
Gilles Peskine449bd832023-01-11 14:50:10 +01001150 for (j = B->n; j > 0; j--) {
1151 if (B->p[j - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001152 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001153 }
1154 }
1155 if (j == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001156 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001157 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001158
Gilles Peskine449bd832023-01-11 14:50:10 +01001159 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1160 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001162 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Paul Bakker5121ce52009-01-03 21:22:43 +00001163
Hanno Beckerda763de2022-04-13 06:50:02 +01001164 /* If the result is 0, we don't shortcut the operation, which reduces
1165 * but does not eliminate side channels leaking the zero-ness. We do
1166 * need to take care to set the sign bit properly since the library does
1167 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001168 if (result_is_zero) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001169 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001170 } else {
Hanno Beckerda763de2022-04-13 06:50:02 +01001171 X->s = A->s * B->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001172 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001173
1174cleanup:
1175
Gilles Peskine449bd832023-01-11 14:50:10 +01001176 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001177
Gilles Peskine449bd832023-01-11 14:50:10 +01001178 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001179}
1180
1181/*
1182 * Baseline multiplication: X = A * b
1183 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001184int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001185{
Gilles Peskine449bd832023-01-11 14:50:10 +01001186 MPI_VALIDATE_RET(X != NULL);
1187 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001188
Hanno Becker35771312022-04-14 11:52:11 +01001189 size_t n = A->n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001190 while (n > 0 && A->p[n - 1] == 0) {
Hanno Becker35771312022-04-14 11:52:11 +01001191 --n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001192 }
Hanno Becker35771312022-04-14 11:52:11 +01001193
Hanno Becker74a11a32022-04-06 06:27:00 +01001194 /* The general method below doesn't work if b==0. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001195 if (b == 0 || n == 0) {
1196 return mbedtls_mpi_lset(X, 0);
1197 }
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001198
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001199 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001200 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001201 /* In general, A * b requires 1 limb more than b. If
1202 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1203 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001204 * copy() will take care of the growth if needed. However, experimentally,
1205 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001206 * calls to calloc() in ECP code, presumably because it reuses the
1207 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001208 * grow to its final size.
1209 *
1210 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1211 * A,X can be the same. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001212 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1213 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1214 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001215
1216cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001217 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001218}
1219
1220/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001221 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1222 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001223 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001224static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1225 mbedtls_mpi_uint u0,
1226 mbedtls_mpi_uint d,
1227 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001228{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001229#if defined(MBEDTLS_HAVE_UDBL)
1230 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001231#else
Simon Butcher9803d072016-01-03 00:24:34 +00001232 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001233 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001234 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1235 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001236 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001237#endif
1238
Simon Butcher15b15d12015-11-26 19:35:03 +00001239 /*
1240 * Check for overflow
1241 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001242 if (0 == d || u1 >= d) {
1243 if (r != NULL) {
1244 *r = ~(mbedtls_mpi_uint) 0u;
1245 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001246
Gilles Peskine449bd832023-01-11 14:50:10 +01001247 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001248 }
1249
1250#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001251 dividend = (mbedtls_t_udbl) u1 << biL;
1252 dividend |= (mbedtls_t_udbl) u0;
1253 quotient = dividend / d;
Gilles Peskine449bd832023-01-11 14:50:10 +01001254 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1255 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1256 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001257
Gilles Peskine449bd832023-01-11 14:50:10 +01001258 if (r != NULL) {
1259 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1260 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001261
1262 return (mbedtls_mpi_uint) quotient;
1263#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001264
1265 /*
1266 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1267 * Vol. 2 - Seminumerical Algorithms, Knuth
1268 */
1269
1270 /*
1271 * Normalize the divisor, d, and dividend, u0, u1
1272 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001273 s = mbedtls_mpi_core_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001274 d = d << s;
1275
1276 u1 = u1 << s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001277 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001278 u0 = u0 << s;
1279
1280 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001281 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001282
1283 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001284 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001285
1286 /*
1287 * Find the first quotient and remainder
1288 */
1289 q1 = u1 / d1;
1290 r0 = u1 - d1 * q1;
1291
Gilles Peskine449bd832023-01-11 14:50:10 +01001292 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001293 q1 -= 1;
1294 r0 += d1;
1295
Gilles Peskine449bd832023-01-11 14:50:10 +01001296 if (r0 >= radix) {
1297 break;
1298 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001299 }
1300
Gilles Peskine449bd832023-01-11 14:50:10 +01001301 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001302 q0 = rAX / d1;
1303 r0 = rAX - q0 * d1;
1304
Gilles Peskine449bd832023-01-11 14:50:10 +01001305 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001306 q0 -= 1;
1307 r0 += d1;
1308
Gilles Peskine449bd832023-01-11 14:50:10 +01001309 if (r0 >= radix) {
1310 break;
1311 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001312 }
1313
Gilles Peskine449bd832023-01-11 14:50:10 +01001314 if (r != NULL) {
1315 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1316 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001317
1318 quotient = q1 * radix + q0;
1319
1320 return quotient;
1321#endif
1322}
1323
1324/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001326 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001327int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1328 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001329{
Janos Follath24eed8d2019-11-22 13:21:35 +00001330 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001331 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001333 mbedtls_mpi_uint TP2[3];
Gilles Peskine449bd832023-01-11 14:50:10 +01001334 MPI_VALIDATE_RET(A != NULL);
1335 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001336
Gilles Peskine449bd832023-01-11 14:50:10 +01001337 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1338 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1339 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001340
Gilles Peskine449bd832023-01-11 14:50:10 +01001341 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1342 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001343 /*
1344 * Avoid dynamic memory allocations for constant-size T2.
1345 *
1346 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1347 * so nobody increase the size of the MPI and we're safe to use an on-stack
1348 * buffer.
1349 */
Alexander K35d6d462019-10-31 14:46:45 +03001350 T2.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001351 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001352 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
Gilles Peskine449bd832023-01-11 14:50:10 +01001354 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1355 if (Q != NULL) {
1356 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1357 }
1358 if (R != NULL) {
1359 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1360 }
1361 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 }
1363
Gilles Peskine449bd832023-01-11 14:50:10 +01001364 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1365 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001366 X.s = Y.s = 1;
1367
Gilles Peskine449bd832023-01-11 14:50:10 +01001368 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1369 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1370 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001371
Gilles Peskine449bd832023-01-11 14:50:10 +01001372 k = mbedtls_mpi_bitlen(&Y) % biL;
1373 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001374 k = biL - 1 - k;
Gilles Peskine449bd832023-01-11 14:50:10 +01001375 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1376 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1377 } else {
1378 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
1381 n = X.n - 1;
1382 t = Y.n - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001383 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
Gilles Peskine449bd832023-01-11 14:50:10 +01001385 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001386 Z.p[n - t]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001387 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001389 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001390
Gilles Peskine449bd832023-01-11 14:50:10 +01001391 for (i = n; i > t; i--) {
1392 if (X.p[i] >= Y.p[t]) {
1393 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1394 } else {
1395 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1396 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 }
1398
Gilles Peskine449bd832023-01-11 14:50:10 +01001399 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1400 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001401 T2.p[2] = X.p[i];
1402
Paul Bakker5121ce52009-01-03 21:22:43 +00001403 Z.p[i - t - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001404 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 Z.p[i - t - 1]--;
1406
Gilles Peskine449bd832023-01-11 14:50:10 +01001407 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1408 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001409 T1.p[1] = Y.p[t];
Gilles Peskine449bd832023-01-11 14:50:10 +01001410 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1411 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001412
Gilles Peskine449bd832023-01-11 14:50:10 +01001413 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1414 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1415 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001416
Gilles Peskine449bd832023-01-11 14:50:10 +01001417 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1418 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1419 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1420 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001421 Z.p[i - t - 1]--;
1422 }
1423 }
1424
Gilles Peskine449bd832023-01-11 14:50:10 +01001425 if (Q != NULL) {
1426 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 Q->s = A->s * B->s;
1428 }
1429
Gilles Peskine449bd832023-01-11 14:50:10 +01001430 if (R != NULL) {
1431 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001432 X.s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001433 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
Gilles Peskine449bd832023-01-11 14:50:10 +01001435 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 R->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001437 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001438 }
1439
1440cleanup:
1441
Gilles Peskine449bd832023-01-11 14:50:10 +01001442 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1443 mbedtls_mpi_free(&T1);
1444 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001445
Gilles Peskine449bd832023-01-11 14:50:10 +01001446 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001447}
1448
1449/*
1450 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001451 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001452int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1453 const mbedtls_mpi *A,
1454 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001455{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001456 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001458 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001459
Gilles Peskine449bd832023-01-11 14:50:10 +01001460 p[0] = mpi_sint_abs(b);
Dave Rodgmanf3df1052023-08-09 18:55:41 +01001461 B.s = TO_SIGN(b);
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001462 B.n = 1;
1463 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001464
Gilles Peskine449bd832023-01-11 14:50:10 +01001465 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001466}
1467
1468/*
1469 * Modulo: R = A mod B
1470 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001471int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001472{
Janos Follath24eed8d2019-11-22 13:21:35 +00001473 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01001474 MPI_VALIDATE_RET(R != NULL);
1475 MPI_VALIDATE_RET(A != NULL);
1476 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
Gilles Peskine449bd832023-01-11 14:50:10 +01001478 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1479 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1480 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001481
Gilles Peskine449bd832023-01-11 14:50:10 +01001482 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
Gilles Peskine449bd832023-01-11 14:50:10 +01001484 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1485 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1486 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
Gilles Peskine449bd832023-01-11 14:50:10 +01001488 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1489 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1490 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001491
1492cleanup:
1493
Gilles Peskine449bd832023-01-11 14:50:10 +01001494 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001495}
1496
1497/*
1498 * Modulo: r = A mod b
1499 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001500int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001501{
Paul Bakker23986e52011-04-24 08:57:21 +00001502 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 mbedtls_mpi_uint x, y, z;
Gilles Peskine449bd832023-01-11 14:50:10 +01001504 MPI_VALIDATE_RET(r != NULL);
1505 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001506
Gilles Peskine449bd832023-01-11 14:50:10 +01001507 if (b == 0) {
1508 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1509 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
Gilles Peskine449bd832023-01-11 14:50:10 +01001511 if (b < 0) {
1512 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1513 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001514
1515 /*
1516 * handle trivial cases
1517 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001518 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001519 *r = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001520 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 }
1522
Gilles Peskine449bd832023-01-11 14:50:10 +01001523 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001524 *r = A->p[0] & 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001525 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001526 }
1527
1528 /*
1529 * general case
1530 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001531 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001532 x = A->p[i - 1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001533 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001534 z = y / b;
1535 y -= z * b;
1536
1537 x <<= biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001538 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001539 z = y / b;
1540 y -= z * b;
1541 }
1542
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001543 /*
1544 * If A is negative, then the current y represents a negative value.
1545 * Flipping it to the positive side.
1546 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001547 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001548 y = b - y;
Gilles Peskine449bd832023-01-11 14:50:10 +01001549 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001550
Paul Bakker5121ce52009-01-03 21:22:43 +00001551 *r = y;
1552
Gilles Peskine449bd832023-01-11 14:50:10 +01001553 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001554}
1555
Gilles Peskine449bd832023-01-11 14:50:10 +01001556static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001557{
Gilles Peskine449bd832023-01-11 14:50:10 +01001558 *mm = mbedtls_mpi_core_montmul_init(N->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001559}
1560
Tom Cosgrove93842842022-08-05 16:59:43 +01001561/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1562 *
1563 * \param[in,out] A One of the numbers to multiply.
1564 * It must have at least as many limbs as N
1565 * (A->n >= N->n), and any limbs beyond n are ignored.
1566 * On successful completion, A contains the result of
1567 * the multiplication A * B * R^-1 mod N where
1568 * R = (2^ciL)^n.
1569 * \param[in] B One of the numbers to multiply.
1570 * It must be nonzero and must not have more limbs than N
1571 * (B->n <= N->n).
Tom Cosgrove40d22942022-08-17 06:42:44 +01001572 * \param[in] N The modulus. \p N must be odd.
Tom Cosgrove93842842022-08-05 16:59:43 +01001573 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1574 * This is -N^-1 mod 2^ciL.
1575 * \param[in,out] T A bignum for temporary storage.
1576 * It must be at least twice the limb size of N plus 1
1577 * (T->n >= 2 * N->n + 1).
1578 * Its initial content is unused and
1579 * its final content is indeterminate.
Tom Cosgrove5dd97e62022-08-30 14:31:49 +01001580 * It does not get reallocated.
Tom Cosgrove93842842022-08-05 16:59:43 +01001581 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001582static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1583 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1584 mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001585{
Gilles Peskine449bd832023-01-11 14:50:10 +01001586 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 +00001587}
1588
1589/*
1590 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001591 *
Tom Cosgrove93842842022-08-05 16:59:43 +01001592 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001593 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001594static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1595 mbedtls_mpi_uint mm, mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001596{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597 mbedtls_mpi_uint z = 1;
1598 mbedtls_mpi U;
Gilles Peskine053022f2023-06-29 19:26:48 +02001599 U.n = 1;
1600 U.s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001601 U.p = &z;
1602
Gilles Peskine449bd832023-01-11 14:50:10 +01001603 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001604}
1605
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001606/**
1607 * Select an MPI from a table without leaking the index.
1608 *
1609 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1610 * reads the entire table in order to avoid leaking the value of idx to an
1611 * attacker able to observe memory access patterns.
1612 *
1613 * \param[out] R Where to write the selected MPI.
1614 * \param[in] T The table to read from.
1615 * \param[in] T_size The number of elements in the table.
1616 * \param[in] idx The index of the element to select;
1617 * this must satisfy 0 <= idx < T_size.
1618 *
1619 * \return \c 0 on success, or a negative error code.
1620 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001621static 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 +01001622{
1623 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1624
Gilles Peskine449bd832023-01-11 14:50:10 +01001625 for (size_t i = 0; i < T_size; i++) {
1626 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
1627 (unsigned char) mbedtls_ct_size_bool_eq(i,
1628 idx)));
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001629 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001630
1631cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001632 return ret;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001633}
1634
Paul Bakker5121ce52009-01-03 21:22:43 +00001635/*
1636 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1637 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001638int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1639 const mbedtls_mpi *E, const mbedtls_mpi *N,
1640 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00001641{
Janos Follath24eed8d2019-11-22 13:21:35 +00001642 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath74601202022-11-21 15:54:20 +00001643 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00001644 size_t i, j, nblimbs;
1645 size_t bufsize, nbits;
Paul Elliott1748de12023-02-13 15:35:35 +00001646 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001647 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine449bd832023-01-11 14:50:10 +01001648 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001649 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
Gilles Peskine449bd832023-01-11 14:50:10 +01001651 MPI_VALIDATE_RET(X != NULL);
1652 MPI_VALIDATE_RET(A != NULL);
1653 MPI_VALIDATE_RET(E != NULL);
1654 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001655
Gilles Peskine449bd832023-01-11 14:50:10 +01001656 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1657 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1658 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
Gilles Peskine449bd832023-01-11 14:50:10 +01001660 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1661 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1662 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00001663
Gilles Peskine449bd832023-01-11 14:50:10 +01001664 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1665 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1666 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1667 }
Chris Jones9246d042020-11-25 15:12:39 +00001668
Paul Bakkerf6198c12012-05-16 08:02:29 +00001669 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 * Init temps and window size
1671 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001672 mpi_montg_init(&mm, N);
1673 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
1674 mbedtls_mpi_init(&Apos);
1675 mbedtls_mpi_init(&WW);
1676 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00001677
Gilles Peskine449bd832023-01-11 14:50:10 +01001678 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00001679
Gilles Peskine449bd832023-01-11 14:50:10 +01001680 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1681 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001682
Gilles Peskine449bd832023-01-11 14:50:10 +01001683#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
1684 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath7fa11b82022-11-21 14:48:02 +00001685 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +01001686 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001687#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001688
Janos Follathc8d66d52022-11-22 10:47:10 +00001689 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath06000952022-11-22 10:18:06 +00001690
Paul Bakker5121ce52009-01-03 21:22:43 +00001691 /*
Janos Follathbe54ca72022-11-21 16:14:54 +00001692 * This function is not constant-trace: its memory accesses depend on the
1693 * exponent value. To defend against timing attacks, callers (such as RSA
1694 * and DHM) should use exponent blinding. However this is not enough if the
1695 * adversary can find the exponent in a single trace, so this function
1696 * takes extra precautions against adversaries who can observe memory
1697 * access patterns.
Janos Follathf08b40e2022-11-11 15:56:38 +00001698 *
Janos Follathbe54ca72022-11-21 16:14:54 +00001699 * This function performs a series of multiplications by table elements and
1700 * squarings, and we want the prevent the adversary from finding out which
1701 * table element was used, and from distinguishing between multiplications
1702 * and squarings. Firstly, when multiplying by an element of the window
1703 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
1704 * squarings as having a different memory access patterns from other
1705 * multiplications. So secondly, we put the accumulator X in the table as
1706 * well, and also do a constant-trace table lookup to multiply by X.
1707 *
1708 * This way, all multiplications take the form of a lookup-and-multiply.
1709 * The number of lookup-and-multiply operations inside each iteration of
1710 * the main loop still depends on the bits of the exponent, but since the
1711 * other operations in the loop don't have an easily recognizable memory
1712 * trace, an adversary is unlikely to be able to observe the exact
1713 * patterns.
1714 *
1715 * An adversary may still be able to recover the exponent if they can
1716 * observe both memory accesses and branches. However, branch prediction
1717 * exploitation typically requires many traces of execution over the same
1718 * data, which is defeated by randomized blinding.
Janos Follath84461482022-11-21 14:31:22 +00001719 *
1720 * To achieve this, we make a copy of X and we use the table entry in each
1721 * calculation from this point on.
Janos Follath8e7d6a02022-10-04 13:27:40 +01001722 */
Janos Follathc8d66d52022-11-22 10:47:10 +00001723 const size_t x_index = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001724 mbedtls_mpi_init(&W[x_index]);
1725 mbedtls_mpi_copy(&W[x_index], X);
Janos Follath84461482022-11-21 14:31:22 +00001726
Paul Bakker5121ce52009-01-03 21:22:43 +00001727 j = N->n + 1;
Tom Cosgrove93842842022-08-05 16:59:43 +01001728 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
Paul Bakker5121ce52009-01-03 21:22:43 +00001729 * and mpi_montred() calls later. Here we ensure that W[1] and X are
1730 * large enough, and later we'll grow other W[i] to the same length.
1731 * They must not be shrunk midway through this function!
1732 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001733 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1734 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
1735 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001736
1737 /*
Paul Bakker50546922012-05-19 08:40:49 +00001738 * Compensate for negative A (and correct at the end)
1739 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001740 neg = (A->s == -1);
1741 if (neg) {
1742 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00001743 Apos.s = 1;
1744 A = &Apos;
1745 }
1746
1747 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001748 * If 1st call, pre-compute R^2 mod N
1749 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001750 if (prec_RR == NULL || prec_RR->p == NULL) {
1751 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
1752 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
1753 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
Gilles Peskine449bd832023-01-11 14:50:10 +01001755 if (prec_RR != NULL) {
1756 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
1757 }
1758 } else {
1759 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001761
1762 /*
1763 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1764 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001765 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1766 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001767 /* This should be a no-op because W[1] is already that large before
1768 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Tom Cosgrove93842842022-08-05 16:59:43 +01001769 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001770 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
1771 } else {
1772 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001773 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001774
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001775 /* Note that this is safe because W[1] always has at least N->n limbs
1776 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001777 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
1779 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001780 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001781 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001782 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1783 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001784
Janos Follathc8d66d52022-11-22 10:47:10 +00001785
Gilles Peskine449bd832023-01-11 14:50:10 +01001786 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001787 /*
Janos Follath74601202022-11-21 15:54:20 +00001788 * W[i] = W[1] ^ i
1789 *
1790 * The first bit of the sliding window is always 1 and therefore we
1791 * only need to store the second half of the table.
Janos Follathc8d66d52022-11-22 10:47:10 +00001792 *
1793 * (There are two special elements in the table: W[0] for the
1794 * accumulator/result and W[1] for A in Montgomery form. Both of these
1795 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00001796 */
Janos Follath74601202022-11-21 15:54:20 +00001797 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001798
Gilles Peskine449bd832023-01-11 14:50:10 +01001799 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1800 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
Gilles Peskine449bd832023-01-11 14:50:10 +01001802 for (i = 0; i < window_bitsize - 1; i++) {
1803 mpi_montmul(&W[j], &W[j], N, mm, &T);
1804 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01001805
Paul Bakker5121ce52009-01-03 21:22:43 +00001806 /*
1807 * W[i] = W[i - 1] * W[1]
1808 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001809 for (i = j + 1; i < w_table_used_size; i++) {
1810 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1811 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Gilles Peskine449bd832023-01-11 14:50:10 +01001813 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001814 }
1815 }
1816
1817 nblimbs = E->n;
1818 bufsize = 0;
1819 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001820 state = 0;
1821
Gilles Peskine449bd832023-01-11 14:50:10 +01001822 while (1) {
1823 if (bufsize == 0) {
1824 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001826 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
Paul Bakker0d7702c2013-10-29 16:18:35 +01001828 nblimbs--;
1829
Gilles Peskine449bd832023-01-11 14:50:10 +01001830 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001831 }
1832
1833 bufsize--;
1834
1835 ei = (E->p[nblimbs] >> bufsize) & 1;
1836
1837 /*
1838 * skip leading 0s
1839 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001840 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01001842 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
Gilles Peskine449bd832023-01-11 14:50:10 +01001844 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001845 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001846 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001848 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1849 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 continue;
1851 }
1852
1853 /*
1854 * add ei to current window
1855 */
1856 state = 2;
1857
1858 nbits++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001859 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
Gilles Peskine449bd832023-01-11 14:50:10 +01001861 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001863 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001865 for (i = 0; i < window_bitsize; i++) {
1866 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1867 x_index));
1868 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001869 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001870
1871 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001872 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001874 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1875 exponent_bits_in_window));
1876 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001877
1878 state--;
1879 nbits = 0;
Janos Follath7fa11b82022-11-21 14:48:02 +00001880 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 }
1882 }
1883
1884 /*
1885 * process the remaining bits
1886 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001887 for (i = 0; i < nbits; i++) {
1888 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1889 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
Janos Follath7fa11b82022-11-21 14:48:02 +00001891 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
Gilles Peskine449bd832023-01-11 14:50:10 +01001893 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
1894 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
1895 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001896 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 }
1898
1899 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001900 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001901 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001902 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
Gilles Peskine449bd832023-01-11 14:50:10 +01001904 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath8e7d6a02022-10-04 13:27:40 +01001905 W[x_index].s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001906 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00001907 }
1908
Janos Follath8e7d6a02022-10-04 13:27:40 +01001909 /*
1910 * Load the result in the output variable.
1911 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001912 mbedtls_mpi_copy(X, &W[x_index]);
Janos Follath8e7d6a02022-10-04 13:27:40 +01001913
Paul Bakker5121ce52009-01-03 21:22:43 +00001914cleanup:
1915
Janos Follathb2c2fca2022-11-21 15:05:31 +00001916 /* The first bit of the sliding window is always 1 and therefore the first
1917 * half of the table was unused. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001918 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
1919 mbedtls_mpi_free(&W[i]);
1920 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
Gilles Peskine449bd832023-01-11 14:50:10 +01001922 mbedtls_mpi_free(&W[x_index]);
1923 mbedtls_mpi_free(&W[1]);
1924 mbedtls_mpi_free(&T);
1925 mbedtls_mpi_free(&Apos);
1926 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00001927
Gilles Peskine449bd832023-01-11 14:50:10 +01001928 if (prec_RR == NULL || prec_RR->p == NULL) {
1929 mbedtls_mpi_free(&RR);
1930 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001931
Gilles Peskine449bd832023-01-11 14:50:10 +01001932 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001933}
1934
Paul Bakker5121ce52009-01-03 21:22:43 +00001935/*
1936 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1937 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001938int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001939{
Janos Follath24eed8d2019-11-22 13:21:35 +00001940 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001941 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03001942 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
Gilles Peskine449bd832023-01-11 14:50:10 +01001944 MPI_VALIDATE_RET(G != NULL);
1945 MPI_VALIDATE_RET(A != NULL);
1946 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001947
Gilles Peskine449bd832023-01-11 14:50:10 +01001948 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
Gilles Peskine449bd832023-01-11 14:50:10 +01001950 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1951 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001952
Gilles Peskine449bd832023-01-11 14:50:10 +01001953 lz = mbedtls_mpi_lsb(&TA);
1954 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001955
Gilles Peskine27253bc2021-06-09 13:26:43 +02001956 /* The loop below gives the correct result when A==0 but not when B==0.
1957 * So have a special case for B==0. Leverage the fact that we just
1958 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1959 * slightly more efficient than cmp_int(). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001960 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1961 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02001962 goto cleanup;
1963 }
1964
Gilles Peskine449bd832023-01-11 14:50:10 +01001965 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001966 lz = lzt;
Gilles Peskine449bd832023-01-11 14:50:10 +01001967 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001968
Paul Bakker5121ce52009-01-03 21:22:43 +00001969 TA.s = TB.s = 1;
1970
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001971 /* We mostly follow the procedure described in HAC 14.54, but with some
1972 * minor differences:
1973 * - Sequences of multiplications or divisions by 2 are grouped into a
1974 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02001975 * - The procedure in HAC assumes that 0 < TB <= TA.
1976 * - The condition TB <= TA is not actually necessary for correctness.
1977 * TA and TB have symmetric roles except for the loop termination
1978 * condition, and the shifts at the beginning of the loop body
1979 * remove any significance from the ordering of TA vs TB before
1980 * the shifts.
1981 * - If TA = 0, the loop goes through 0 iterations and the result is
1982 * correctly TB.
1983 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001984 *
1985 * For the correctness proof below, decompose the original values of
1986 * A and B as
1987 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1988 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1989 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1990 * and gcd(A',B') is odd or 0.
1991 *
1992 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1993 * The code maintains the following invariant:
1994 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02001995 */
1996
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001997 /* Proof that the loop terminates:
1998 * At each iteration, either the right-shift by 1 is made on a nonzero
1999 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2000 * by at least 1, or the right-shift by 1 is made on zero and then
2001 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2002 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2003 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002004 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002005 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine449bd832023-01-11 14:50:10 +01002006 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2007 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002009 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2010 * TA-TB is even so the division by 2 has an integer result.
2011 * Invariant (I) is preserved since any odd divisor of both TA and TB
2012 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08002013 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002014 * divides TA.
2015 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002016 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2017 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2018 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2019 } else {
2020 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2021 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002022 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002023 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 }
2025
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002026 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2027 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2028 * - If there was at least one loop iteration, then one of TA or TB is odd,
2029 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2030 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2031 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002032 * 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 +02002033 */
2034
Gilles Peskine449bd832023-01-11 14:50:10 +01002035 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2036 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002037
2038cleanup:
2039
Gilles Peskine449bd832023-01-11 14:50:10 +01002040 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002041
Gilles Peskine449bd832023-01-11 14:50:10 +01002042 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002043}
2044
Paul Bakker33dc46b2014-04-30 16:11:39 +02002045/*
2046 * Fill X with size bytes of random.
Gilles Peskine22cdd0c2022-10-27 20:15:13 +02002047 * The bytes returned from the RNG are used in a specific order which
2048 * is suitable for deterministic ECDSA (see the specification of
2049 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Paul Bakker33dc46b2014-04-30 16:11:39 +02002050 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002051int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2052 int (*f_rng)(void *, unsigned char *, size_t),
2053 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002054{
Janos Follath24eed8d2019-11-22 13:21:35 +00002055 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01002056 const size_t limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002057
Gilles Peskine449bd832023-01-11 14:50:10 +01002058 MPI_VALIDATE_RET(X != NULL);
2059 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002060
Hanno Beckerda1655a2017-10-18 14:21:44 +01002061 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +01002062 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2063 if (size == 0) {
2064 return 0;
2065 }
Paul Bakker287781a2011-03-26 13:18:49 +00002066
Gilles Peskine449bd832023-01-11 14:50:10 +01002067 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002068
2069cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002070 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002071}
2072
Gilles Peskine449bd832023-01-11 14:50:10 +01002073int mbedtls_mpi_random(mbedtls_mpi *X,
2074 mbedtls_mpi_sint min,
2075 const mbedtls_mpi *N,
2076 int (*f_rng)(void *, unsigned char *, size_t),
2077 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002078{
Gilles Peskine449bd832023-01-11 14:50:10 +01002079 if (min < 0) {
2080 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2081 }
2082 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2083 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2084 }
Gilles Peskine1e918f42021-03-29 22:14:51 +02002085
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002086 /* Ensure that target MPI has exactly the same number of limbs
2087 * as the upper bound, even if the upper bound has leading zeros.
Gilles Peskine6b7ce962022-12-15 15:04:33 +01002088 * This is necessary for mbedtls_mpi_core_random. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002089 int ret = mbedtls_mpi_resize_clear(X, N->n);
2090 if (ret != 0) {
2091 return ret;
2092 }
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002093
Gilles Peskine449bd832023-01-11 14:50:10 +01002094 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002095}
2096
Paul Bakker5121ce52009-01-03 21:22:43 +00002097/*
2098 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2099 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002100int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002101{
Janos Follath24eed8d2019-11-22 13:21:35 +00002102 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002103 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine449bd832023-01-11 14:50:10 +01002104 MPI_VALIDATE_RET(X != NULL);
2105 MPI_VALIDATE_RET(A != NULL);
2106 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
Gilles Peskine449bd832023-01-11 14:50:10 +01002108 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2109 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2110 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
Gilles Peskine449bd832023-01-11 14:50:10 +01002112 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2113 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2114 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002115
Gilles Peskine449bd832023-01-11 14:50:10 +01002116 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
Gilles Peskine449bd832023-01-11 14:50:10 +01002118 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002120 goto cleanup;
2121 }
2122
Gilles Peskine449bd832023-01-11 14:50:10 +01002123 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2124 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2125 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2126 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002127
Gilles Peskine449bd832023-01-11 14:50:10 +01002128 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2129 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2130 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2131 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002132
Gilles Peskine449bd832023-01-11 14:50:10 +01002133 do {
2134 while ((TU.p[0] & 1) == 0) {
2135 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002136
Gilles Peskine449bd832023-01-11 14:50:10 +01002137 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2138 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2139 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002140 }
2141
Gilles Peskine449bd832023-01-11 14:50:10 +01002142 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2143 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002144 }
2145
Gilles Peskine449bd832023-01-11 14:50:10 +01002146 while ((TV.p[0] & 1) == 0) {
2147 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002148
Gilles Peskine449bd832023-01-11 14:50:10 +01002149 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2150 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2151 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002152 }
2153
Gilles Peskine449bd832023-01-11 14:50:10 +01002154 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2155 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002156 }
2157
Gilles Peskine449bd832023-01-11 14:50:10 +01002158 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2159 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2160 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2161 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2162 } else {
2163 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2164 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2165 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002166 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002167 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2168
2169 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2170 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002171 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
Gilles Peskine449bd832023-01-11 14:50:10 +01002173 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2174 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2175 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002176
Gilles Peskine449bd832023-01-11 14:50:10 +01002177 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
2179cleanup:
2180
Gilles Peskine449bd832023-01-11 14:50:10 +01002181 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2182 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2183 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002184
Gilles Peskine449bd832023-01-11 14:50:10 +01002185 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002186}
2187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002189
Paul Bakker5121ce52009-01-03 21:22:43 +00002190static const int small_prime[] =
2191{
Gilles Peskine449bd832023-01-11 14:50:10 +01002192 3, 5, 7, 11, 13, 17, 19, 23,
2193 29, 31, 37, 41, 43, 47, 53, 59,
2194 61, 67, 71, 73, 79, 83, 89, 97,
2195 101, 103, 107, 109, 113, 127, 131, 137,
2196 139, 149, 151, 157, 163, 167, 173, 179,
2197 181, 191, 193, 197, 199, 211, 223, 227,
2198 229, 233, 239, 241, 251, 257, 263, 269,
2199 271, 277, 281, 283, 293, 307, 311, 313,
2200 317, 331, 337, 347, 349, 353, 359, 367,
2201 373, 379, 383, 389, 397, 401, 409, 419,
2202 421, 431, 433, 439, 443, 449, 457, 461,
2203 463, 467, 479, 487, 491, 499, 503, 509,
2204 521, 523, 541, 547, 557, 563, 569, 571,
2205 577, 587, 593, 599, 601, 607, 613, 617,
2206 619, 631, 641, 643, 647, 653, 659, 661,
2207 673, 677, 683, 691, 701, 709, 719, 727,
2208 733, 739, 743, 751, 757, 761, 769, 773,
2209 787, 797, 809, 811, 821, 823, 827, 829,
2210 839, 853, 857, 859, 863, 877, 881, 883,
2211 887, 907, 911, 919, 929, 937, 941, 947,
2212 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002213};
2214
2215/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002216 * Small divisors test (X must be positive)
2217 *
2218 * Return values:
2219 * 0: no small factor (possible prime, more tests needed)
2220 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002222 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002223 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002224static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002225{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002226 int ret = 0;
2227 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002229
Gilles Peskine449bd832023-01-11 14:50:10 +01002230 if ((X->p[0] & 1) == 0) {
2231 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2232 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
Gilles Peskine449bd832023-01-11 14:50:10 +01002234 for (i = 0; small_prime[i] > 0; i++) {
2235 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2236 return 1;
2237 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002238
Gilles Peskine449bd832023-01-11 14:50:10 +01002239 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002240
Gilles Peskine449bd832023-01-11 14:50:10 +01002241 if (r == 0) {
2242 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2243 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 }
2245
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002246cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002247 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002248}
2249
2250/*
2251 * Miller-Rabin pseudo-primality test (HAC 4.24)
2252 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002253static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2254 int (*f_rng)(void *, unsigned char *, size_t),
2255 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002256{
Pascal Junodb99183d2015-03-11 16:49:45 +01002257 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002258 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002260
Gilles Peskine449bd832023-01-11 14:50:10 +01002261 MPI_VALIDATE_RET(X != NULL);
2262 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002263
Gilles Peskine449bd832023-01-11 14:50:10 +01002264 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2265 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2266 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002267
Paul Bakker5121ce52009-01-03 21:22:43 +00002268 /*
2269 * W = |X| - 1
2270 * R = W >> lsb( W )
2271 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002272 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2273 s = mbedtls_mpi_lsb(&W);
2274 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2275 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
Gilles Peskine449bd832023-01-11 14:50:10 +01002277 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 /*
2279 * pick a random A, 1 < A < |X| - 1
2280 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002281 count = 0;
2282 do {
Gilles Peskine449bd832023-01-11 14:50:10 +01002283 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002284
Gilles Peskine449bd832023-01-11 14:50:10 +01002285 j = mbedtls_mpi_bitlen(&A);
2286 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002287 if (j > k) {
Gilles Peskine449bd832023-01-11 14:50:10 +01002288 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002289 }
2290
2291 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002292 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2293 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002294 }
2295
Gilles Peskine449bd832023-01-11 14:50:10 +01002296 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2297 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
2299 /*
2300 * A = A^R mod |X|
2301 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002302 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
Gilles Peskine449bd832023-01-11 14:50:10 +01002304 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2305 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01002307 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
2309 j = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002310 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002311 /*
2312 * A = A * A mod |X|
2313 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002314 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2315 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
Gilles Peskine449bd832023-01-11 14:50:10 +01002317 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01002319 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
2321 j++;
2322 }
2323
2324 /*
2325 * not prime if A != |X| - 1 or A == 1
2326 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002327 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2328 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002330 break;
2331 }
2332 }
2333
2334cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002335 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2336 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2337 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
Gilles Peskine449bd832023-01-11 14:50:10 +01002339 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002340}
2341
2342/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002343 * Pseudo-primality test: small factors, then Miller-Rabin
2344 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002345int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2346 int (*f_rng)(void *, unsigned char *, size_t),
2347 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002348{
Janos Follath24eed8d2019-11-22 13:21:35 +00002349 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 mbedtls_mpi XX;
Gilles Peskine449bd832023-01-11 14:50:10 +01002351 MPI_VALIDATE_RET(X != NULL);
2352 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002353
2354 XX.s = 1;
2355 XX.n = X->n;
2356 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002357
Gilles Peskine449bd832023-01-11 14:50:10 +01002358 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2359 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2360 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002361 }
2362
Gilles Peskine449bd832023-01-11 14:50:10 +01002363 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2364 return 0;
2365 }
2366
2367 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2368 if (ret == 1) {
2369 return 0;
2370 }
2371
2372 return ret;
2373 }
2374
2375 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002376}
2377
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002378/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002379 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002380 *
Janos Follathf301d232018-08-14 13:34:01 +01002381 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2382 * be either 1024 bits or 1536 bits long, and flags must contain
2383 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002384 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002385int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2386 int (*f_rng)(void *, unsigned char *, size_t),
2387 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002388{
Jethro Beekman66689272018-02-14 19:24:10 -08002389#ifdef MBEDTLS_HAVE_INT64
2390// ceil(2^63.5)
2391#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2392#else
2393// ceil(2^31.5)
2394#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2395#endif
2396 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002397 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002398 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 mbedtls_mpi_uint r;
2400 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002401
Gilles Peskine449bd832023-01-11 14:50:10 +01002402 MPI_VALIDATE_RET(X != NULL);
2403 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002404
Gilles Peskine449bd832023-01-11 14:50:10 +01002405 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2406 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2407 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002408
Gilles Peskine449bd832023-01-11 14:50:10 +01002409 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002410
Gilles Peskine449bd832023-01-11 14:50:10 +01002411 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
Gilles Peskine449bd832023-01-11 14:50:10 +01002413 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002414 /*
2415 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2416 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002417 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2418 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2419 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2420 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002421 /*
2422 * 2^-100 error probability, number of rounds computed based on HAC,
2423 * fact 4.48
2424 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002425 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2426 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2427 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2428 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002429 }
2430
Gilles Peskine449bd832023-01-11 14:50:10 +01002431 while (1) {
2432 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002433 /* 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 +01002434 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2435 continue;
2436 }
Jethro Beekman66689272018-02-14 19:24:10 -08002437
2438 k = n * biL;
Gilles Peskine449bd832023-01-11 14:50:10 +01002439 if (k > nbits) {
2440 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2441 }
Jethro Beekman66689272018-02-14 19:24:10 -08002442 X->p[0] |= 1;
2443
Gilles Peskine449bd832023-01-11 14:50:10 +01002444 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2445 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002446
Gilles Peskine449bd832023-01-11 14:50:10 +01002447 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002449 }
2450 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002451 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002452 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002453 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2454 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002455 */
Jethro Beekman66689272018-02-14 19:24:10 -08002456
2457 X->p[0] |= 2;
2458
Gilles Peskine449bd832023-01-11 14:50:10 +01002459 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2460 if (r == 0) {
2461 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2462 } else if (r == 1) {
2463 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2464 }
Jethro Beekman66689272018-02-14 19:24:10 -08002465
2466 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine449bd832023-01-11 14:50:10 +01002467 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2468 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002469
Gilles Peskine449bd832023-01-11 14:50:10 +01002470 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002471 /*
2472 * First, check small factors for X and Y
2473 * before doing Miller-Rabin on any of them
2474 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002475 if ((ret = mpi_check_small_factors(X)) == 0 &&
2476 (ret = mpi_check_small_factors(&Y)) == 0 &&
2477 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2478 == 0 &&
2479 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2480 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002481 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002482 }
Jethro Beekman66689272018-02-14 19:24:10 -08002483
Gilles Peskine449bd832023-01-11 14:50:10 +01002484 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002485 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002486 }
Jethro Beekman66689272018-02-14 19:24:10 -08002487
2488 /*
2489 * Next candidates. We want to preserve Y = (X-1) / 2 and
2490 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2491 * so up Y by 6 and X by 12.
2492 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002493 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2494 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002495 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002496 }
2497 }
2498
2499cleanup:
2500
Gilles Peskine449bd832023-01-11 14:50:10 +01002501 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002502
Gilles Peskine449bd832023-01-11 14:50:10 +01002503 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002504}
2505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002509
Paul Bakker23986e52011-04-24 08:57:21 +00002510#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002511
2512static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2513{
2514 { 693, 609, 21 },
2515 { 1764, 868, 28 },
2516 { 768454923, 542167814, 1 }
2517};
2518
Paul Bakker5121ce52009-01-03 21:22:43 +00002519/*
2520 * Checkup routine
2521 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002522int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00002523{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002524 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002526
Gilles Peskine449bd832023-01-11 14:50:10 +01002527 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2528 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002529
Gilles Peskine449bd832023-01-11 14:50:10 +01002530 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2531 "EFE021C2645FD1DC586E69184AF4A31E" \
2532 "D5F53E93B5F123FA41680867BA110131" \
2533 "944FE7952E2517337780CB0DB80E61AA" \
2534 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002535
Gilles Peskine449bd832023-01-11 14:50:10 +01002536 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2537 "B2E7EFD37075B9F03FF989C7C5051C20" \
2538 "34D2A323810251127E7BF8625A4F49A5" \
2539 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2540 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002541
Gilles Peskine449bd832023-01-11 14:50:10 +01002542 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2543 "0066A198186C18C10B2F5ED9B522752A" \
2544 "9830B69916E535C8F047518A889A43A5" \
2545 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002546
Gilles Peskine449bd832023-01-11 14:50:10 +01002547 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002548
Gilles Peskine449bd832023-01-11 14:50:10 +01002549 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2550 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2551 "9E857EA95A03512E2BAE7391688D264A" \
2552 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2553 "8001B72E848A38CAE1C65F78E56ABDEF" \
2554 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2555 "ECF677152EF804370C1A305CAF3B5BF1" \
2556 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002557
Gilles Peskine449bd832023-01-11 14:50:10 +01002558 if (verbose != 0) {
2559 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2560 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002561
Gilles Peskine449bd832023-01-11 14:50:10 +01002562 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2563 if (verbose != 0) {
2564 mbedtls_printf("failed\n");
2565 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002566
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002567 ret = 1;
2568 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002569 }
2570
Gilles Peskine449bd832023-01-11 14:50:10 +01002571 if (verbose != 0) {
2572 mbedtls_printf("passed\n");
2573 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002574
Gilles Peskine449bd832023-01-11 14:50:10 +01002575 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002576
Gilles Peskine449bd832023-01-11 14:50:10 +01002577 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2578 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002579
Gilles Peskine449bd832023-01-11 14:50:10 +01002580 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2581 "6613F26162223DF488E9CD48CC132C7A" \
2582 "0AC93C701B001B092E4E5B9F73BCD27B" \
2583 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002584
Gilles Peskine449bd832023-01-11 14:50:10 +01002585 if (verbose != 0) {
2586 mbedtls_printf(" MPI test #2 (div_mpi): ");
2587 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002588
Gilles Peskine449bd832023-01-11 14:50:10 +01002589 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2590 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2591 if (verbose != 0) {
2592 mbedtls_printf("failed\n");
2593 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002595 ret = 1;
2596 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 }
2598
Gilles Peskine449bd832023-01-11 14:50:10 +01002599 if (verbose != 0) {
2600 mbedtls_printf("passed\n");
2601 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002602
Gilles Peskine449bd832023-01-11 14:50:10 +01002603 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00002604
Gilles Peskine449bd832023-01-11 14:50:10 +01002605 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2606 "36E139AEA55215609D2816998ED020BB" \
2607 "BD96C37890F65171D948E9BC7CBAA4D9" \
2608 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002609
Gilles Peskine449bd832023-01-11 14:50:10 +01002610 if (verbose != 0) {
2611 mbedtls_printf(" MPI test #3 (exp_mod): ");
2612 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002613
Gilles Peskine449bd832023-01-11 14:50:10 +01002614 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2615 if (verbose != 0) {
2616 mbedtls_printf("failed\n");
2617 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002618
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002619 ret = 1;
2620 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002621 }
2622
Gilles Peskine449bd832023-01-11 14:50:10 +01002623 if (verbose != 0) {
2624 mbedtls_printf("passed\n");
2625 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002626
Gilles Peskine449bd832023-01-11 14:50:10 +01002627 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002628
Gilles Peskine449bd832023-01-11 14:50:10 +01002629 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2630 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2631 "C3DBA76456363A10869622EAC2DD84EC" \
2632 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002633
Gilles Peskine449bd832023-01-11 14:50:10 +01002634 if (verbose != 0) {
2635 mbedtls_printf(" MPI test #4 (inv_mod): ");
2636 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002637
Gilles Peskine449bd832023-01-11 14:50:10 +01002638 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2639 if (verbose != 0) {
2640 mbedtls_printf("failed\n");
2641 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002642
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002643 ret = 1;
2644 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002645 }
2646
Gilles Peskine449bd832023-01-11 14:50:10 +01002647 if (verbose != 0) {
2648 mbedtls_printf("passed\n");
2649 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002650
Gilles Peskine449bd832023-01-11 14:50:10 +01002651 if (verbose != 0) {
2652 mbedtls_printf(" MPI test #5 (simple gcd): ");
2653 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002654
Gilles Peskine449bd832023-01-11 14:50:10 +01002655 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2656 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2657 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002658
Gilles Peskine449bd832023-01-11 14:50:10 +01002659 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002660
Gilles Peskine449bd832023-01-11 14:50:10 +01002661 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2662 if (verbose != 0) {
2663 mbedtls_printf("failed at %d\n", i);
2664 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002665
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002666 ret = 1;
2667 goto cleanup;
2668 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002669 }
2670
Gilles Peskine449bd832023-01-11 14:50:10 +01002671 if (verbose != 0) {
2672 mbedtls_printf("passed\n");
2673 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002674
Paul Bakker5121ce52009-01-03 21:22:43 +00002675cleanup:
2676
Gilles Peskine449bd832023-01-11 14:50:10 +01002677 if (ret != 0 && verbose != 0) {
2678 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2679 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002680
Gilles Peskine449bd832023-01-11 14:50:10 +01002681 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2682 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
Gilles Peskine449bd832023-01-11 14:50:10 +01002684 if (verbose != 0) {
2685 mbedtls_printf("\n");
2686 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002687
Gilles Peskine449bd832023-01-11 14:50:10 +01002688 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002689}
2690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002693#endif /* MBEDTLS_BIGNUM_C */