blob: 06626c69c4f3379d77c44a8cf4a35fc192582d8b [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 Cosgrove350226f2023-07-25 14:58:25 +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
112 X->n = nblimbs;
113 X->p = p;
114 }
115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000117}
118
119/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100120 * Resize down as much as possible,
121 * while keeping at least the specified number of limbs
122 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100123int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100124{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100126 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
130 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
131 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100132
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100133 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 if (X->n <= nblimbs) {
135 return mbedtls_mpi_grow(X, nblimbs);
136 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100137 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100138
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 for (i = X->n - 1; i > 0; i--) {
140 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 }
143 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100144 i++;
145
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 i = nblimbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100148 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
151 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
152 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100153
Gilles Peskine449bd832023-01-11 14:50:10 +0100154 if (X->p != NULL) {
155 memcpy(p, X->p, i * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100156 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100157 }
158
159 X->n = i;
160 X->p = p;
161
Gilles Peskine449bd832023-01-11 14:50:10 +0100162 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163}
164
Gilles Peskineed32b572021-06-02 22:17:52 +0200165/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100166static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200167{
Gilles Peskine449bd832023-01-11 14:50:10 +0100168 if (limbs == 0) {
169 mbedtls_mpi_free(X);
170 return 0;
171 } else if (X->n == limbs) {
172 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200173 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 return 0;
175 } else {
176 mbedtls_mpi_free(X);
177 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200178 }
179}
180
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100181/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200182 * Copy the contents of Y into X.
183 *
184 * This function is not constant-time. Leading zeros in Y may be removed.
185 *
186 * Ensure that X does not shrink. This is not guaranteed by the public API,
187 * but some code in the bignum module relies on this property, for example
188 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100190int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000191{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100192 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000193 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 MPI_VALIDATE_RET(X != NULL);
195 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000196
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 if (X == Y) {
198 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200199 }
200
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 if (Y->n == 0) {
202 if (X->n != 0) {
203 X->s = 1;
204 memset(X->p, 0, X->n * ciL);
205 }
206 return 0;
207 }
208
209 for (i = Y->n - 1; i > 0; i--) {
210 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000211 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 }
213 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000214 i++;
215
216 X->s = Y->s;
217
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 if (X->n < i) {
219 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
220 } else {
221 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100222 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000225
226cleanup:
227
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000229}
230
231/*
232 * Swap the contents of X and Y
233 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100234void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000235{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 MPI_VALIDATE(X != NULL);
238 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 memcpy(&T, X, sizeof(mbedtls_mpi));
241 memcpy(X, Y, sizeof(mbedtls_mpi));
242 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000243}
244
Gilles Peskine449bd832023-01-11 14:50:10 +0100245static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100246{
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 if (z >= 0) {
248 return z;
249 }
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100250 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
251 * A naive -z would have undefined behavior.
252 * Write this in a way that makes popular compilers happy (GCC, Clang,
253 * MSVC). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100255}
256
Paul Bakker5121ce52009-01-03 21:22:43 +0000257/*
258 * Set value from integer
259 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100260int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000261{
Janos Follath24eed8d2019-11-22 13:21:35 +0000262 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100263 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000264
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
266 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000267
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 X->p[0] = mpi_sint_abs(z);
269 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000270
271cleanup:
272
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000274}
275
276/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000277 * Get a specific bit
278 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100279int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000280{
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000282
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 if (X->n * biL <= pos) {
284 return 0;
285 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000286
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000288}
289
290/*
291 * Set a bit to a specific value of 0 or 1
292 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100293int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000294{
295 int ret = 0;
296 size_t off = pos / biL;
297 size_t idx = pos % biL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000299
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 if (val != 0 && val != 1) {
301 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000302 }
303
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 if (X->n * biL <= pos) {
305 if (val == 0) {
306 return 0;
307 }
308
309 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
310 }
311
312 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314
315cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200316
Gilles Peskine449bd832023-01-11 14:50:10 +0100317 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000318}
319
320/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200321 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000322 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100323size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000324{
Paul Bakker23986e52011-04-24 08:57:21 +0000325 size_t i, j, count = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000327
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 for (i = 0; i < X->n; i++) {
329 for (j = 0; j < biL; j++, count++) {
330 if (((X->p[i] >> j) & 1) != 0) {
331 return count;
332 }
333 }
334 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000335
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000337}
338
339/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200340 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000341 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100342size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000343{
Gilles Peskine449bd832023-01-11 14:50:10 +0100344 return mbedtls_mpi_core_bitlen(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000345}
346
347/*
348 * Return the total size in bytes
349 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100350size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000351{
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000353}
354
355/*
356 * Convert an ASCII character to digit value
357 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100358static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000359{
360 *d = 255;
361
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 if (c >= 0x30 && c <= 0x39) {
363 *d = c - 0x30;
364 }
365 if (c >= 0x41 && c <= 0x46) {
366 *d = c - 0x37;
367 }
368 if (c >= 0x61 && c <= 0x66) {
369 *d = c - 0x57;
370 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000371
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 if (*d >= (mbedtls_mpi_uint) radix) {
373 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
374 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000375
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000377}
378
379/*
380 * Import from an ASCII string
381 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100382int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000383{
Janos Follath24eed8d2019-11-22 13:21:35 +0000384 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000385 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200386 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387 mbedtls_mpi_uint d;
388 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 MPI_VALIDATE_RET(X != NULL);
390 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000391
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 if (radix < 2 || radix > 16) {
393 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200394 }
395
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 mbedtls_mpi_init(&T);
397
398 if (s[0] == 0) {
399 mbedtls_mpi_free(X);
400 return 0;
401 }
402
403 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200404 ++s;
405 sign = -1;
406 }
407
Gilles Peskine449bd832023-01-11 14:50:10 +0100408 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000409
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 if (radix == 16) {
Dave Rodgman68ef1d62023-05-18 20:49:03 +0100411 if (slen > SIZE_MAX >> 2) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100412 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 n = BITS_TO_LIMBS(slen << 2);
416
417 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
418 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
419
420 for (i = slen, j = 0; i > 0; i--, j++) {
421 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
422 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
423 }
424 } else {
425 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
426
427 for (i = 0; i < slen; i++) {
428 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
429 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
430 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000431 }
432 }
433
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200435 X->s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200437
Paul Bakker5121ce52009-01-03 21:22:43 +0000438cleanup:
439
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000443}
444
445/*
Ron Eldora16fa292018-11-20 14:07:01 +0200446 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000447 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100448static int mpi_write_hlp(mbedtls_mpi *X, int radix,
449 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000450{
Janos Follath24eed8d2019-11-22 13:21:35 +0000451 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200453 size_t length = 0;
454 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 do {
457 if (length >= buflen) {
458 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200459 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
462 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200463 /*
464 * Write the residue in the current position, as an ASCII character.
465 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 if (r < 0xA) {
467 *(--p_end) = (char) ('0' + r);
468 } else {
469 *(--p_end) = (char) ('A' + (r - 0xA));
470 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Ron Eldora16fa292018-11-20 14:07:01 +0200472 length++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000474
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200476 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000477
478cleanup:
479
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000481}
482
483/*
484 * Export into an ASCII string
485 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100486int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
487 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000488{
Paul Bakker23986e52011-04-24 08:57:21 +0000489 int ret = 0;
490 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000491 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 MPI_VALIDATE_RET(X != NULL);
494 MPI_VALIDATE_RET(olen != NULL);
495 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000496
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 if (radix < 2 || radix > 16) {
498 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
499 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
Gilles Peskine449bd832023-01-11 14:50:10 +0100501 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
502 if (radix >= 4) {
503 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000504 * `n`. If radix > 4, this might be a strict
505 * overapproximation of the number of
506 * radix-adic digits needed to present `n`. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 }
508 if (radix >= 16) {
509 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000510 * present `n`. */
511
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 }
Janos Follath80470622019-03-06 13:43:02 +0000513 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000514 n += 1; /* Compensate for the divisions above, which round down `n`
515 * in case it's not even. */
516 n += 1; /* Potential '-'-sign. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000518 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100521 *olen = n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000523 }
524
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100525 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100526 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000527
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000529 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000530 buflen--;
531 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
Gilles Peskine449bd832023-01-11 14:50:10 +0100533 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000534 int c;
535 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 for (i = X->n, k = 0; i > 0; i--) {
538 for (j = ciL; j > 0; j--) {
539 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000540
Gilles Peskine449bd832023-01-11 14:50:10 +0100541 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000542 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100543 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000544
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000545 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000546 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000547 k = 1;
548 }
549 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 } else {
551 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000552
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000554 T.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100555 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000556
Gilles Peskine449bd832023-01-11 14:50:10 +0100557 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000558 }
559
560 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100561 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563cleanup:
564
Gilles Peskine449bd832023-01-11 14:50:10 +0100565 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
Gilles Peskine449bd832023-01-11 14:50:10 +0100567 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000568}
569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000571/*
572 * Read X from an opened file
573 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100574int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000575{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000577 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000579 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000580 * Buffer should have space for (short) label and decimal formatted MPI,
581 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000582 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 MPI_VALIDATE_RET(X != NULL);
586 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 if (radix < 2 || radix > 16) {
589 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
590 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000591
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 memset(s, 0, sizeof(s));
593 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
594 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
595 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000596
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 slen = strlen(s);
598 if (slen == sizeof(s) - 2) {
599 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
600 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000601
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 if (slen > 0 && s[slen - 1] == '\n') {
603 slen--; s[slen] = '\0';
604 }
605 if (slen > 0 && s[slen - 1] == '\r') {
606 slen--; s[slen] = '\0';
607 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
609 p = s + slen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100610 while (p-- > s) {
611 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000612 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100613 }
614 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000615
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000617}
618
619/*
620 * Write X into an opened file (or stdout if fout == NULL)
621 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100622int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000623{
Janos Follath24eed8d2019-11-22 13:21:35 +0000624 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000625 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000626 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000627 * Buffer should have space for (short) label and decimal formatted MPI,
628 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000629 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100630 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
631 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000632
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 if (radix < 2 || radix > 16) {
634 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
635 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000636
Gilles Peskine449bd832023-01-11 14:50:10 +0100637 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000640
Gilles Peskine449bd832023-01-11 14:50:10 +0100641 if (p == NULL) {
642 p = "";
643 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
Gilles Peskine449bd832023-01-11 14:50:10 +0100645 plen = strlen(p);
646 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000647 s[slen++] = '\r';
648 s[slen++] = '\n';
649
Gilles Peskine449bd832023-01-11 14:50:10 +0100650 if (fout != NULL) {
651 if (fwrite(p, 1, plen, fout) != plen ||
652 fwrite(s, 1, slen, fout) != slen) {
653 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
654 }
655 } else {
656 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000657 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
659cleanup:
660
Gilles Peskine449bd832023-01-11 14:50:10 +0100661 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000662}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000664
665/*
Janos Follatha778a942019-02-13 10:28:28 +0000666 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100667 *
668 * This function is guaranteed to return an MPI with exactly the necessary
669 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000670 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100671int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
672 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000673{
Janos Follath24eed8d2019-11-22 13:21:35 +0000674 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100675 const size_t limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000676
677 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100678 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000679
Gilles Peskine449bd832023-01-11 14:50:10 +0100680 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Janos Follatha778a942019-02-13 10:28:28 +0000681
682cleanup:
683
Janos Follath171a7ef2019-02-15 16:17:45 +0000684 /*
685 * This function is also used to import keys. However, wiping the buffers
686 * upon failure is not necessary because failure only can happen before any
687 * input is copied.
688 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100689 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000690}
691
692/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000693 * Import X from unsigned binary data, big 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).
Paul Bakker5121ce52009-01-03 21:22:43 +0000697 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100698int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000699{
Janos Follath24eed8d2019-11-22 13:21:35 +0000700 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100701 const size_t limbs = CHARS_TO_LIMBS(buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
Gilles Peskine449bd832023-01-11 14:50:10 +0100703 MPI_VALIDATE_RET(X != NULL);
704 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000705
Hanno Becker073c1992017-10-17 15:17:27 +0100706 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100707 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
Gilles Peskine449bd832023-01-11 14:50:10 +0100709 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000710
711cleanup:
712
Janos Follath171a7ef2019-02-15 16:17:45 +0000713 /*
714 * This function is also used to import keys. However, wiping the buffers
715 * upon failure is not necessary because failure only can happen before any
716 * input is copied.
717 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000719}
720
721/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000722 * Export X into unsigned binary data, little endian
723 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100724int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
725 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000726{
Gilles Peskine449bd832023-01-11 14:50:10 +0100727 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Janos Follathe344d0f2019-02-19 16:17:40 +0000728}
729
730/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000731 * Export X into unsigned binary data, big endian
732 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100733int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
734 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000735{
Gilles Peskine449bd832023-01-11 14:50:10 +0100736 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000737}
738
739/*
740 * Left-shift: X <<= count
741 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100742int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000743{
Janos Follath24eed8d2019-11-22 13:21:35 +0000744 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Minos Galanakis0144b352023-05-02 14:02:32 +0100745 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100746 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000747
Gilles Peskine449bd832023-01-11 14:50:10 +0100748 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000749
Gilles Peskine449bd832023-01-11 14:50:10 +0100750 if (X->n * biL < i) {
751 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
752 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000753
754 ret = 0;
755
Minos Galanakis0144b352023-05-02 14:02:32 +0100756 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Paul Bakker5121ce52009-01-03 21:22:43 +0000757cleanup:
758
Gilles Peskine449bd832023-01-11 14:50:10 +0100759 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000760}
761
762/*
763 * Right-shift: X >>= count
764 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100765int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000766{
Gilles Peskine449bd832023-01-11 14:50:10 +0100767 MPI_VALIDATE_RET(X != NULL);
768 if (X->n != 0) {
769 mbedtls_mpi_core_shift_r(X->p, X->n, count);
770 }
771 return 0;
Gilles Peskine66414202022-09-21 15:36:16 +0200772}
773
Paul Bakker5121ce52009-01-03 21:22:43 +0000774/*
775 * Compare unsigned values
776 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100777int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000778{
Paul Bakker23986e52011-04-24 08:57:21 +0000779 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100780 MPI_VALIDATE_RET(X != NULL);
781 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
Gilles Peskine449bd832023-01-11 14:50:10 +0100783 for (i = X->n; i > 0; i--) {
784 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000785 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100786 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000787 }
788
Gilles Peskine449bd832023-01-11 14:50:10 +0100789 for (j = Y->n; j > 0; j--) {
790 if (Y->p[j - 1] != 0) {
791 break;
792 }
793 }
794
795 if (i == 0 && j == 0) {
796 return 0;
797 }
798
799 if (i > j) {
800 return 1;
801 }
802 if (j > i) {
803 return -1;
804 }
805
806 for (; i > 0; i--) {
807 if (X->p[i - 1] > Y->p[i - 1]) {
808 return 1;
809 }
810 if (X->p[i - 1] < Y->p[i - 1]) {
811 return -1;
812 }
813 }
814
815 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000816}
817
818/*
819 * Compare signed values
820 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100821int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000822{
Paul Bakker23986e52011-04-24 08:57:21 +0000823 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100824 MPI_VALIDATE_RET(X != NULL);
825 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000826
Gilles Peskine449bd832023-01-11 14:50:10 +0100827 for (i = X->n; i > 0; i--) {
828 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000829 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100830 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 }
832
Gilles Peskine449bd832023-01-11 14:50:10 +0100833 for (j = Y->n; j > 0; j--) {
834 if (Y->p[j - 1] != 0) {
835 break;
836 }
837 }
838
839 if (i == 0 && j == 0) {
840 return 0;
841 }
842
843 if (i > j) {
844 return X->s;
845 }
846 if (j > i) {
847 return -Y->s;
848 }
849
850 if (X->s > 0 && Y->s < 0) {
851 return 1;
852 }
853 if (Y->s > 0 && X->s < 0) {
854 return -1;
855 }
856
857 for (; i > 0; i--) {
858 if (X->p[i - 1] > Y->p[i - 1]) {
859 return X->s;
860 }
861 if (X->p[i - 1] < Y->p[i - 1]) {
862 return -X->s;
863 }
864 }
865
866 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000867}
868
Janos Follathee6abce2019-09-05 14:47:19 +0100869/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000870 * Compare signed values
871 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100872int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000873{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 mbedtls_mpi Y;
875 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +0100876 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000877
Gilles Peskine449bd832023-01-11 14:50:10 +0100878 *p = mpi_sint_abs(z);
879 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000880 Y.n = 1;
881 Y.p = p;
882
Gilles Peskine449bd832023-01-11 14:50:10 +0100883 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +0000884}
885
886/*
887 * Unsigned addition: X = |A| + |B| (HAC 14.7)
888 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100889int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +0000890{
Janos Follath24eed8d2019-11-22 13:21:35 +0000891 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100892 size_t j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100893 MPI_VALIDATE_RET(X != NULL);
894 MPI_VALIDATE_RET(A != NULL);
895 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000896
Gilles Peskine449bd832023-01-11 14:50:10 +0100897 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000899 }
900
Gilles Peskine449bd832023-01-11 14:50:10 +0100901 if (X != A) {
902 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
903 }
Paul Bakker9af723c2014-05-01 13:03:14 +0200904
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000905 /*
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100906 * X must always be positive as a result of unsigned additions.
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000907 */
908 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
Gilles Peskine449bd832023-01-11 14:50:10 +0100910 for (j = B->n; j > 0; j--) {
911 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000912 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100913 }
914 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000915
Gilles Peskinedb14a9d2022-11-15 22:59:00 +0100916 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
917 * and B is 0 (of any size). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100918 if (j == 0) {
919 return 0;
920 }
Gilles Peskinedb14a9d2022-11-15 22:59:00 +0100921
Gilles Peskine449bd832023-01-11 14:50:10 +0100922 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +0000923
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100924 /* j is the number of non-zero limbs of B. Add those to X. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000925
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100926 mbedtls_mpi_uint *p = X->p;
927
Gilles Peskine449bd832023-01-11 14:50:10 +0100928 mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j);
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100929
930 p += j;
931
932 /* Now propagate any carry */
Paul Bakker5121ce52009-01-03 21:22:43 +0000933
Gilles Peskine449bd832023-01-11 14:50:10 +0100934 while (c != 0) {
935 if (j >= X->n) {
936 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100937 p = X->p + j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000938 }
939
Gilles Peskine449bd832023-01-11 14:50:10 +0100940 *p += c; c = (*p < c); j++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000941 }
942
943cleanup:
944
Gilles Peskine449bd832023-01-11 14:50:10 +0100945 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000946}
947
Paul Bakker5121ce52009-01-03 21:22:43 +0000948/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +0200949 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +0000950 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100951int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +0000952{
Janos Follath24eed8d2019-11-22 13:21:35 +0000953 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000954 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +0200955 mbedtls_mpi_uint carry;
Gilles Peskine449bd832023-01-11 14:50:10 +0100956 MPI_VALIDATE_RET(X != NULL);
957 MPI_VALIDATE_RET(A != NULL);
958 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000959
Gilles Peskine449bd832023-01-11 14:50:10 +0100960 for (n = B->n; n > 0; n--) {
961 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000962 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100963 }
964 }
965 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +0100966 /* B >= (2^ciL)^n > A */
967 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
968 goto cleanup;
969 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000970
Gilles Peskine449bd832023-01-11 14:50:10 +0100971 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200972
973 /* Set the high limbs of X to match A. Don't touch the lower limbs
974 * because X might be aliased to B, and we must not overwrite the
975 * significant digits of B. */
Aaron M. Uckoaf67d2c2023-01-17 11:52:22 -0500976 if (A->n > n && A != X) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100977 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
978 }
979 if (X->n > A->n) {
980 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
981 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200982
Gilles Peskine449bd832023-01-11 14:50:10 +0100983 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
984 if (carry != 0) {
Tom Cosgrove452c99c2022-08-25 10:07:07 +0100985 /* Propagate the carry through the rest of X. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100986 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
Tom Cosgrove452c99c2022-08-25 10:07:07 +0100987
988 /* If we have further carry/borrow, the result is negative. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100989 if (carry != 0) {
Gilles Peskine89b41302020-07-23 01:16:46 +0200990 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
991 goto cleanup;
992 }
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200993 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000994
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200995 /* X should always be positive as a result of unsigned subtractions. */
996 X->s = 1;
997
Paul Bakker5121ce52009-01-03 21:22:43 +0000998cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100999 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001000}
1001
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001002/* Common function for signed addition and subtraction.
1003 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001004 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001005static int add_sub_mpi(mbedtls_mpi *X,
1006 const mbedtls_mpi *A, const mbedtls_mpi *B,
1007 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001008{
Hanno Becker73d7d792018-12-11 10:35:51 +00001009 int ret, s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001010 MPI_VALIDATE_RET(X != NULL);
1011 MPI_VALIDATE_RET(A != NULL);
1012 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001013
Hanno Becker73d7d792018-12-11 10:35:51 +00001014 s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001015 if (A->s * B->s * flip_B < 0) {
1016 int cmp = mbedtls_mpi_cmp_abs(A, B);
1017 if (cmp >= 0) {
1018 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001019 /* If |A| = |B|, the result is 0 and we must set the sign bit
1020 * to +1 regardless of which of A or B was negative. Otherwise,
1021 * since |A| > |B|, the sign is the sign of A. */
1022 X->s = cmp == 0 ? 1 : s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001023 } else {
1024 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001025 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001026 X->s = -s;
1027 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 } else {
1029 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 X->s = s;
1031 }
1032
1033cleanup:
1034
Gilles Peskine449bd832023-01-11 14:50:10 +01001035 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001036}
1037
1038/*
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001039 * Signed addition: X = A + B
1040 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001041int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001042{
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 return add_sub_mpi(X, A, B, 1);
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001044}
1045
1046/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001047 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001049int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001050{
Gilles Peskine449bd832023-01-11 14:50:10 +01001051 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001052}
1053
1054/*
1055 * Signed addition: X = A + b
1056 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001057int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001058{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001059 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001061 MPI_VALIDATE_RET(X != NULL);
1062 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001063
Gilles Peskine449bd832023-01-11 14:50:10 +01001064 p[0] = mpi_sint_abs(b);
1065 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001066 B.n = 1;
1067 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001068
Gilles Peskine449bd832023-01-11 14:50:10 +01001069 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001070}
1071
1072/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001073 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001074 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001075int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001076{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001077 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 MPI_VALIDATE_RET(X != NULL);
1080 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001081
Gilles Peskine449bd832023-01-11 14:50:10 +01001082 p[0] = mpi_sint_abs(b);
1083 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001084 B.n = 1;
1085 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001086
Gilles Peskine449bd832023-01-11 14:50:10 +01001087 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001088}
1089
Paul Bakker5121ce52009-01-03 21:22:43 +00001090/*
1091 * Baseline multiplication: X = A * B (HAC 14.12)
1092 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001093int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001094{
Janos Follath24eed8d2019-11-22 13:21:35 +00001095 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001096 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001097 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001098 int result_is_zero = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001099 MPI_VALIDATE_RET(X != NULL);
1100 MPI_VALIDATE_RET(A != NULL);
1101 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001102
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001103 mbedtls_mpi_init(&TA);
1104 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001105
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 if (X == A) {
1107 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1108 }
1109 if (X == B) {
1110 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1111 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001112
Gilles Peskine449bd832023-01-11 14:50:10 +01001113 for (i = A->n; i > 0; i--) {
1114 if (A->p[i - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001115 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001116 }
1117 }
1118 if (i == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001119 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001120 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001121
Gilles Peskine449bd832023-01-11 14:50:10 +01001122 for (j = B->n; j > 0; j--) {
1123 if (B->p[j - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001124 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001125 }
1126 }
1127 if (j == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001128 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001129 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001130
Gilles Peskine449bd832023-01-11 14:50:10 +01001131 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1132 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001133
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001134 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Paul Bakker5121ce52009-01-03 21:22:43 +00001135
Hanno Beckerda763de2022-04-13 06:50:02 +01001136 /* If the result is 0, we don't shortcut the operation, which reduces
1137 * but does not eliminate side channels leaking the zero-ness. We do
1138 * need to take care to set the sign bit properly since the library does
1139 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001140 if (result_is_zero) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001141 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001142 } else {
Hanno Beckerda763de2022-04-13 06:50:02 +01001143 X->s = A->s * B->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001144 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001145
1146cleanup:
1147
Gilles Peskine449bd832023-01-11 14:50:10 +01001148 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001149
Gilles Peskine449bd832023-01-11 14:50:10 +01001150 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001151}
1152
1153/*
1154 * Baseline multiplication: X = A * b
1155 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001156int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001157{
Gilles Peskine449bd832023-01-11 14:50:10 +01001158 MPI_VALIDATE_RET(X != NULL);
1159 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001160
Hanno Becker35771312022-04-14 11:52:11 +01001161 size_t n = A->n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001162 while (n > 0 && A->p[n - 1] == 0) {
Hanno Becker35771312022-04-14 11:52:11 +01001163 --n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001164 }
Hanno Becker35771312022-04-14 11:52:11 +01001165
Hanno Becker74a11a32022-04-06 06:27:00 +01001166 /* The general method below doesn't work if b==0. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001167 if (b == 0 || n == 0) {
1168 return mbedtls_mpi_lset(X, 0);
1169 }
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001170
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001171 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001172 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001173 /* In general, A * b requires 1 limb more than b. If
1174 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1175 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001176 * copy() will take care of the growth if needed. However, experimentally,
1177 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001178 * calls to calloc() in ECP code, presumably because it reuses the
1179 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001180 * grow to its final size.
1181 *
1182 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1183 * A,X can be the same. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001184 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1185 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1186 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001187
1188cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001189 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001190}
1191
1192/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001193 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1194 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001195 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001196static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1197 mbedtls_mpi_uint u0,
1198 mbedtls_mpi_uint d,
1199 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001200{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001201#if defined(MBEDTLS_HAVE_UDBL)
1202 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001203#else
Simon Butcher9803d072016-01-03 00:24:34 +00001204 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001205 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001206 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1207 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001208 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001209#endif
1210
Simon Butcher15b15d12015-11-26 19:35:03 +00001211 /*
1212 * Check for overflow
1213 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001214 if (0 == d || u1 >= d) {
1215 if (r != NULL) {
1216 *r = ~(mbedtls_mpi_uint) 0u;
1217 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001218
Gilles Peskine449bd832023-01-11 14:50:10 +01001219 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001220 }
1221
1222#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001223 dividend = (mbedtls_t_udbl) u1 << biL;
1224 dividend |= (mbedtls_t_udbl) u0;
1225 quotient = dividend / d;
Gilles Peskine449bd832023-01-11 14:50:10 +01001226 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1227 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1228 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001229
Gilles Peskine449bd832023-01-11 14:50:10 +01001230 if (r != NULL) {
1231 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1232 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001233
1234 return (mbedtls_mpi_uint) quotient;
1235#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001236
1237 /*
1238 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1239 * Vol. 2 - Seminumerical Algorithms, Knuth
1240 */
1241
1242 /*
1243 * Normalize the divisor, d, and dividend, u0, u1
1244 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001245 s = mbedtls_mpi_core_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001246 d = d << s;
1247
1248 u1 = u1 << s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001249 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001250 u0 = u0 << s;
1251
1252 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001253 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001254
1255 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001256 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001257
1258 /*
1259 * Find the first quotient and remainder
1260 */
1261 q1 = u1 / d1;
1262 r0 = u1 - d1 * q1;
1263
Gilles Peskine449bd832023-01-11 14:50:10 +01001264 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001265 q1 -= 1;
1266 r0 += d1;
1267
Gilles Peskine449bd832023-01-11 14:50:10 +01001268 if (r0 >= radix) {
1269 break;
1270 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001271 }
1272
Gilles Peskine449bd832023-01-11 14:50:10 +01001273 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001274 q0 = rAX / d1;
1275 r0 = rAX - q0 * d1;
1276
Gilles Peskine449bd832023-01-11 14:50:10 +01001277 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001278 q0 -= 1;
1279 r0 += d1;
1280
Gilles Peskine449bd832023-01-11 14:50:10 +01001281 if (r0 >= radix) {
1282 break;
1283 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001284 }
1285
Gilles Peskine449bd832023-01-11 14:50:10 +01001286 if (r != NULL) {
1287 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1288 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001289
1290 quotient = q1 * radix + q0;
1291
1292 return quotient;
1293#endif
1294}
1295
1296/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001297 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001298 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001299int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1300 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001301{
Janos Follath24eed8d2019-11-22 13:21:35 +00001302 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001303 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001304 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001305 mbedtls_mpi_uint TP2[3];
Gilles Peskine449bd832023-01-11 14:50:10 +01001306 MPI_VALIDATE_RET(A != NULL);
1307 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001308
Gilles Peskine449bd832023-01-11 14:50:10 +01001309 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1310 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1311 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001312
Gilles Peskine449bd832023-01-11 14:50:10 +01001313 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1314 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001315 /*
1316 * Avoid dynamic memory allocations for constant-size T2.
1317 *
1318 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1319 * so nobody increase the size of the MPI and we're safe to use an on-stack
1320 * buffer.
1321 */
Alexander K35d6d462019-10-31 14:46:45 +03001322 T2.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001323 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001324 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001325
Gilles Peskine449bd832023-01-11 14:50:10 +01001326 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1327 if (Q != NULL) {
1328 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1329 }
1330 if (R != NULL) {
1331 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1332 }
1333 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001334 }
1335
Gilles Peskine449bd832023-01-11 14:50:10 +01001336 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1337 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 X.s = Y.s = 1;
1339
Gilles Peskine449bd832023-01-11 14:50:10 +01001340 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1341 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1342 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001343
Gilles Peskine449bd832023-01-11 14:50:10 +01001344 k = mbedtls_mpi_bitlen(&Y) % biL;
1345 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001346 k = biL - 1 - k;
Gilles Peskine449bd832023-01-11 14:50:10 +01001347 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1348 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1349 } else {
1350 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001351 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001352
1353 n = X.n - 1;
1354 t = Y.n - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001355 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001356
Gilles Peskine449bd832023-01-11 14:50:10 +01001357 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 Z.p[n - t]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001359 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001361 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
Gilles Peskine449bd832023-01-11 14:50:10 +01001363 for (i = n; i > t; i--) {
1364 if (X.p[i] >= Y.p[t]) {
1365 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1366 } else {
1367 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1368 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001369 }
1370
Gilles Peskine449bd832023-01-11 14:50:10 +01001371 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1372 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001373 T2.p[2] = X.p[i];
1374
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 Z.p[i - t - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001376 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001377 Z.p[i - t - 1]--;
1378
Gilles Peskine449bd832023-01-11 14:50:10 +01001379 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1380 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001381 T1.p[1] = Y.p[t];
Gilles Peskine449bd832023-01-11 14:50:10 +01001382 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1383 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
Gilles Peskine449bd832023-01-11 14:50:10 +01001385 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1386 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1387 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001388
Gilles Peskine449bd832023-01-11 14:50:10 +01001389 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1390 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1391 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1392 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 Z.p[i - t - 1]--;
1394 }
1395 }
1396
Gilles Peskine449bd832023-01-11 14:50:10 +01001397 if (Q != NULL) {
1398 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 Q->s = A->s * B->s;
1400 }
1401
Gilles Peskine449bd832023-01-11 14:50:10 +01001402 if (R != NULL) {
1403 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001404 X.s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001405 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001406
Gilles Peskine449bd832023-01-11 14:50:10 +01001407 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001408 R->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001409 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 }
1411
1412cleanup:
1413
Gilles Peskine449bd832023-01-11 14:50:10 +01001414 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1415 mbedtls_mpi_free(&T1);
1416 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
Gilles Peskine449bd832023-01-11 14:50:10 +01001418 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001419}
1420
1421/*
1422 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001423 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001424int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1425 const mbedtls_mpi *A,
1426 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001427{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001428 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001429 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001430 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001431
Gilles Peskine449bd832023-01-11 14:50:10 +01001432 p[0] = mpi_sint_abs(b);
1433 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001434 B.n = 1;
1435 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001436
Gilles Peskine449bd832023-01-11 14:50:10 +01001437 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001438}
1439
1440/*
1441 * Modulo: R = A mod B
1442 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001443int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001444{
Janos Follath24eed8d2019-11-22 13:21:35 +00001445 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01001446 MPI_VALIDATE_RET(R != NULL);
1447 MPI_VALIDATE_RET(A != NULL);
1448 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001449
Gilles Peskine449bd832023-01-11 14:50:10 +01001450 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1451 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1452 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001453
Gilles Peskine449bd832023-01-11 14:50:10 +01001454 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001455
Gilles Peskine449bd832023-01-11 14:50:10 +01001456 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1457 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1458 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001459
Gilles Peskine449bd832023-01-11 14:50:10 +01001460 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1461 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1462 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001463
1464cleanup:
1465
Gilles Peskine449bd832023-01-11 14:50:10 +01001466 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001467}
1468
1469/*
1470 * Modulo: r = A mod b
1471 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001472int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001473{
Paul Bakker23986e52011-04-24 08:57:21 +00001474 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 mbedtls_mpi_uint x, y, z;
Gilles Peskine449bd832023-01-11 14:50:10 +01001476 MPI_VALIDATE_RET(r != NULL);
1477 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
Gilles Peskine449bd832023-01-11 14:50:10 +01001479 if (b == 0) {
1480 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1481 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
Gilles Peskine449bd832023-01-11 14:50:10 +01001483 if (b < 0) {
1484 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1485 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
1487 /*
1488 * handle trivial cases
1489 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001490 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001491 *r = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001492 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001493 }
1494
Gilles Peskine449bd832023-01-11 14:50:10 +01001495 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001496 *r = A->p[0] & 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001497 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001498 }
1499
1500 /*
1501 * general case
1502 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001503 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001504 x = A->p[i - 1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001505 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 z = y / b;
1507 y -= z * b;
1508
1509 x <<= biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001510 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001511 z = y / b;
1512 y -= z * b;
1513 }
1514
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001515 /*
1516 * If A is negative, then the current y represents a negative value.
1517 * Flipping it to the positive side.
1518 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001519 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001520 y = b - y;
Gilles Peskine449bd832023-01-11 14:50:10 +01001521 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001522
Paul Bakker5121ce52009-01-03 21:22:43 +00001523 *r = y;
1524
Gilles Peskine449bd832023-01-11 14:50:10 +01001525 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001526}
1527
Gilles Peskine449bd832023-01-11 14:50:10 +01001528static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001529{
Gilles Peskine449bd832023-01-11 14:50:10 +01001530 *mm = mbedtls_mpi_core_montmul_init(N->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001531}
1532
Tom Cosgrove93842842022-08-05 16:59:43 +01001533/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1534 *
1535 * \param[in,out] A One of the numbers to multiply.
1536 * It must have at least as many limbs as N
1537 * (A->n >= N->n), and any limbs beyond n are ignored.
1538 * On successful completion, A contains the result of
1539 * the multiplication A * B * R^-1 mod N where
1540 * R = (2^ciL)^n.
1541 * \param[in] B One of the numbers to multiply.
1542 * It must be nonzero and must not have more limbs than N
1543 * (B->n <= N->n).
Tom Cosgrove40d22942022-08-17 06:42:44 +01001544 * \param[in] N The modulus. \p N must be odd.
Tom Cosgrove93842842022-08-05 16:59:43 +01001545 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1546 * This is -N^-1 mod 2^ciL.
1547 * \param[in,out] T A bignum for temporary storage.
1548 * It must be at least twice the limb size of N plus 1
1549 * (T->n >= 2 * N->n + 1).
1550 * Its initial content is unused and
1551 * its final content is indeterminate.
Tom Cosgrove5dd97e62022-08-30 14:31:49 +01001552 * It does not get reallocated.
Tom Cosgrove93842842022-08-05 16:59:43 +01001553 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001554static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1555 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1556 mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001557{
Gilles Peskine449bd832023-01-11 14:50:10 +01001558 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 +00001559}
1560
1561/*
1562 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001563 *
Tom Cosgrove93842842022-08-05 16:59:43 +01001564 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001565 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001566static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1567 mbedtls_mpi_uint mm, mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001568{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 mbedtls_mpi_uint z = 1;
1570 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
Paul Bakker8ddb6452013-02-27 14:56:33 +01001572 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001573 U.p = &z;
1574
Gilles Peskine449bd832023-01-11 14:50:10 +01001575 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001576}
1577
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001578/**
1579 * Select an MPI from a table without leaking the index.
1580 *
1581 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1582 * reads the entire table in order to avoid leaking the value of idx to an
1583 * attacker able to observe memory access patterns.
1584 *
1585 * \param[out] R Where to write the selected MPI.
1586 * \param[in] T The table to read from.
1587 * \param[in] T_size The number of elements in the table.
1588 * \param[in] idx The index of the element to select;
1589 * this must satisfy 0 <= idx < T_size.
1590 *
1591 * \return \c 0 on success, or a negative error code.
1592 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001593static 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 +01001594{
1595 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1596
Gilles Peskine449bd832023-01-11 14:50:10 +01001597 for (size_t i = 0; i < T_size; i++) {
1598 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
1599 (unsigned char) mbedtls_ct_size_bool_eq(i,
1600 idx)));
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001601 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001602
1603cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001604 return ret;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001605}
1606
Paul Bakker5121ce52009-01-03 21:22:43 +00001607/*
1608 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1609 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001610int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1611 const mbedtls_mpi *E, const mbedtls_mpi *N,
1612 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00001613{
Janos Follath24eed8d2019-11-22 13:21:35 +00001614 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath74601202022-11-21 15:54:20 +00001615 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00001616 size_t i, j, nblimbs;
1617 size_t bufsize, nbits;
Paul Elliott1748de12023-02-13 15:35:35 +00001618 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine449bd832023-01-11 14:50:10 +01001620 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001621 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001622
Gilles Peskine449bd832023-01-11 14:50:10 +01001623 MPI_VALIDATE_RET(X != NULL);
1624 MPI_VALIDATE_RET(A != NULL);
1625 MPI_VALIDATE_RET(E != NULL);
1626 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001627
Gilles Peskine449bd832023-01-11 14:50:10 +01001628 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1629 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1630 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Gilles Peskine449bd832023-01-11 14:50:10 +01001632 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1633 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1634 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00001635
Gilles Peskine449bd832023-01-11 14:50:10 +01001636 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1637 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1638 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1639 }
Chris Jones9246d042020-11-25 15:12:39 +00001640
Paul Bakkerf6198c12012-05-16 08:02:29 +00001641 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001642 * Init temps and window size
1643 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001644 mpi_montg_init(&mm, N);
1645 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
1646 mbedtls_mpi_init(&Apos);
1647 mbedtls_mpi_init(&WW);
1648 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00001649
Gilles Peskine449bd832023-01-11 14:50:10 +01001650 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00001651
Gilles Peskine449bd832023-01-11 14:50:10 +01001652 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1653 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
Gilles Peskine449bd832023-01-11 14:50:10 +01001655#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
1656 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath7fa11b82022-11-21 14:48:02 +00001657 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +01001658 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001659#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001660
Janos Follathc8d66d52022-11-22 10:47:10 +00001661 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath06000952022-11-22 10:18:06 +00001662
Paul Bakker5121ce52009-01-03 21:22:43 +00001663 /*
Janos Follathbe54ca72022-11-21 16:14:54 +00001664 * This function is not constant-trace: its memory accesses depend on the
1665 * exponent value. To defend against timing attacks, callers (such as RSA
1666 * and DHM) should use exponent blinding. However this is not enough if the
1667 * adversary can find the exponent in a single trace, so this function
1668 * takes extra precautions against adversaries who can observe memory
1669 * access patterns.
Janos Follathf08b40e2022-11-11 15:56:38 +00001670 *
Janos Follathbe54ca72022-11-21 16:14:54 +00001671 * This function performs a series of multiplications by table elements and
1672 * squarings, and we want the prevent the adversary from finding out which
1673 * table element was used, and from distinguishing between multiplications
1674 * and squarings. Firstly, when multiplying by an element of the window
1675 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
1676 * squarings as having a different memory access patterns from other
1677 * multiplications. So secondly, we put the accumulator X in the table as
1678 * well, and also do a constant-trace table lookup to multiply by X.
1679 *
1680 * This way, all multiplications take the form of a lookup-and-multiply.
1681 * The number of lookup-and-multiply operations inside each iteration of
1682 * the main loop still depends on the bits of the exponent, but since the
1683 * other operations in the loop don't have an easily recognizable memory
1684 * trace, an adversary is unlikely to be able to observe the exact
1685 * patterns.
1686 *
1687 * An adversary may still be able to recover the exponent if they can
1688 * observe both memory accesses and branches. However, branch prediction
1689 * exploitation typically requires many traces of execution over the same
1690 * data, which is defeated by randomized blinding.
Janos Follath84461482022-11-21 14:31:22 +00001691 *
1692 * To achieve this, we make a copy of X and we use the table entry in each
1693 * calculation from this point on.
Janos Follath8e7d6a02022-10-04 13:27:40 +01001694 */
Janos Follathc8d66d52022-11-22 10:47:10 +00001695 const size_t x_index = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001696 mbedtls_mpi_init(&W[x_index]);
1697 mbedtls_mpi_copy(&W[x_index], X);
Janos Follath84461482022-11-21 14:31:22 +00001698
Paul Bakker5121ce52009-01-03 21:22:43 +00001699 j = N->n + 1;
Tom Cosgrove93842842022-08-05 16:59:43 +01001700 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
Paul Bakker5121ce52009-01-03 21:22:43 +00001701 * and mpi_montred() calls later. Here we ensure that W[1] and X are
1702 * large enough, and later we'll grow other W[i] to the same length.
1703 * They must not be shrunk midway through this function!
1704 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001705 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1706 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
1707 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001708
1709 /*
Paul Bakker50546922012-05-19 08:40:49 +00001710 * Compensate for negative A (and correct at the end)
1711 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001712 neg = (A->s == -1);
1713 if (neg) {
1714 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00001715 Apos.s = 1;
1716 A = &Apos;
1717 }
1718
1719 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 * If 1st call, pre-compute R^2 mod N
1721 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001722 if (prec_RR == NULL || prec_RR->p == NULL) {
1723 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
1724 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
1725 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
Gilles Peskine449bd832023-01-11 14:50:10 +01001727 if (prec_RR != NULL) {
1728 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
1729 }
1730 } else {
1731 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00001732 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
1734 /*
1735 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1736 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001737 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1738 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001739 /* This should be a no-op because W[1] is already that large before
1740 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Tom Cosgrove93842842022-08-05 16:59:43 +01001741 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001742 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
1743 } else {
1744 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001745 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001746
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001747 /* Note that this is safe because W[1] always has at least N->n limbs
1748 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001749 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001750
1751 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001752 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001753 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001754 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1755 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001756
Janos Follathc8d66d52022-11-22 10:47:10 +00001757
Gilles Peskine449bd832023-01-11 14:50:10 +01001758 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001759 /*
Janos Follath74601202022-11-21 15:54:20 +00001760 * W[i] = W[1] ^ i
1761 *
1762 * The first bit of the sliding window is always 1 and therefore we
1763 * only need to store the second half of the table.
Janos Follathc8d66d52022-11-22 10:47:10 +00001764 *
1765 * (There are two special elements in the table: W[0] for the
1766 * accumulator/result and W[1] for A in Montgomery form. Both of these
1767 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00001768 */
Janos Follath74601202022-11-21 15:54:20 +00001769 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
Gilles Peskine449bd832023-01-11 14:50:10 +01001771 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1772 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001773
Gilles Peskine449bd832023-01-11 14:50:10 +01001774 for (i = 0; i < window_bitsize - 1; i++) {
1775 mpi_montmul(&W[j], &W[j], N, mm, &T);
1776 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01001777
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 /*
1779 * W[i] = W[i - 1] * W[1]
1780 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001781 for (i = j + 1; i < w_table_used_size; i++) {
1782 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1783 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001784
Gilles Peskine449bd832023-01-11 14:50:10 +01001785 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001786 }
1787 }
1788
1789 nblimbs = E->n;
1790 bufsize = 0;
1791 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001792 state = 0;
1793
Gilles Peskine449bd832023-01-11 14:50:10 +01001794 while (1) {
1795 if (bufsize == 0) {
1796 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001797 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001798 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001799
Paul Bakker0d7702c2013-10-29 16:18:35 +01001800 nblimbs--;
1801
Gilles Peskine449bd832023-01-11 14:50:10 +01001802 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001803 }
1804
1805 bufsize--;
1806
1807 ei = (E->p[nblimbs] >> bufsize) & 1;
1808
1809 /*
1810 * skip leading 0s
1811 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001812 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001813 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01001814 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Gilles Peskine449bd832023-01-11 14:50:10 +01001816 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001817 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001818 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001820 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1821 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001822 continue;
1823 }
1824
1825 /*
1826 * add ei to current window
1827 */
1828 state = 2;
1829
1830 nbits++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001831 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00001832
Gilles Peskine449bd832023-01-11 14:50:10 +01001833 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001835 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001836 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001837 for (i = 0; i < window_bitsize; i++) {
1838 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1839 x_index));
1840 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001841 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001842
1843 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001844 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001845 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001846 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1847 exponent_bits_in_window));
1848 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850 state--;
1851 nbits = 0;
Janos Follath7fa11b82022-11-21 14:48:02 +00001852 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 }
1854 }
1855
1856 /*
1857 * process the remaining bits
1858 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001859 for (i = 0; i < nbits; i++) {
1860 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1861 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
Janos Follath7fa11b82022-11-21 14:48:02 +00001863 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001864
Gilles Peskine449bd832023-01-11 14:50:10 +01001865 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
1866 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
1867 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001868 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 }
1870
1871 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001872 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001874 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
Gilles Peskine449bd832023-01-11 14:50:10 +01001876 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath8e7d6a02022-10-04 13:27:40 +01001877 W[x_index].s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001878 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00001879 }
1880
Janos Follath8e7d6a02022-10-04 13:27:40 +01001881 /*
1882 * Load the result in the output variable.
1883 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001884 mbedtls_mpi_copy(X, &W[x_index]);
Janos Follath8e7d6a02022-10-04 13:27:40 +01001885
Paul Bakker5121ce52009-01-03 21:22:43 +00001886cleanup:
1887
Janos Follathb2c2fca2022-11-21 15:05:31 +00001888 /* The first bit of the sliding window is always 1 and therefore the first
1889 * half of the table was unused. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001890 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
1891 mbedtls_mpi_free(&W[i]);
1892 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
Gilles Peskine449bd832023-01-11 14:50:10 +01001894 mbedtls_mpi_free(&W[x_index]);
1895 mbedtls_mpi_free(&W[1]);
1896 mbedtls_mpi_free(&T);
1897 mbedtls_mpi_free(&Apos);
1898 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00001899
Gilles Peskine449bd832023-01-11 14:50:10 +01001900 if (prec_RR == NULL || prec_RR->p == NULL) {
1901 mbedtls_mpi_free(&RR);
1902 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
Gilles Peskine449bd832023-01-11 14:50:10 +01001904 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001905}
1906
Paul Bakker5121ce52009-01-03 21:22:43 +00001907/*
1908 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1909 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001910int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001911{
Janos Follath24eed8d2019-11-22 13:21:35 +00001912 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001913 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03001914 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
Gilles Peskine449bd832023-01-11 14:50:10 +01001916 MPI_VALIDATE_RET(G != NULL);
1917 MPI_VALIDATE_RET(A != NULL);
1918 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001919
Gilles Peskine449bd832023-01-11 14:50:10 +01001920 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
Gilles Peskine449bd832023-01-11 14:50:10 +01001922 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1923 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
Gilles Peskine449bd832023-01-11 14:50:10 +01001925 lz = mbedtls_mpi_lsb(&TA);
1926 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001927
Gilles Peskine27253bc2021-06-09 13:26:43 +02001928 /* The loop below gives the correct result when A==0 but not when B==0.
1929 * So have a special case for B==0. Leverage the fact that we just
1930 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1931 * slightly more efficient than cmp_int(). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001932 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1933 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02001934 goto cleanup;
1935 }
1936
Gilles Peskine449bd832023-01-11 14:50:10 +01001937 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001938 lz = lzt;
Gilles Peskine449bd832023-01-11 14:50:10 +01001939 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001940
Paul Bakker5121ce52009-01-03 21:22:43 +00001941 TA.s = TB.s = 1;
1942
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001943 /* We mostly follow the procedure described in HAC 14.54, but with some
1944 * minor differences:
1945 * - Sequences of multiplications or divisions by 2 are grouped into a
1946 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02001947 * - The procedure in HAC assumes that 0 < TB <= TA.
1948 * - The condition TB <= TA is not actually necessary for correctness.
1949 * TA and TB have symmetric roles except for the loop termination
1950 * condition, and the shifts at the beginning of the loop body
1951 * remove any significance from the ordering of TA vs TB before
1952 * the shifts.
1953 * - If TA = 0, the loop goes through 0 iterations and the result is
1954 * correctly TB.
1955 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001956 *
1957 * For the correctness proof below, decompose the original values of
1958 * A and B as
1959 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1960 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1961 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1962 * and gcd(A',B') is odd or 0.
1963 *
1964 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1965 * The code maintains the following invariant:
1966 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02001967 */
1968
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001969 /* Proof that the loop terminates:
1970 * At each iteration, either the right-shift by 1 is made on a nonzero
1971 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
1972 * by at least 1, or the right-shift by 1 is made on zero and then
1973 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
1974 * since in that case TB is calculated from TB-TA with the condition TB>TA).
1975 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001976 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001977 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001978 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
1979 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001980
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001981 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
1982 * TA-TB is even so the division by 2 has an integer result.
1983 * Invariant (I) is preserved since any odd divisor of both TA and TB
1984 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08001985 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001986 * divides TA.
1987 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001988 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
1989 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
1990 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
1991 } else {
1992 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
1993 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001994 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001995 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001996 }
1997
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001998 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
1999 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2000 * - If there was at least one loop iteration, then one of TA or TB is odd,
2001 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2002 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2003 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002004 * 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 +02002005 */
2006
Gilles Peskine449bd832023-01-11 14:50:10 +01002007 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2008 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002009
2010cleanup:
2011
Gilles Peskine449bd832023-01-11 14:50:10 +01002012 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
Gilles Peskine449bd832023-01-11 14:50:10 +01002014 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002015}
2016
Paul Bakker33dc46b2014-04-30 16:11:39 +02002017/*
2018 * Fill X with size bytes of random.
Gilles Peskine22cdd0c2022-10-27 20:15:13 +02002019 * The bytes returned from the RNG are used in a specific order which
2020 * is suitable for deterministic ECDSA (see the specification of
2021 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Paul Bakker33dc46b2014-04-30 16:11:39 +02002022 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002023int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2024 int (*f_rng)(void *, unsigned char *, size_t),
2025 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002026{
Janos Follath24eed8d2019-11-22 13:21:35 +00002027 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01002028 const size_t limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002029
Gilles Peskine449bd832023-01-11 14:50:10 +01002030 MPI_VALIDATE_RET(X != NULL);
2031 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002032
Hanno Beckerda1655a2017-10-18 14:21:44 +01002033 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +01002034 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2035 if (size == 0) {
2036 return 0;
2037 }
Paul Bakker287781a2011-03-26 13:18:49 +00002038
Gilles Peskine449bd832023-01-11 14:50:10 +01002039 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002040
2041cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002042 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002043}
2044
Gilles Peskine449bd832023-01-11 14:50:10 +01002045int mbedtls_mpi_random(mbedtls_mpi *X,
2046 mbedtls_mpi_sint min,
2047 const mbedtls_mpi *N,
2048 int (*f_rng)(void *, unsigned char *, size_t),
2049 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002050{
Gilles Peskine449bd832023-01-11 14:50:10 +01002051 if (min < 0) {
2052 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2053 }
2054 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2055 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2056 }
Gilles Peskine1e918f42021-03-29 22:14:51 +02002057
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002058 /* Ensure that target MPI has exactly the same number of limbs
2059 * as the upper bound, even if the upper bound has leading zeros.
Gilles Peskine6b7ce962022-12-15 15:04:33 +01002060 * This is necessary for mbedtls_mpi_core_random. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002061 int ret = mbedtls_mpi_resize_clear(X, N->n);
2062 if (ret != 0) {
2063 return ret;
2064 }
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002065
Gilles Peskine449bd832023-01-11 14:50:10 +01002066 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002067}
2068
Paul Bakker5121ce52009-01-03 21:22:43 +00002069/*
2070 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2071 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002072int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002073{
Janos Follath24eed8d2019-11-22 13:21:35 +00002074 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002075 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine449bd832023-01-11 14:50:10 +01002076 MPI_VALIDATE_RET(X != NULL);
2077 MPI_VALIDATE_RET(A != NULL);
2078 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002079
Gilles Peskine449bd832023-01-11 14:50:10 +01002080 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2081 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2082 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002083
Gilles Peskine449bd832023-01-11 14:50:10 +01002084 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2085 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2086 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002087
Gilles Peskine449bd832023-01-11 14:50:10 +01002088 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
Gilles Peskine449bd832023-01-11 14:50:10 +01002090 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002092 goto cleanup;
2093 }
2094
Gilles Peskine449bd832023-01-11 14:50:10 +01002095 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2096 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2097 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2098 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002099
Gilles Peskine449bd832023-01-11 14:50:10 +01002100 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2101 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2102 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2103 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
Gilles Peskine449bd832023-01-11 14:50:10 +01002105 do {
2106 while ((TU.p[0] & 1) == 0) {
2107 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
Gilles Peskine449bd832023-01-11 14:50:10 +01002109 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2110 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2111 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002112 }
2113
Gilles Peskine449bd832023-01-11 14:50:10 +01002114 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2115 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002116 }
2117
Gilles Peskine449bd832023-01-11 14:50:10 +01002118 while ((TV.p[0] & 1) == 0) {
2119 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
Gilles Peskine449bd832023-01-11 14:50:10 +01002121 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2122 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2123 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002124 }
2125
Gilles Peskine449bd832023-01-11 14:50:10 +01002126 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2127 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002128 }
2129
Gilles Peskine449bd832023-01-11 14:50:10 +01002130 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2131 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2132 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2133 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2134 } else {
2135 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2136 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2137 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002138 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002139 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2140
2141 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2142 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002143 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
Gilles Peskine449bd832023-01-11 14:50:10 +01002145 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2146 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2147 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002148
Gilles Peskine449bd832023-01-11 14:50:10 +01002149 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002150
2151cleanup:
2152
Gilles Peskine449bd832023-01-11 14:50:10 +01002153 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2154 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2155 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002156
Gilles Peskine449bd832023-01-11 14:50:10 +01002157 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002158}
2159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002161
Paul Bakker5121ce52009-01-03 21:22:43 +00002162static const int small_prime[] =
2163{
Gilles Peskine449bd832023-01-11 14:50:10 +01002164 3, 5, 7, 11, 13, 17, 19, 23,
2165 29, 31, 37, 41, 43, 47, 53, 59,
2166 61, 67, 71, 73, 79, 83, 89, 97,
2167 101, 103, 107, 109, 113, 127, 131, 137,
2168 139, 149, 151, 157, 163, 167, 173, 179,
2169 181, 191, 193, 197, 199, 211, 223, 227,
2170 229, 233, 239, 241, 251, 257, 263, 269,
2171 271, 277, 281, 283, 293, 307, 311, 313,
2172 317, 331, 337, 347, 349, 353, 359, 367,
2173 373, 379, 383, 389, 397, 401, 409, 419,
2174 421, 431, 433, 439, 443, 449, 457, 461,
2175 463, 467, 479, 487, 491, 499, 503, 509,
2176 521, 523, 541, 547, 557, 563, 569, 571,
2177 577, 587, 593, 599, 601, 607, 613, 617,
2178 619, 631, 641, 643, 647, 653, 659, 661,
2179 673, 677, 683, 691, 701, 709, 719, 727,
2180 733, 739, 743, 751, 757, 761, 769, 773,
2181 787, 797, 809, 811, 821, 823, 827, 829,
2182 839, 853, 857, 859, 863, 877, 881, 883,
2183 887, 907, 911, 919, 929, 937, 941, 947,
2184 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002185};
2186
2187/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002188 * Small divisors test (X must be positive)
2189 *
2190 * Return values:
2191 * 0: no small factor (possible prime, more tests needed)
2192 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002194 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002195 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002196static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002197{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002198 int ret = 0;
2199 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
Gilles Peskine449bd832023-01-11 14:50:10 +01002202 if ((X->p[0] & 1) == 0) {
2203 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2204 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
Gilles Peskine449bd832023-01-11 14:50:10 +01002206 for (i = 0; small_prime[i] > 0; i++) {
2207 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2208 return 1;
2209 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
Gilles Peskine449bd832023-01-11 14:50:10 +01002211 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
Gilles Peskine449bd832023-01-11 14:50:10 +01002213 if (r == 0) {
2214 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2215 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002216 }
2217
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002218cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002219 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002220}
2221
2222/*
2223 * Miller-Rabin pseudo-primality test (HAC 4.24)
2224 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002225static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2226 int (*f_rng)(void *, unsigned char *, size_t),
2227 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002228{
Pascal Junodb99183d2015-03-11 16:49:45 +01002229 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002230 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002232
Gilles Peskine449bd832023-01-11 14:50:10 +01002233 MPI_VALIDATE_RET(X != NULL);
2234 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002235
Gilles Peskine449bd832023-01-11 14:50:10 +01002236 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2237 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2238 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002239
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 /*
2241 * W = |X| - 1
2242 * R = W >> lsb( W )
2243 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002244 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2245 s = mbedtls_mpi_lsb(&W);
2246 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2247 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
Gilles Peskine449bd832023-01-11 14:50:10 +01002249 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002250 /*
2251 * pick a random A, 1 < A < |X| - 1
2252 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002253 count = 0;
2254 do {
Gilles Peskine449bd832023-01-11 14:50:10 +01002255 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002256
Gilles Peskine449bd832023-01-11 14:50:10 +01002257 j = mbedtls_mpi_bitlen(&A);
2258 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002259 if (j > k) {
Gilles Peskine449bd832023-01-11 14:50:10 +01002260 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002261 }
2262
2263 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002264 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2265 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002266 }
2267
Gilles Peskine449bd832023-01-11 14:50:10 +01002268 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2269 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002270
2271 /*
2272 * A = A^R mod |X|
2273 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002274 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
Gilles Peskine449bd832023-01-11 14:50:10 +01002276 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2277 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01002279 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002280
2281 j = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002282 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 /*
2284 * A = A * A mod |X|
2285 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002286 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2287 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002288
Gilles Peskine449bd832023-01-11 14:50:10 +01002289 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002290 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01002291 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
2293 j++;
2294 }
2295
2296 /*
2297 * not prime if A != |X| - 1 or A == 1
2298 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002299 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2300 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002302 break;
2303 }
2304 }
2305
2306cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002307 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2308 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2309 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
Gilles Peskine449bd832023-01-11 14:50:10 +01002311 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002312}
2313
2314/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002315 * Pseudo-primality test: small factors, then Miller-Rabin
2316 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002317int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2318 int (*f_rng)(void *, unsigned char *, size_t),
2319 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002320{
Janos Follath24eed8d2019-11-22 13:21:35 +00002321 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 mbedtls_mpi XX;
Gilles Peskine449bd832023-01-11 14:50:10 +01002323 MPI_VALIDATE_RET(X != NULL);
2324 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002325
2326 XX.s = 1;
2327 XX.n = X->n;
2328 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002329
Gilles Peskine449bd832023-01-11 14:50:10 +01002330 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2331 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2332 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002333 }
2334
Gilles Peskine449bd832023-01-11 14:50:10 +01002335 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2336 return 0;
2337 }
2338
2339 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2340 if (ret == 1) {
2341 return 0;
2342 }
2343
2344 return ret;
2345 }
2346
2347 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002348}
2349
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002350/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002351 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002352 *
Janos Follathf301d232018-08-14 13:34:01 +01002353 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2354 * be either 1024 bits or 1536 bits long, and flags must contain
2355 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002356 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002357int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2358 int (*f_rng)(void *, unsigned char *, size_t),
2359 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002360{
Jethro Beekman66689272018-02-14 19:24:10 -08002361#ifdef MBEDTLS_HAVE_INT64
2362// ceil(2^63.5)
2363#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2364#else
2365// ceil(2^31.5)
2366#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2367#endif
2368 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002369 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002370 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 mbedtls_mpi_uint r;
2372 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
Gilles Peskine449bd832023-01-11 14:50:10 +01002374 MPI_VALIDATE_RET(X != NULL);
2375 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002376
Gilles Peskine449bd832023-01-11 14:50:10 +01002377 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2378 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2379 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002380
Gilles Peskine449bd832023-01-11 14:50:10 +01002381 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Gilles Peskine449bd832023-01-11 14:50:10 +01002383 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Gilles Peskine449bd832023-01-11 14:50:10 +01002385 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002386 /*
2387 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2388 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002389 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2390 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2391 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2392 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002393 /*
2394 * 2^-100 error probability, number of rounds computed based on HAC,
2395 * fact 4.48
2396 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002397 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2398 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2399 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2400 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002401 }
2402
Gilles Peskine449bd832023-01-11 14:50:10 +01002403 while (1) {
2404 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002405 /* 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 +01002406 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2407 continue;
2408 }
Jethro Beekman66689272018-02-14 19:24:10 -08002409
2410 k = n * biL;
Gilles Peskine449bd832023-01-11 14:50:10 +01002411 if (k > nbits) {
2412 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2413 }
Jethro Beekman66689272018-02-14 19:24:10 -08002414 X->p[0] |= 1;
2415
Gilles Peskine449bd832023-01-11 14:50:10 +01002416 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2417 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002418
Gilles Peskine449bd832023-01-11 14:50:10 +01002419 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002420 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002421 }
2422 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002423 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002424 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002425 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2426 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002427 */
Jethro Beekman66689272018-02-14 19:24:10 -08002428
2429 X->p[0] |= 2;
2430
Gilles Peskine449bd832023-01-11 14:50:10 +01002431 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2432 if (r == 0) {
2433 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2434 } else if (r == 1) {
2435 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2436 }
Jethro Beekman66689272018-02-14 19:24:10 -08002437
2438 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine449bd832023-01-11 14:50:10 +01002439 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2440 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002441
Gilles Peskine449bd832023-01-11 14:50:10 +01002442 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002443 /*
2444 * First, check small factors for X and Y
2445 * before doing Miller-Rabin on any of them
2446 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002447 if ((ret = mpi_check_small_factors(X)) == 0 &&
2448 (ret = mpi_check_small_factors(&Y)) == 0 &&
2449 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2450 == 0 &&
2451 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2452 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002453 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002454 }
Jethro Beekman66689272018-02-14 19:24:10 -08002455
Gilles Peskine449bd832023-01-11 14:50:10 +01002456 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002457 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002458 }
Jethro Beekman66689272018-02-14 19:24:10 -08002459
2460 /*
2461 * Next candidates. We want to preserve Y = (X-1) / 2 and
2462 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2463 * so up Y by 6 and X by 12.
2464 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002465 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2466 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002467 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002468 }
2469 }
2470
2471cleanup:
2472
Gilles Peskine449bd832023-01-11 14:50:10 +01002473 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002474
Gilles Peskine449bd832023-01-11 14:50:10 +01002475 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002476}
2477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002481
Paul Bakker23986e52011-04-24 08:57:21 +00002482#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002483
2484static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2485{
2486 { 693, 609, 21 },
2487 { 1764, 868, 28 },
2488 { 768454923, 542167814, 1 }
2489};
2490
Paul Bakker5121ce52009-01-03 21:22:43 +00002491/*
2492 * Checkup routine
2493 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002494int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00002495{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002496 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
Gilles Peskine449bd832023-01-11 14:50:10 +01002499 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2500 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002501
Gilles Peskine449bd832023-01-11 14:50:10 +01002502 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2503 "EFE021C2645FD1DC586E69184AF4A31E" \
2504 "D5F53E93B5F123FA41680867BA110131" \
2505 "944FE7952E2517337780CB0DB80E61AA" \
2506 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002507
Gilles Peskine449bd832023-01-11 14:50:10 +01002508 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2509 "B2E7EFD37075B9F03FF989C7C5051C20" \
2510 "34D2A323810251127E7BF8625A4F49A5" \
2511 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2512 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002513
Gilles Peskine449bd832023-01-11 14:50:10 +01002514 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2515 "0066A198186C18C10B2F5ED9B522752A" \
2516 "9830B69916E535C8F047518A889A43A5" \
2517 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002518
Gilles Peskine449bd832023-01-11 14:50:10 +01002519 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002520
Gilles Peskine449bd832023-01-11 14:50:10 +01002521 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2522 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2523 "9E857EA95A03512E2BAE7391688D264A" \
2524 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2525 "8001B72E848A38CAE1C65F78E56ABDEF" \
2526 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2527 "ECF677152EF804370C1A305CAF3B5BF1" \
2528 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002529
Gilles Peskine449bd832023-01-11 14:50:10 +01002530 if (verbose != 0) {
2531 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2532 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002533
Gilles Peskine449bd832023-01-11 14:50:10 +01002534 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2535 if (verbose != 0) {
2536 mbedtls_printf("failed\n");
2537 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002538
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002539 ret = 1;
2540 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002541 }
2542
Gilles Peskine449bd832023-01-11 14:50:10 +01002543 if (verbose != 0) {
2544 mbedtls_printf("passed\n");
2545 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002546
Gilles Peskine449bd832023-01-11 14:50:10 +01002547 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &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 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002551
Gilles Peskine449bd832023-01-11 14:50:10 +01002552 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2553 "6613F26162223DF488E9CD48CC132C7A" \
2554 "0AC93C701B001B092E4E5B9F73BCD27B" \
2555 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002556
Gilles Peskine449bd832023-01-11 14:50:10 +01002557 if (verbose != 0) {
2558 mbedtls_printf(" MPI test #2 (div_mpi): ");
2559 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002560
Gilles Peskine449bd832023-01-11 14:50:10 +01002561 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2562 mbedtls_mpi_cmp_mpi(&Y, &V) != 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_exp_mod(&X, &A, &E, &N, NULL));
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 "36E139AEA55215609D2816998ED020BB" \
2579 "BD96C37890F65171D948E9BC7CBAA4D9" \
2580 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002581
Gilles Peskine449bd832023-01-11 14:50:10 +01002582 if (verbose != 0) {
2583 mbedtls_printf(" MPI test #3 (exp_mod): ");
2584 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
Gilles Peskine449bd832023-01-11 14:50:10 +01002586 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2587 if (verbose != 0) {
2588 mbedtls_printf("failed\n");
2589 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002590
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002591 ret = 1;
2592 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002593 }
2594
Gilles Peskine449bd832023-01-11 14:50:10 +01002595 if (verbose != 0) {
2596 mbedtls_printf("passed\n");
2597 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002598
Gilles Peskine449bd832023-01-11 14:50:10 +01002599 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002600
Gilles Peskine449bd832023-01-11 14:50:10 +01002601 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2602 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2603 "C3DBA76456363A10869622EAC2DD84EC" \
2604 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002605
Gilles Peskine449bd832023-01-11 14:50:10 +01002606 if (verbose != 0) {
2607 mbedtls_printf(" MPI test #4 (inv_mod): ");
2608 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002609
Gilles Peskine449bd832023-01-11 14:50:10 +01002610 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2611 if (verbose != 0) {
2612 mbedtls_printf("failed\n");
2613 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002614
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002615 ret = 1;
2616 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002617 }
2618
Gilles Peskine449bd832023-01-11 14:50:10 +01002619 if (verbose != 0) {
2620 mbedtls_printf("passed\n");
2621 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002622
Gilles Peskine449bd832023-01-11 14:50:10 +01002623 if (verbose != 0) {
2624 mbedtls_printf(" MPI test #5 (simple gcd): ");
2625 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002626
Gilles Peskine449bd832023-01-11 14:50:10 +01002627 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2628 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2629 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002630
Gilles Peskine449bd832023-01-11 14:50:10 +01002631 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002632
Gilles Peskine449bd832023-01-11 14:50:10 +01002633 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2634 if (verbose != 0) {
2635 mbedtls_printf("failed at %d\n", i);
2636 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002637
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002638 ret = 1;
2639 goto cleanup;
2640 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002641 }
2642
Gilles Peskine449bd832023-01-11 14:50:10 +01002643 if (verbose != 0) {
2644 mbedtls_printf("passed\n");
2645 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002646
Paul Bakker5121ce52009-01-03 21:22:43 +00002647cleanup:
2648
Gilles Peskine449bd832023-01-11 14:50:10 +01002649 if (ret != 0 && verbose != 0) {
2650 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2651 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002652
Gilles Peskine449bd832023-01-11 14:50:10 +01002653 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2654 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Gilles Peskine449bd832023-01-11 14:50:10 +01002656 if (verbose != 0) {
2657 mbedtls_printf("\n");
2658 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002659
Gilles Peskine449bd832023-01-11 14:50:10 +01002660 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002661}
2662
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002663#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665#endif /* MBEDTLS_BIGNUM_C */