blob: fadd9e9cc2a2a3bd56c68beac71766131b160eb8 [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
Dave Rodgman0f2971a2023-11-03 12:04:52 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker5121ce52009-01-03 21:22:43 +00006 */
Simon Butcher15b15d12015-11-26 19:35:03 +00007
Paul Bakker5121ce52009-01-03 21:22:43 +00008/*
Simon Butcher15b15d12015-11-26 19:35:03 +00009 * The following sources were referenced in the design of this Multi-precision
10 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000011 *
Simon Butcher15b15d12015-11-26 19:35:03 +000012 * [1] Handbook of Applied Cryptography - 1997
13 * Menezes, van Oorschot and Vanstone
14 *
15 * [2] Multi-Precision Math
16 * Tom St Denis
17 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
18 *
19 * [3] GNU Multi-Precision Arithmetic Library
20 * https://gmplib.org/manual/index.html
21 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000022 */
Paul Bakker5121ce52009-01-03 21:22:43 +000023
Gilles Peskinedb09ef62020-06-03 01:43:33 +020024#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000025
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020026#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000027
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000028#include "mbedtls/bignum.h"
29#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Gabor Mezeic0ae1cf2021-10-20 12:09:35 +020032#include "constant_time_internal.h"
Janos Follath1a9a6972024-01-09 09:37:06 +000033#include "bignum_internal.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Tom Cosgrove58efe612021-11-15 09:59:53 +000035#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000036#include <string.h>
37
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000038#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020039
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010040#define MPI_VALIDATE_RET(cond) \
41 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
42#define MPI_VALIDATE(cond) \
43 MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker73d7d792018-12-11 10:35:51 +000044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000046#define biL (ciL << 3) /* bits in limb */
47#define biH (ciL << 2) /* half limb size */
48
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010049#define MPI_SIZE_T_MAX ((size_t) -1) /* SIZE_T_MAX is not standard */
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010050
Paul Bakker5121ce52009-01-03 21:22:43 +000051/*
52 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020053 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000054 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010055#define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0))
56#define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0))
Paul Bakker5121ce52009-01-03 21:22:43 +000057
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050058/* Implementation that should never be optimized out by the compiler */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010059static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050060{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010061 mbedtls_platform_zeroize(v, ciL * n);
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050062}
63
Paul Bakker5121ce52009-01-03 21:22:43 +000064/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000065 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000066 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010067void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000068{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010069 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +000070
Paul Bakker6c591fa2011-05-05 11:49:20 +000071 X->s = 1;
72 X->n = 0;
73 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000074}
75
76/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000077 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000078 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010079void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000080{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010081 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010083 }
Paul Bakker5121ce52009-01-03 21:22:43 +000084
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010085 if (X->p != NULL) {
86 mbedtls_mpi_zeroize(X->p, X->n);
87 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +000088 }
89
Paul Bakker6c591fa2011-05-05 11:49:20 +000090 X->s = 1;
91 X->n = 0;
92 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000093}
94
95/*
96 * Enlarge to the specified number of limbs
97 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010098int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +000099{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 mbedtls_mpi_uint *p;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100101 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000102
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100103 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
104 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
105 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000106
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100107 if (X->n < nblimbs) {
108 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
109 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
110 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000111
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100112 if (X->p != NULL) {
113 memcpy(p, X->p, X->n * ciL);
114 mbedtls_mpi_zeroize(X->p, X->n);
115 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000116 }
117
118 X->n = nblimbs;
119 X->p = p;
120 }
121
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100122 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000123}
124
125/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100126 * Resize down as much as possible,
127 * while keeping at least the specified number of limbs
128 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100129int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100130{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100132 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100133 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000134
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100135 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
136 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
137 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100138
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100139 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100140 if (X->n <= nblimbs) {
141 return mbedtls_mpi_grow(X, nblimbs);
142 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100143 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100144
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100145 for (i = X->n - 1; i > 0; i--) {
146 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100148 }
149 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150 i++;
151
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100152 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100153 i = nblimbs;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100154 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100156 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
157 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
158 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100160 if (X->p != NULL) {
161 memcpy(p, X->p, i * ciL);
162 mbedtls_mpi_zeroize(X->p, X->n);
163 mbedtls_free(X->p);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 }
165
166 X->n = i;
167 X->p = p;
168
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100169 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170}
171
Gilles Peskine3130ce22021-06-02 22:17:52 +0200172/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100173static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskine3130ce22021-06-02 22:17:52 +0200174{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100175 if (limbs == 0) {
176 mbedtls_mpi_free(X);
177 return 0;
178 } else if (X->n == limbs) {
179 memset(X->p, 0, limbs * ciL);
Gilles Peskine3130ce22021-06-02 22:17:52 +0200180 X->s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100181 return 0;
182 } else {
183 mbedtls_mpi_free(X);
184 return mbedtls_mpi_grow(X, limbs);
Gilles Peskine3130ce22021-06-02 22:17:52 +0200185 }
186}
187
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100188/*
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200189 * Copy the contents of Y into X.
190 *
191 * This function is not constant-time. Leading zeros in Y may be removed.
192 *
193 * Ensure that X does not shrink. This is not guaranteed by the public API,
194 * but some code in the bignum module relies on this property, for example
195 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000196 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100197int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000198{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100199 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000200 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100201 MPI_VALIDATE_RET(X != NULL);
202 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000203
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100204 if (X == Y) {
205 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200206 }
207
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100208 if (Y->n == 0) {
209 if (X->n != 0) {
210 X->s = 1;
211 memset(X->p, 0, X->n * ciL);
212 }
213 return 0;
214 }
215
216 for (i = Y->n - 1; i > 0; i--) {
217 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000218 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 }
220 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000221 i++;
222
223 X->s = Y->s;
224
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100225 if (X->n < i) {
226 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
227 } else {
228 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100229 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000230
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100231 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000232
233cleanup:
234
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100235 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000236}
237
238/*
239 * Swap the contents of X and Y
240 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100241void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000242{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200243 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100244 MPI_VALIDATE(X != NULL);
245 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000246
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100247 memcpy(&T, X, sizeof(mbedtls_mpi));
248 memcpy(X, Y, sizeof(mbedtls_mpi));
249 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000250}
251
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100252static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100253{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100254 if (z >= 0) {
255 return z;
256 }
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100257 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
258 * A naive -z would have undefined behavior.
259 * Write this in a way that makes popular compilers happy (GCC, Clang,
260 * MSVC). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100261 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100262}
263
Paul Bakker5121ce52009-01-03 21:22:43 +0000264/*
265 * Set value from integer
266 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100267int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000268{
Janos Follath24eed8d2019-11-22 13:21:35 +0000269 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100270 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000271
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
273 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000274
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100275 X->p[0] = mpi_sint_abs(z);
276 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000277
278cleanup:
279
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100280 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000281}
282
283/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000284 * Get a specific bit
285 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100286int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000287{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100288 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000289
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100290 if (X->n * biL <= pos) {
291 return 0;
292 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000293
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100294 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000295}
296
Gilles Peskine11cdb052018-11-20 16:47:47 +0100297/* Get a specific byte, without range checks. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100298#define GET_BYTE(X, i) \
299 (((X)->p[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)
Gilles Peskine11cdb052018-11-20 16:47:47 +0100300
Paul Bakker2f5947e2011-05-18 15:47:11 +0000301/*
302 * Set a bit to a specific value of 0 or 1
303 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100304int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000305{
306 int ret = 0;
307 size_t off = pos / biL;
308 size_t idx = pos % biL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000310
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100311 if (val != 0 && val != 1) {
312 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000313 }
314
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100315 if (X->n * biL <= pos) {
316 if (val == 0) {
317 return 0;
318 }
319
320 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
321 }
322
323 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325
326cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200327
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100328 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000329}
330
331/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200332 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000333 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100334size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000335{
Paul Bakker23986e52011-04-24 08:57:21 +0000336 size_t i, j, count = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100337 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000338
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100339 for (i = 0; i < X->n; i++) {
340 for (j = 0; j < biL; j++, count++) {
341 if (((X->p[i] >> j) & 1) != 0) {
342 return count;
343 }
344 }
345 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000346
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100347 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000348}
349
350/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000351 * Count leading zero bits in a given integer
352 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100353static size_t mbedtls_clz(const mbedtls_mpi_uint x)
Simon Butcher15b15d12015-11-26 19:35:03 +0000354{
355 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100356 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000357
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100358 for (j = 0; j < biL; j++) {
359 if (x & mask) {
360 break;
361 }
Simon Butcher15b15d12015-11-26 19:35:03 +0000362
363 mask >>= 1;
364 }
365
366 return j;
367}
368
369/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200370 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000371 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100372size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000373{
Paul Bakker23986e52011-04-24 08:57:21 +0000374 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000375
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100376 if (X->n == 0) {
377 return 0;
378 }
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200379
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100380 for (i = X->n - 1; i > 0; i--) {
381 if (X->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000382 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100383 }
384 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000385
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100386 j = biL - mbedtls_clz(X->p[i]);
Paul Bakker5121ce52009-01-03 21:22:43 +0000387
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100388 return (i * biL) + j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000389}
390
391/*
392 * Return the total size in bytes
393 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100394size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000395{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100396 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000397}
398
399/*
400 * Convert an ASCII character to digit value
401 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100402static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000403{
404 *d = 255;
405
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100406 if (c >= 0x30 && c <= 0x39) {
407 *d = c - 0x30;
408 }
409 if (c >= 0x41 && c <= 0x46) {
410 *d = c - 0x37;
411 }
412 if (c >= 0x61 && c <= 0x66) {
413 *d = c - 0x57;
414 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000415
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100416 if (*d >= (mbedtls_mpi_uint) radix) {
417 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
418 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000419
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100420 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000421}
422
423/*
424 * Import from an ASCII string
425 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100426int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000427{
Janos Follath24eed8d2019-11-22 13:21:35 +0000428 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000429 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200430 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 mbedtls_mpi_uint d;
432 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100433 MPI_VALIDATE_RET(X != NULL);
434 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100436 if (radix < 2 || radix > 16) {
437 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskined4876132021-06-08 18:32:34 +0200438 }
439
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100440 mbedtls_mpi_init(&T);
441
442 if (s[0] == 0) {
443 mbedtls_mpi_free(X);
444 return 0;
445 }
446
447 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200448 ++s;
449 sign = -1;
450 }
451
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100452 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000453
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100454 if (radix == 16) {
455 if (slen > MPI_SIZE_T_MAX >> 2) {
456 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000457 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100459 n = BITS_TO_LIMBS(slen << 2);
460
461 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
462 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
463
464 for (i = slen, j = 0; i > 0; i--, j++) {
465 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
466 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
467 }
468 } else {
469 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
470
471 for (i = 0; i < slen; i++) {
472 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
473 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
474 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000475 }
476 }
477
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100478 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200479 X->s = -1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100480 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200481
Paul Bakker5121ce52009-01-03 21:22:43 +0000482cleanup:
483
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100484 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100486 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000487}
488
489/*
Ron Eldora16fa292018-11-20 14:07:01 +0200490 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000491 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100492static int mpi_write_hlp(mbedtls_mpi *X, int radix,
493 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000494{
Janos Follath24eed8d2019-11-22 13:21:35 +0000495 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200497 size_t length = 0;
498 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100500 do {
501 if (length >= buflen) {
502 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200503 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000504
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100505 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
506 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200507 /*
508 * Write the residue in the current position, as an ASCII character.
509 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100510 if (r < 0xA) {
511 *(--p_end) = (char) ('0' + r);
512 } else {
513 *(--p_end) = (char) ('A' + (r - 0xA));
514 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000515
Ron Eldora16fa292018-11-20 14:07:01 +0200516 length++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100517 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000518
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100519 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200520 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000521
522cleanup:
523
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100524 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000525}
526
527/*
528 * Export into an ASCII string
529 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100530int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
531 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000532{
Paul Bakker23986e52011-04-24 08:57:21 +0000533 int ret = 0;
534 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000535 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100537 MPI_VALIDATE_RET(X != NULL);
538 MPI_VALIDATE_RET(olen != NULL);
539 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000540
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100541 if (radix < 2 || radix > 16) {
542 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
543 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000544
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100545 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
546 if (radix >= 4) {
547 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000548 * `n`. If radix > 4, this might be a strict
549 * overapproximation of the number of
550 * radix-adic digits needed to present `n`. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100551 }
552 if (radix >= 16) {
553 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000554 * present `n`. */
555
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100556 }
Janos Follath80470622019-03-06 13:43:02 +0000557 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000558 n += 1; /* Compensate for the divisions above, which round down `n`
559 * in case it's not even. */
560 n += 1; /* Potential '-'-sign. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100561 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000562 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100564 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100565 *olen = n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100566 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 }
568
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100569 p = buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100570 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000571
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100572 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000573 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000574 buflen--;
575 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000576
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100577 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000578 int c;
579 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000580
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100581 for (i = X->n, k = 0; i > 0; i--) {
582 for (j = ciL; j > 0; j--) {
583 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100585 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000586 continue;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100587 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000588
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000589 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000590 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000591 k = 1;
592 }
593 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100594 } else {
595 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000596
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100597 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000598 T.s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100599 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000600
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100601 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000602 }
603
604 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100605 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000606
607cleanup:
608
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100609 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100611 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000612}
613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000615/*
616 * Read X from an opened file
617 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100618int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000619{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000621 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000622 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000623 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000624 * Buffer should have space for (short) label and decimal formatted MPI,
625 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000626 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100627 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000628
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100629 MPI_VALIDATE_RET(X != NULL);
630 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000631
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100632 if (radix < 2 || radix > 16) {
633 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
634 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000635
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100636 memset(s, 0, sizeof(s));
637 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
638 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
639 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000640
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100641 slen = strlen(s);
642 if (slen == sizeof(s) - 2) {
643 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
644 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000645
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100646 if (slen > 0 && s[slen - 1] == '\n') {
647 slen--; s[slen] = '\0';
648 }
649 if (slen > 0 && s[slen - 1] == '\r') {
650 slen--; s[slen] = '\0';
651 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
653 p = s + slen;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100654 while (p-- > s) {
655 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000656 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100657 }
658 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100660 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000661}
662
663/*
664 * Write X into an opened file (or stdout if fout == NULL)
665 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100666int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000667{
Janos Follath24eed8d2019-11-22 13:21:35 +0000668 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000669 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000670 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000671 * Buffer should have space for (short) label and decimal formatted MPI,
672 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000673 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100674 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
675 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000676
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100677 if (radix < 2 || radix > 16) {
678 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
679 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100681 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000682
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100683 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000684
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100685 if (p == NULL) {
686 p = "";
687 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000688
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100689 plen = strlen(p);
690 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000691 s[slen++] = '\r';
692 s[slen++] = '\n';
693
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100694 if (fout != NULL) {
695 if (fwrite(p, 1, plen, fout) != plen ||
696 fwrite(s, 1, slen, fout) != slen) {
697 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
698 }
699 } else {
700 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000701 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
703cleanup:
704
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100705 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000706}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
Hanno Beckerda1655a2017-10-18 14:21:44 +0100709
710/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
711 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000712
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100713static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000714{
715 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100716 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000717 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100718
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100719 for (i = 0, x_ptr = (unsigned char *) &x; i < ciL; i++, x_ptr++) {
Hanno Becker031d6332019-05-01 17:09:11 +0100720 tmp <<= CHAR_BIT;
721 tmp |= (mbedtls_mpi_uint) *x_ptr;
722 }
723
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100724 return tmp;
Hanno Beckerf8720072018-11-08 11:53:49 +0000725}
726
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100727static mbedtls_mpi_uint mpi_uint_bigendian_to_host(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000728{
729#if defined(__BYTE_ORDER__)
730
731/* Nothing to do on bigendian systems. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100732#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
733 return x;
Hanno Beckerf8720072018-11-08 11:53:49 +0000734#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
735
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100736#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
Hanno Beckerf8720072018-11-08 11:53:49 +0000737
738/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000739#if defined(__GNUC__) && defined(__GNUC_PREREQ)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100740#if __GNUC_PREREQ(4, 3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000741#define have_bswap
742#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000743#endif
744
745#if defined(__clang__) && defined(__has_builtin)
746#if __has_builtin(__builtin_bswap32) && \
747 __has_builtin(__builtin_bswap64)
748#define have_bswap
749#endif
750#endif
751
Hanno Beckerf8720072018-11-08 11:53:49 +0000752#if defined(have_bswap)
753 /* The compiler is hopefully able to statically evaluate this! */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100754 switch (sizeof(mbedtls_mpi_uint)) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000755 case 4:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100756 return __builtin_bswap32(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000757 case 8:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100758 return __builtin_bswap64(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000759 }
760#endif
761#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
762#endif /* __BYTE_ORDER__ */
763
764 /* Fall back to C-based reordering if we don't know the byte order
765 * or we couldn't use a compiler-specific builtin. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100766 return mpi_uint_bigendian_to_host_c(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000767}
768
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100769static void mpi_bigendian_to_host(mbedtls_mpi_uint * const p, size_t limbs)
Hanno Beckerda1655a2017-10-18 14:21:44 +0100770{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100771 mbedtls_mpi_uint *cur_limb_left;
772 mbedtls_mpi_uint *cur_limb_right;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100773 if (limbs == 0) {
Hanno Becker2be8a552018-10-25 12:40:09 +0100774 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100775 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100776
777 /*
778 * Traverse limbs and
779 * - adapt byte-order in each limb
780 * - swap the limbs themselves.
781 * For that, simultaneously traverse the limbs from left to right
782 * and from right to left, as long as the left index is not bigger
783 * than the right index (it's not a problem if limbs is odd and the
784 * indices coincide in the last iteration).
785 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100786 for (cur_limb_left = p, cur_limb_right = p + (limbs - 1);
Hanno Beckerda1655a2017-10-18 14:21:44 +0100787 cur_limb_left <= cur_limb_right;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100788 cur_limb_left++, cur_limb_right--) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000789 mbedtls_mpi_uint tmp;
790 /* Note that if cur_limb_left == cur_limb_right,
791 * this code effectively swaps the bytes only once. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100792 tmp = mpi_uint_bigendian_to_host(*cur_limb_left);
793 *cur_limb_left = mpi_uint_bigendian_to_host(*cur_limb_right);
Hanno Beckerf8720072018-11-08 11:53:49 +0000794 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100795 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100796}
797
Paul Bakker5121ce52009-01-03 21:22:43 +0000798/*
Janos Follatha778a942019-02-13 10:28:28 +0000799 * Import X from unsigned binary data, little endian
800 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100801int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
802 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000803{
Janos Follath24eed8d2019-11-22 13:21:35 +0000804 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000805 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100806 size_t const limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000807
808 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100809 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000810
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100811 for (i = 0; i < buflen; i++) {
Janos Follatha778a942019-02-13 10:28:28 +0000812 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100813 }
Janos Follatha778a942019-02-13 10:28:28 +0000814
815cleanup:
816
Janos Follath171a7ef2019-02-15 16:17:45 +0000817 /*
818 * This function is also used to import keys. However, wiping the buffers
819 * upon failure is not necessary because failure only can happen before any
820 * input is copied.
821 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100822 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000823}
824
825/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000826 * Import X from unsigned binary data, big endian
827 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100828int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000829{
Janos Follath24eed8d2019-11-22 13:21:35 +0000830 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100831 size_t const limbs = CHARS_TO_LIMBS(buflen);
832 size_t const overhead = (limbs * ciL) - buflen;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100833 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000834
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100835 MPI_VALIDATE_RET(X != NULL);
836 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000837
Hanno Becker073c1992017-10-17 15:17:27 +0100838 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100839 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000840
Gilles Peskine3130ce22021-06-02 22:17:52 +0200841 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000842 * even if buflen is 0. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100843 if (buflen != 0) {
844 Xp = (unsigned char *) X->p;
845 memcpy(Xp + overhead, buf, buflen);
Hanno Beckerda1655a2017-10-18 14:21:44 +0100846
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100847 mpi_bigendian_to_host(X->p, limbs);
Hanno Becker0e810b92019-01-03 17:13:11 +0000848 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000849
850cleanup:
851
Janos Follath171a7ef2019-02-15 16:17:45 +0000852 /*
853 * This function is also used to import keys. However, wiping the buffers
854 * upon failure is not necessary because failure only can happen before any
855 * input is copied.
856 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100857 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000858}
859
860/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000861 * Export X into unsigned binary data, little endian
862 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100863int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
864 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000865{
866 size_t stored_bytes = X->n * ciL;
867 size_t bytes_to_copy;
868 size_t i;
869
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100870 if (stored_bytes < buflen) {
Janos Follathe344d0f2019-02-19 16:17:40 +0000871 bytes_to_copy = stored_bytes;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100872 } else {
Janos Follathe344d0f2019-02-19 16:17:40 +0000873 bytes_to_copy = buflen;
874
875 /* The output buffer is smaller than the allocated size of X.
876 * However X may fit if its leading bytes are zero. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100877 for (i = bytes_to_copy; i < stored_bytes; i++) {
878 if (GET_BYTE(X, i) != 0) {
879 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
880 }
Janos Follathe344d0f2019-02-19 16:17:40 +0000881 }
882 }
883
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100884 for (i = 0; i < bytes_to_copy; i++) {
885 buf[i] = GET_BYTE(X, i);
Janos Follathe344d0f2019-02-19 16:17:40 +0000886 }
887
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100888 if (stored_bytes < buflen) {
889 /* Write trailing 0 bytes */
890 memset(buf + stored_bytes, 0, buflen - stored_bytes);
891 }
892
893 return 0;
Janos Follathe344d0f2019-02-19 16:17:40 +0000894}
895
896/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 * Export X into unsigned binary data, big endian
898 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100899int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
900 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000901{
Hanno Becker73d7d792018-12-11 10:35:51 +0000902 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100903 size_t bytes_to_copy;
904 unsigned char *p;
905 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100907 MPI_VALIDATE_RET(X != NULL);
908 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000909
910 stored_bytes = X->n * ciL;
911
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100912 if (stored_bytes < buflen) {
Gilles Peskine11cdb052018-11-20 16:47:47 +0100913 /* There is enough space in the output buffer. Write initial
914 * null bytes and record the position at which to start
915 * writing the significant bytes. In this case, the execution
916 * trace of this function does not depend on the value of the
917 * number. */
918 bytes_to_copy = stored_bytes;
919 p = buf + buflen - stored_bytes;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100920 memset(buf, 0, buflen - stored_bytes);
921 } else {
Gilles Peskine11cdb052018-11-20 16:47:47 +0100922 /* The output buffer is smaller than the allocated size of X.
923 * However X may fit if its leading bytes are zero. */
924 bytes_to_copy = buflen;
925 p = buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100926 for (i = bytes_to_copy; i < stored_bytes; i++) {
927 if (GET_BYTE(X, i) != 0) {
928 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
929 }
Gilles Peskine11cdb052018-11-20 16:47:47 +0100930 }
931 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000932
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100933 for (i = 0; i < bytes_to_copy; i++) {
934 p[bytes_to_copy - i - 1] = GET_BYTE(X, i);
935 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000936
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100937 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000938}
939
940/*
941 * Left-shift: X <<= count
942 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100943int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000944{
Janos Follath24eed8d2019-11-22 13:21:35 +0000945 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000946 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 mbedtls_mpi_uint r0 = 0, r1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100948 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000949
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100950 v0 = count / (biL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000951 t1 = count & (biL - 1);
952
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100953 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000954
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100955 if (X->n * biL < i) {
956 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
957 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000958
959 ret = 0;
960
961 /*
962 * shift by count / limb_size
963 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100964 if (v0 > 0) {
965 for (i = X->n; i > v0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +0000966 X->p[i - 1] = X->p[i - v0 - 1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100967 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000968
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100969 for (; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +0000970 X->p[i - 1] = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100971 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000972 }
973
974 /*
975 * shift by count % limb_size
976 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100977 if (t1 > 0) {
978 for (i = v0; i < X->n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 r1 = X->p[i] >> (biL - t1);
980 X->p[i] <<= t1;
981 X->p[i] |= r0;
982 r0 = r1;
983 }
984 }
985
986cleanup:
987
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100988 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000989}
990
991/*
992 * Right-shift: X >>= count
993 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100994int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000995{
Paul Bakker23986e52011-04-24 08:57:21 +0000996 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 mbedtls_mpi_uint r0 = 0, r1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100998 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000999
1000 v0 = count / biL;
1001 v1 = count & (biL - 1);
1002
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001003 if (v0 > X->n || (v0 == X->n && v1 > 0)) {
1004 return mbedtls_mpi_lset(X, 0);
1005 }
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001006
Paul Bakker5121ce52009-01-03 21:22:43 +00001007 /*
1008 * shift by count / limb_size
1009 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001010 if (v0 > 0) {
1011 for (i = 0; i < X->n - v0; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 X->p[i] = X->p[i + v0];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001013 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001014
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001015 for (; i < X->n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 X->p[i] = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001017 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 }
1019
1020 /*
1021 * shift by count % limb_size
1022 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001023 if (v1 > 0) {
1024 for (i = X->n; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001025 r1 = X->p[i - 1] << (biL - v1);
1026 X->p[i - 1] >>= v1;
1027 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001028 r0 = r1;
1029 }
1030 }
1031
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001032 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001033}
1034
1035/*
1036 * Compare unsigned values
1037 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001038int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001039{
Paul Bakker23986e52011-04-24 08:57:21 +00001040 size_t i, j;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001041 MPI_VALIDATE_RET(X != NULL);
1042 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001043
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001044 for (i = X->n; i > 0; i--) {
1045 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001046 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001047 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001048 }
1049
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001050 for (j = Y->n; j > 0; j--) {
1051 if (Y->p[j - 1] != 0) {
1052 break;
1053 }
1054 }
1055
1056 if (i == 0 && j == 0) {
1057 return 0;
1058 }
1059
1060 if (i > j) {
1061 return 1;
1062 }
1063 if (j > i) {
1064 return -1;
1065 }
1066
1067 for (; i > 0; i--) {
1068 if (X->p[i - 1] > Y->p[i - 1]) {
1069 return 1;
1070 }
1071 if (X->p[i - 1] < Y->p[i - 1]) {
1072 return -1;
1073 }
1074 }
1075
1076 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001077}
1078
1079/*
1080 * Compare signed values
1081 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001082int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001083{
Paul Bakker23986e52011-04-24 08:57:21 +00001084 size_t i, j;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001085 MPI_VALIDATE_RET(X != NULL);
1086 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001087
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001088 for (i = X->n; i > 0; i--) {
1089 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001090 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001091 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001092 }
1093
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001094 for (j = Y->n; j > 0; j--) {
1095 if (Y->p[j - 1] != 0) {
1096 break;
1097 }
1098 }
1099
1100 if (i == 0 && j == 0) {
1101 return 0;
1102 }
1103
1104 if (i > j) {
1105 return X->s;
1106 }
1107 if (j > i) {
1108 return -Y->s;
1109 }
1110
1111 if (X->s > 0 && Y->s < 0) {
1112 return 1;
1113 }
1114 if (Y->s > 0 && X->s < 0) {
1115 return -1;
1116 }
1117
1118 for (; i > 0; i--) {
1119 if (X->p[i - 1] > Y->p[i - 1]) {
1120 return X->s;
1121 }
1122 if (X->p[i - 1] < Y->p[i - 1]) {
1123 return -X->s;
1124 }
1125 }
1126
1127 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001128}
1129
Janos Follathee6abce2019-09-05 14:47:19 +01001130/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001131 * Compare signed values
1132 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001133int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +00001134{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001135 mbedtls_mpi Y;
1136 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001137 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001138
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001139 *p = mpi_sint_abs(z);
1140 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001141 Y.n = 1;
1142 Y.p = p;
1143
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001144 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00001145}
1146
1147/*
1148 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1149 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001150int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001151{
Janos Follath24eed8d2019-11-22 13:21:35 +00001152 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001153 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001154 mbedtls_mpi_uint *o, *p, c, tmp;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001155 MPI_VALIDATE_RET(X != NULL);
1156 MPI_VALIDATE_RET(A != NULL);
1157 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001158
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001159 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 }
1162
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001163 if (X != A) {
1164 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1165 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001166
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001167 /*
1168 * X should always be positive as a result of unsigned additions.
1169 */
1170 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001171
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001172 for (j = B->n; j > 0; j--) {
1173 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001174 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001175 }
1176 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001177
Gilles Peskine103cf592022-11-15 22:59:00 +01001178 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1179 * and B is 0 (of any size). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001180 if (j == 0) {
1181 return 0;
1182 }
Gilles Peskine103cf592022-11-15 22:59:00 +01001183
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001184 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
1186 o = B->p; p = X->p; c = 0;
1187
Janos Follath6c922682015-10-30 17:43:11 +01001188 /*
1189 * tmp is used because it might happen that p == o
1190 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001191 for (i = 0; i < j; i++, o++, p++) {
1192 tmp = *o;
1193 *p += c; c = (*p < c);
1194 *p += tmp; c += (*p < tmp);
Paul Bakker5121ce52009-01-03 21:22:43 +00001195 }
1196
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001197 while (c != 0) {
1198 if (i >= X->n) {
1199 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001200 p = X->p + i;
1201 }
1202
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001203 *p += c; c = (*p < c); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001204 }
1205
1206cleanup:
1207
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001208 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001209}
1210
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001211/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001212 * Helper for mbedtls_mpi subtraction.
1213 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001214 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001215 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001216 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001217 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001218 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001219 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001220 * \param n Number of limbs of \p d, \p l and \p r.
1221 * \param[out] d The result of the subtraction.
1222 * \param[in] l The left operand.
1223 * \param[in] r The right operand.
1224 *
1225 * \return 1 if `l < r`.
1226 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001227 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001228static mbedtls_mpi_uint mpi_sub_hlp(size_t n,
1229 mbedtls_mpi_uint *d,
1230 const mbedtls_mpi_uint *l,
1231 const mbedtls_mpi_uint *r)
Paul Bakker5121ce52009-01-03 21:22:43 +00001232{
Paul Bakker23986e52011-04-24 08:57:21 +00001233 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001234 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001235
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001236 for (i = 0; i < n; i++) {
1237 z = (l[i] < c); t = l[i] - c;
1238 c = (t < r[i]) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001239 }
1240
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001241 return c;
Paul Bakker5121ce52009-01-03 21:22:43 +00001242}
1243
1244/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001245 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001246 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001247int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001248{
Janos Follath24eed8d2019-11-22 13:21:35 +00001249 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001250 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001251 mbedtls_mpi_uint carry;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001252 MPI_VALIDATE_RET(X != NULL);
1253 MPI_VALIDATE_RET(A != NULL);
1254 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001255
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001256 for (n = B->n; n > 0; n--) {
1257 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001258 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001259 }
1260 }
1261 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001262 /* B >= (2^ciL)^n > A */
1263 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1264 goto cleanup;
1265 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001267 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001268
1269 /* Set the high limbs of X to match A. Don't touch the lower limbs
1270 * because X might be aliased to B, and we must not overwrite the
1271 * significant digits of B. */
Aaron M. Ucko78b823a2023-01-31 15:45:44 -05001272 if (A->n > n && A != X) {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001273 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1274 }
1275 if (X->n > A->n) {
1276 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1277 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001278
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001279 carry = mpi_sub_hlp(n, X->p, A->p, B->p);
1280 if (carry != 0) {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001281 /* Propagate the carry to the first nonzero limb of X. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001282 for (; n < X->n && X->p[n] == 0; n++) {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001283 --X->p[n];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001284 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001285 /* If we ran out of space for the carry, it means that the result
1286 * is negative. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001287 if (n == X->n) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001288 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1289 goto cleanup;
1290 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001291 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001292 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001293
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001294 /* X should always be positive as a result of unsigned subtractions. */
1295 X->s = 1;
1296
Paul Bakker5121ce52009-01-03 21:22:43 +00001297cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001298 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001299}
1300
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001301/* Common function for signed addition and subtraction.
1302 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001303 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001304static int add_sub_mpi(mbedtls_mpi *X,
1305 const mbedtls_mpi *A, const mbedtls_mpi *B,
1306 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001307{
Hanno Becker73d7d792018-12-11 10:35:51 +00001308 int ret, s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001309 MPI_VALIDATE_RET(X != NULL);
1310 MPI_VALIDATE_RET(A != NULL);
1311 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001312
Hanno Becker73d7d792018-12-11 10:35:51 +00001313 s = A->s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001314 if (A->s * B->s * flip_B < 0) {
1315 int cmp = mbedtls_mpi_cmp_abs(A, B);
1316 if (cmp >= 0) {
1317 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine581c4602022-11-09 22:02:16 +01001318 /* If |A| = |B|, the result is 0 and we must set the sign bit
1319 * to +1 regardless of which of A or B was negative. Otherwise,
1320 * since |A| > |B|, the sign is the sign of A. */
1321 X->s = cmp == 0 ? 1 : s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001322 } else {
1323 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine581c4602022-11-09 22:02:16 +01001324 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 X->s = -s;
1326 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001327 } else {
1328 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001329 X->s = s;
1330 }
1331
1332cleanup:
1333
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001334 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001335}
1336
1337/*
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001338 * Signed addition: X = A + B
1339 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001340int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001341{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001342 return add_sub_mpi(X, A, B, 1);
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001343}
1344
1345/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001346 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001348int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001349{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001350 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001351}
1352
1353/*
1354 * Signed addition: X = A + b
1355 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001356int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001357{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001358 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001360 MPI_VALIDATE_RET(X != NULL);
1361 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001363 p[0] = mpi_sint_abs(b);
1364 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001365 B.n = 1;
1366 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001367
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001368 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001369}
1370
1371/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001372 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001374int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001375{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001376 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001378 MPI_VALIDATE_RET(X != NULL);
1379 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001381 p[0] = mpi_sint_abs(b);
1382 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001383 B.n = 1;
1384 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001385
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001386 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001387}
1388
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001389/** Helper for mbedtls_mpi multiplication.
1390 *
1391 * Add \p b * \p s to \p d.
1392 *
1393 * \param i The number of limbs of \p s.
1394 * \param[in] s A bignum to multiply, of size \p i.
1395 * It may overlap with \p d, but only if
1396 * \p d <= \p s.
1397 * Its leading limb must not be \c 0.
1398 * \param[in,out] d The bignum to add to.
1399 * It must be sufficiently large to store the
1400 * result of the multiplication. This means
1401 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1402 * is not known a priori.
1403 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001404 */
1405static
1406#if defined(__APPLE__) && defined(__arm__)
1407/*
1408 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1409 * appears to need this to prevent bad ARM code generation at -O3.
1410 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001411__attribute__((noinline))
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001412#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001413void mpi_mul_hlp(size_t i,
1414 const mbedtls_mpi_uint *s,
1415 mbedtls_mpi_uint *d,
1416 mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001417{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 mbedtls_mpi_uint c = 0, t = 0;
Gilles Peskined7848332023-02-24 12:08:01 +01001419 (void) t; /* Unused in some architectures */
Paul Bakker5121ce52009-01-03 21:22:43 +00001420
1421#if defined(MULADDC_HUIT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001422 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001423 MULADDC_INIT
1424 MULADDC_HUIT
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001425 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 }
1427
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001428 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001429 MULADDC_INIT
1430 MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001431 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001432 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001433#else /* MULADDC_HUIT */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001434 for (; i >= 16; i -= 16) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001435 MULADDC_INIT
1436 MULADDC_CORE MULADDC_CORE
1437 MULADDC_CORE MULADDC_CORE
1438 MULADDC_CORE MULADDC_CORE
1439 MULADDC_CORE MULADDC_CORE
1440
1441 MULADDC_CORE MULADDC_CORE
1442 MULADDC_CORE MULADDC_CORE
1443 MULADDC_CORE MULADDC_CORE
1444 MULADDC_CORE MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001445 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001446 }
1447
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001448 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001449 MULADDC_INIT
1450 MULADDC_CORE MULADDC_CORE
1451 MULADDC_CORE MULADDC_CORE
1452
1453 MULADDC_CORE MULADDC_CORE
1454 MULADDC_CORE MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001455 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001456 }
1457
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001458 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001459 MULADDC_INIT
1460 MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001461 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001462 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001463#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001464
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001465 while (c != 0) {
1466 *d += c; c = (*d < c); d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001467 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001468}
1469
1470/*
1471 * Baseline multiplication: X = A * B (HAC 14.12)
1472 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001473int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001474{
Janos Follath24eed8d2019-11-22 13:21:35 +00001475 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001476 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 mbedtls_mpi TA, TB;
Gilles Peskined65b5002021-06-15 21:44:32 +02001478 int result_is_zero = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001479 MPI_VALIDATE_RET(X != NULL);
1480 MPI_VALIDATE_RET(A != NULL);
1481 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001483 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001485 if (X == A) {
1486 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1487 }
1488 if (X == B) {
1489 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1490 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001491
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001492 for (i = A->n; i > 0; i--) {
1493 if (A->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001494 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001495 }
1496 }
1497 if (i == 0) {
Gilles Peskined65b5002021-06-15 21:44:32 +02001498 result_is_zero = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001499 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001500
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001501 for (j = B->n; j > 0; j--) {
1502 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001503 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001504 }
1505 }
1506 if (j == 0) {
Gilles Peskined65b5002021-06-15 21:44:32 +02001507 result_is_zero = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001508 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001509
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001510 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1511 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001513 for (; j > 0; j--) {
1514 mpi_mul_hlp(i, A->p, X->p + j - 1, B->p[j - 1]);
1515 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001517 /* If the result is 0, we don't shortcut the operation, which reduces
1518 * but does not eliminate side channels leaking the zero-ness. We do
1519 * need to take care to set the sign bit properly since the library does
1520 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001521 if (result_is_zero) {
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001522 X->s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001523 } else {
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001524 X->s = A->s * B->s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001525 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
1527cleanup:
1528
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001529 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001530
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001531 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001532}
1533
1534/*
1535 * Baseline multiplication: X = A * b
1536 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001537int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001538{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001539 MPI_VALIDATE_RET(X != NULL);
1540 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001542 /* mpi_mul_hlp can't deal with a leading 0. */
1543 size_t n = A->n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001544 while (n > 0 && A->p[n - 1] == 0) {
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001545 --n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001546 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001548 /* The general method below doesn't work if n==0 or b==0. By chance
1549 * calculating the result is trivial in those cases. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001550 if (b == 0 || n == 0) {
1551 return mbedtls_mpi_lset(X, 0);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001552 }
1553
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001554 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001555 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001556 /* In general, A * b requires 1 limb more than b. If
1557 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1558 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001559 * copy() will take care of the growth if needed. However, experimentally,
1560 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001561 * calls to calloc() in ECP code, presumably because it reuses the
1562 * same mpi for a while and this way the mpi is more likely to directly
1563 * grow to its final size. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001564 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1565 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1566 mpi_mul_hlp(n, A->p, X->p, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001567
1568cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001569 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001570}
1571
1572/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001573 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1574 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001575 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001576static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1577 mbedtls_mpi_uint u0,
1578 mbedtls_mpi_uint d,
1579 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001580{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001581#if defined(MBEDTLS_HAVE_UDBL)
1582 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001583#else
Simon Butcher9803d072016-01-03 00:24:34 +00001584 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001585 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001586 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1587 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001588 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001589#endif
1590
Simon Butcher15b15d12015-11-26 19:35:03 +00001591 /*
1592 * Check for overflow
1593 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001594 if (0 == d || u1 >= d) {
1595 if (r != NULL) {
1596 *r = ~(mbedtls_mpi_uint) 0u;
1597 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001598
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001599 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001600 }
1601
1602#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001603 dividend = (mbedtls_t_udbl) u1 << biL;
1604 dividend |= (mbedtls_t_udbl) u0;
1605 quotient = dividend / d;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001606 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1607 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1608 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001609
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001610 if (r != NULL) {
1611 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1612 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001613
1614 return (mbedtls_mpi_uint) quotient;
1615#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001616
1617 /*
1618 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1619 * Vol. 2 - Seminumerical Algorithms, Knuth
1620 */
1621
1622 /*
1623 * Normalize the divisor, d, and dividend, u0, u1
1624 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001625 s = mbedtls_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001626 d = d << s;
1627
1628 u1 = u1 << s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001629 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001630 u0 = u0 << s;
1631
1632 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001633 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001634
1635 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001636 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001637
1638 /*
1639 * Find the first quotient and remainder
1640 */
1641 q1 = u1 / d1;
1642 r0 = u1 - d1 * q1;
1643
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001644 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001645 q1 -= 1;
1646 r0 += d1;
1647
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001648 if (r0 >= radix) {
1649 break;
1650 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001651 }
1652
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001653 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001654 q0 = rAX / d1;
1655 r0 = rAX - q0 * d1;
1656
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001657 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001658 q0 -= 1;
1659 r0 += d1;
1660
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001661 if (r0 >= radix) {
1662 break;
1663 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001664 }
1665
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001666 if (r != NULL) {
1667 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1668 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001669
1670 quotient = q1 * radix + q0;
1671
1672 return quotient;
1673#endif
1674}
1675
1676/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001679int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1680 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001681{
Janos Follath24eed8d2019-11-22 13:21:35 +00001682 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001683 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001685 mbedtls_mpi_uint TP2[3];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001686 MPI_VALIDATE_RET(A != NULL);
1687 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001688
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001689 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1690 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1691 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001693 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1694 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001695 /*
1696 * Avoid dynamic memory allocations for constant-size T2.
1697 *
1698 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1699 * so nobody increase the size of the MPI and we're safe to use an on-stack
1700 * buffer.
1701 */
Alexander K35d6d462019-10-31 14:46:45 +03001702 T2.s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001703 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001704 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001705
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001706 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1707 if (Q != NULL) {
1708 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1709 }
1710 if (R != NULL) {
1711 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1712 }
1713 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 }
1715
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001716 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1717 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001718 X.s = Y.s = 1;
1719
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001720 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1721 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1722 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001724 k = mbedtls_mpi_bitlen(&Y) % biL;
1725 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 k = biL - 1 - k;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001727 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1728 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1729 } else {
1730 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001731 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001732
1733 n = X.n - 1;
1734 t = Y.n - 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001735 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001736
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001737 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001738 Z.p[n - t]++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001739 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001740 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001741 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001742
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001743 for (i = n; i > t; i--) {
1744 if (X.p[i] >= Y.p[t]) {
1745 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1746 } else {
1747 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1748 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 }
1750
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001751 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1752 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001753 T2.p[2] = X.p[i];
1754
Paul Bakker5121ce52009-01-03 21:22:43 +00001755 Z.p[i - t - 1]++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001756 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001757 Z.p[i - t - 1]--;
1758
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001759 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1760 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001761 T1.p[1] = Y.p[t];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001762 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1763 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001764
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001765 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1766 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1767 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001769 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1770 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1771 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1772 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001773 Z.p[i - t - 1]--;
1774 }
1775 }
1776
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001777 if (Q != NULL) {
1778 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001779 Q->s = A->s * B->s;
1780 }
1781
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001782 if (R != NULL) {
1783 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001784 X.s = A->s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001785 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001786
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001787 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001788 R->s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001789 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001790 }
1791
1792cleanup:
1793
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001794 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1795 mbedtls_mpi_free(&T1);
1796 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001798 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001799}
1800
1801/*
1802 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001803 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001804int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1805 const mbedtls_mpi *A,
1806 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001807{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001808 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001810 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001812 p[0] = mpi_sint_abs(b);
1813 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001814 B.n = 1;
1815 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001817 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001818}
1819
1820/*
1821 * Modulo: R = A mod B
1822 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001823int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001824{
Janos Follath24eed8d2019-11-22 13:21:35 +00001825 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001826 MPI_VALIDATE_RET(R != NULL);
1827 MPI_VALIDATE_RET(A != NULL);
1828 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001830 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1831 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1832 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001833
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001834 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001835
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001836 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1837 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1838 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001840 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1841 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1842 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
1844cleanup:
1845
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001846 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001847}
1848
1849/*
1850 * Modulo: r = A mod b
1851 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001852int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001853{
Paul Bakker23986e52011-04-24 08:57:21 +00001854 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 mbedtls_mpi_uint x, y, z;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001856 MPI_VALIDATE_RET(r != NULL);
1857 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001858
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001859 if (b == 0) {
1860 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1861 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001863 if (b < 0) {
1864 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1865 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001866
1867 /*
1868 * handle trivial cases
1869 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001870 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001871 *r = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001872 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 }
1874
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001875 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001876 *r = A->p[0] & 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001877 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 }
1879
1880 /*
1881 * general case
1882 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001883 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001884 x = A->p[i - 1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001885 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001886 z = y / b;
1887 y -= z * b;
1888
1889 x <<= biH;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001890 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001891 z = y / b;
1892 y -= z * b;
1893 }
1894
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001895 /*
1896 * If A is negative, then the current y represents a negative value.
1897 * Flipping it to the positive side.
1898 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001899 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001900 y = b - y;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001901 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001902
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 *r = y;
1904
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001905 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001906}
1907
1908/*
1909 * Fast Montgomery initialization (thanks to Tom St Denis)
1910 */
Janos Follath8cdb6062024-01-09 09:28:48 +00001911mbedtls_mpi_uint mbedtls_mpi_montmul_init(const mbedtls_mpi_uint *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001912{
Janos Follath8cdb6062024-01-09 09:28:48 +00001913 mbedtls_mpi_uint x = N[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
Janos Follath8cdb6062024-01-09 09:28:48 +00001915 x += ((N[0] + 2) & 4) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001916
Janos Follath8cdb6062024-01-09 09:28:48 +00001917 for (unsigned int i = biL; i >= 8; i /= 2) {
1918 x *= (2 - (N[0] * x));
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001919 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
Janos Follath8cdb6062024-01-09 09:28:48 +00001921 return ~x + 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001922}
1923
Janos Follath4fe396f2024-01-08 14:08:17 +00001924void mbedtls_mpi_montmul(mbedtls_mpi *A,
1925 const mbedtls_mpi *B,
1926 const mbedtls_mpi *N,
1927 mbedtls_mpi_uint mm,
1928 const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001929{
Paul Bakker23986e52011-04-24 08:57:21 +00001930 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001933 memset(T->p, 0, T->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001934
1935 d = T->p;
1936 n = N->n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001937 m = (B->n < n) ? B->n : n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001939 for (i = 0; i < n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 /*
1941 * T = (T + u0*B + u1*N) / 2^biL
1942 */
1943 u0 = A->p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001944 u1 = (d[0] + u0 * B->p[0]) * mm;
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001946 mpi_mul_hlp(m, B->p, d, u0);
1947 mpi_mul_hlp(n, N->p, d, u1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
1949 *d++ = u0; d[n + 1] = 0;
1950 }
1951
Gilles Peskine221626f2020-06-08 22:37:50 +02001952 /* At this point, d is either the desired result or the desired result
1953 * plus N. We now potentially subtract N, avoiding leaking whether the
1954 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001955
Gilles Peskine221626f2020-06-08 22:37:50 +02001956 /* Copy the n least significant limbs of d to A, so that
1957 * A = d if d < N (recall that N has n limbs). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001958 memcpy(A->p, d, n * ciL);
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001959 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02001960 * do the calculation without using conditional tests. */
1961 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02001962 d[n] += 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001963 d[n] -= mpi_sub_hlp(n, d, d, N->p);
Gilles Peskine221626f2020-06-08 22:37:50 +02001964 /* If d0 < N then d < (2^biL)^n
1965 * so d[n] == 0 and we want to keep A as it is.
1966 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1967 * so d[n] == 1 and we want to set A to the result of the subtraction
1968 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1969 * This exactly corresponds to a conditional assignment. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001970 mbedtls_ct_mpi_uint_cond_assign(n, A->p, d, (unsigned char) d[n]);
Paul Bakker5121ce52009-01-03 21:22:43 +00001971}
1972
1973/*
1974 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001975 *
Janos Follath4fe396f2024-01-08 14:08:17 +00001976 * See mbedtls_mpi_montmul() regarding constraints and guarantees on the
1977 * parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001979static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1980 mbedtls_mpi_uint mm, const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001981{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 mbedtls_mpi_uint z = 1;
1983 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
Paul Bakker8ddb6452013-02-27 14:56:33 +01001985 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001986 U.p = &z;
1987
Janos Follath4fe396f2024-01-08 14:08:17 +00001988 mbedtls_mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001989}
1990
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01001991/**
1992 * Select an MPI from a table without leaking the index.
1993 *
1994 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1995 * reads the entire table in order to avoid leaking the value of idx to an
1996 * attacker able to observe memory access patterns.
1997 *
1998 * \param[out] R Where to write the selected MPI.
1999 * \param[in] T The table to read from.
2000 * \param[in] T_size The number of elements in the table.
2001 * \param[in] idx The index of the element to select;
2002 * this must satisfy 0 <= idx < T_size.
2003 *
2004 * \return \c 0 on success, or a negative error code.
2005 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002006static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002007{
2008 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2009
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002010 for (size_t i = 0; i < T_size; i++) {
2011 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
2012 (unsigned char) mbedtls_ct_size_bool_eq(i,
2013 idx)));
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002014 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002015
2016cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002017 return ret;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002018}
2019
Janos Follath42175032024-01-08 13:45:49 +00002020int mbedtls_mpi_get_mont_r2_unsafe(mbedtls_mpi *X,
2021 const mbedtls_mpi *N)
2022{
2023 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2024
2025 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1));
2026 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, N->n * 2 * biL));
2027 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
2028 MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(X, N->n));
2029
2030cleanup:
2031 return ret;
2032}
2033
Paul Bakker5121ce52009-01-03 21:22:43 +00002034/*
2035 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2036 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002037int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
2038 const mbedtls_mpi *E, const mbedtls_mpi *N,
2039 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00002040{
Janos Follath24eed8d2019-11-22 13:21:35 +00002041 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathd88e2192022-11-21 15:54:20 +00002042 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00002043 size_t i, j, nblimbs;
2044 size_t bufsize, nbits;
Paul Elliottfc820d92023-01-13 16:29:30 +00002045 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002047 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002048 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002050 MPI_VALIDATE_RET(X != NULL);
2051 MPI_VALIDATE_RET(A != NULL);
2052 MPI_VALIDATE_RET(E != NULL);
2053 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002054
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002055 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
2056 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2057 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002059 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
2060 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2061 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00002062
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002063 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
2064 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
2065 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2066 }
Chris Jones9246d042020-11-25 15:12:39 +00002067
Paul Bakkerf6198c12012-05-16 08:02:29 +00002068 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002069 * Init temps and window size
2070 */
Janos Follath8cdb6062024-01-09 09:28:48 +00002071 mm = mbedtls_mpi_montmul_init(N->p);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002072 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
2073 mbedtls_mpi_init(&Apos);
2074 mbedtls_mpi_init(&WW);
2075 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00002076
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002077 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002079 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
2080 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002082#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
2083 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath66323832022-11-21 14:48:02 +00002084 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002085 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002086#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002087
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002088 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath6fa7a762022-11-22 10:18:06 +00002089
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 /*
Janos Follath6e2d8e32022-11-21 16:14:54 +00002091 * This function is not constant-trace: its memory accesses depend on the
2092 * exponent value. To defend against timing attacks, callers (such as RSA
2093 * and DHM) should use exponent blinding. However this is not enough if the
2094 * adversary can find the exponent in a single trace, so this function
2095 * takes extra precautions against adversaries who can observe memory
2096 * access patterns.
Janos Follath3a3c50c2022-11-11 15:56:38 +00002097 *
Janos Follath6e2d8e32022-11-21 16:14:54 +00002098 * This function performs a series of multiplications by table elements and
2099 * squarings, and we want the prevent the adversary from finding out which
2100 * table element was used, and from distinguishing between multiplications
2101 * and squarings. Firstly, when multiplying by an element of the window
2102 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
2103 * squarings as having a different memory access patterns from other
Gilles Peskine20d54e32023-08-10 15:59:28 +02002104 * multiplications. So secondly, we put the accumulator in the table as
2105 * well, and also do a constant-trace table lookup to multiply by the
2106 * accumulator which is W[x_index].
Janos Follath6e2d8e32022-11-21 16:14:54 +00002107 *
2108 * This way, all multiplications take the form of a lookup-and-multiply.
2109 * The number of lookup-and-multiply operations inside each iteration of
2110 * the main loop still depends on the bits of the exponent, but since the
2111 * other operations in the loop don't have an easily recognizable memory
2112 * trace, an adversary is unlikely to be able to observe the exact
2113 * patterns.
2114 *
2115 * An adversary may still be able to recover the exponent if they can
2116 * observe both memory accesses and branches. However, branch prediction
2117 * exploitation typically requires many traces of execution over the same
2118 * data, which is defeated by randomized blinding.
Janos Follath91c02862022-10-04 13:27:40 +01002119 */
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002120 const size_t x_index = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002121 mbedtls_mpi_init(&W[x_index]);
Janos Follathf0ceb1c2022-11-21 14:31:22 +00002122
2123 j = N->n + 1;
Gilles Peskine20d54e32023-08-10 15:59:28 +02002124 /* All W[i] including the accumulator must have at least N->n limbs for
Janos Follath4fe396f2024-01-08 14:08:17 +00002125 * the mbedtls_mpi_montmul() and mpi_montred() calls later. Here we ensure
2126 * that W[1] and the accumulator W[x_index] are large enough. later we'll
2127 * grow other W[i] to the same length. They must not be shrunk midway
2128 * through this function!
Janos Follath3a3c50c2022-11-11 15:56:38 +00002129 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002130 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
2131 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
2132 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Janos Follath91c02862022-10-04 13:27:40 +01002133
2134 /*
Paul Bakker50546922012-05-19 08:40:49 +00002135 * Compensate for negative A (and correct at the end)
2136 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002137 neg = (A->s == -1);
2138 if (neg) {
2139 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00002140 Apos.s = 1;
2141 A = &Apos;
2142 }
2143
2144 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002145 * If 1st call, pre-compute R^2 mod N
2146 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002147 if (prec_RR == NULL || prec_RR->p == NULL) {
Janos Follath42175032024-01-08 13:45:49 +00002148 mbedtls_mpi_get_mont_r2_unsafe(&RR, N);
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002150 if (prec_RR != NULL) {
2151 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
2152 }
2153 } else {
2154 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00002155 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002156
2157 /*
2158 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2159 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002160 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
2161 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002162 /* This should be a no-op because W[1] is already that large before
2163 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Janos Follath4fe396f2024-01-08 14:08:17 +00002164 * in mbedtls_mpi_montmul() below, so let's make sure. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002165 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
2166 } else {
2167 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002168 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002169
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002170 /* Note that this is safe because W[1] always has at least N->n limbs
2171 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Janos Follath4fe396f2024-01-08 14:08:17 +00002172 mbedtls_mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002173
2174 /*
Janos Follath91c02862022-10-04 13:27:40 +01002175 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002176 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002177 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
2178 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002180
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002181 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002182 /*
Janos Follathd88e2192022-11-21 15:54:20 +00002183 * W[i] = W[1] ^ i
2184 *
2185 * The first bit of the sliding window is always 1 and therefore we
2186 * only need to store the second half of the table.
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002187 *
2188 * (There are two special elements in the table: W[0] for the
2189 * accumulator/result and W[1] for A in Montgomery form. Both of these
2190 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00002191 */
Janos Follathd88e2192022-11-21 15:54:20 +00002192 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002193
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002194 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
2195 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002197 for (i = 0; i < window_bitsize - 1; i++) {
Janos Follath4fe396f2024-01-08 14:08:17 +00002198 mbedtls_mpi_montmul(&W[j], &W[j], N, mm, &T);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002199 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01002200
Paul Bakker5121ce52009-01-03 21:22:43 +00002201 /*
2202 * W[i] = W[i - 1] * W[1]
2203 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002204 for (i = j + 1; i < w_table_used_size; i++) {
2205 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
2206 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002207
Janos Follath4fe396f2024-01-08 14:08:17 +00002208 mbedtls_mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002209 }
2210 }
2211
2212 nblimbs = E->n;
2213 bufsize = 0;
2214 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002215 state = 0;
2216
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002217 while (1) {
2218 if (bufsize == 0) {
2219 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002220 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002221 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002222
Paul Bakker0d7702c2013-10-29 16:18:35 +01002223 nblimbs--;
2224
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002225 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002226 }
2227
2228 bufsize--;
2229
2230 ei = (E->p[nblimbs] >> bufsize) & 1;
2231
2232 /*
2233 * skip leading 0s
2234 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002235 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002236 continue;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002237 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002238
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002239 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 /*
Janos Follath91c02862022-10-04 13:27:40 +01002241 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00002242 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002243 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
Janos Follath4fe396f2024-01-08 14:08:17 +00002244 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 continue;
2246 }
2247
2248 /*
2249 * add ei to current window
2250 */
2251 state = 2;
2252
2253 nbits++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002254 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00002255
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002256 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 /*
Janos Follath66323832022-11-21 14:48:02 +00002258 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002260 for (i = 0; i < window_bitsize; i++) {
2261 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
2262 x_index));
Janos Follath4fe396f2024-01-08 14:08:17 +00002263 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follath95655a22022-10-04 14:00:09 +01002264 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002265
2266 /*
Janos Follath66323832022-11-21 14:48:02 +00002267 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002268 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002269 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
2270 exponent_bits_in_window));
Janos Follath4fe396f2024-01-08 14:08:17 +00002271 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
2273 state--;
2274 nbits = 0;
Janos Follath66323832022-11-21 14:48:02 +00002275 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 }
2277 }
2278
2279 /*
2280 * process the remaining bits
2281 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002282 for (i = 0; i < nbits; i++) {
2283 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
Janos Follath4fe396f2024-01-08 14:08:17 +00002284 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
Janos Follath66323832022-11-21 14:48:02 +00002286 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002287
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002288 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
2289 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
Janos Follath4fe396f2024-01-08 14:08:17 +00002290 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follath95655a22022-10-04 14:00:09 +01002291 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 }
2293
2294 /*
Janos Follath91c02862022-10-04 13:27:40 +01002295 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002297 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002299 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath91c02862022-10-04 13:27:40 +01002300 W[x_index].s = -1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002301 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00002302 }
2303
Janos Follath91c02862022-10-04 13:27:40 +01002304 /*
2305 * Load the result in the output variable.
2306 */
Chien Wong0118a1d2023-08-01 21:38:46 +08002307 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
Janos Follath91c02862022-10-04 13:27:40 +01002308
Paul Bakker5121ce52009-01-03 21:22:43 +00002309cleanup:
2310
Janos Follatha92f9152022-11-21 15:05:31 +00002311 /* The first bit of the sliding window is always 1 and therefore the first
2312 * half of the table was unused. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002313 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
2314 mbedtls_mpi_free(&W[i]);
2315 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002317 mbedtls_mpi_free(&W[x_index]);
2318 mbedtls_mpi_free(&W[1]);
2319 mbedtls_mpi_free(&T);
2320 mbedtls_mpi_free(&Apos);
2321 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00002322
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002323 if (prec_RR == NULL || prec_RR->p == NULL) {
2324 mbedtls_mpi_free(&RR);
2325 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002326
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002327 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002328}
2329
Paul Bakker5121ce52009-01-03 21:22:43 +00002330/*
2331 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2332 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002333int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002334{
Janos Follath24eed8d2019-11-22 13:21:35 +00002335 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002336 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002337 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002339 MPI_VALIDATE_RET(G != NULL);
2340 MPI_VALIDATE_RET(A != NULL);
2341 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002342
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002343 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002345 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2346 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002347
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002348 lz = mbedtls_mpi_lsb(&TA);
2349 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002350
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002351 /* The loop below gives the correct result when A==0 but not when B==0.
2352 * So have a special case for B==0. Leverage the fact that we just
2353 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2354 * slightly more efficient than cmp_int(). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002355 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
2356 ret = mbedtls_mpi_copy(G, A);
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002357 goto cleanup;
2358 }
2359
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002360 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002361 lz = lzt;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002362 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002363
Paul Bakker5121ce52009-01-03 21:22:43 +00002364 TA.s = TB.s = 1;
2365
Gilles Peskineea9aa142021-06-16 13:42:04 +02002366 /* We mostly follow the procedure described in HAC 14.54, but with some
2367 * minor differences:
2368 * - Sequences of multiplications or divisions by 2 are grouped into a
2369 * single shift operation.
Gilles Peskine37d690c2021-06-21 18:58:39 +02002370 * - The procedure in HAC assumes that 0 < TB <= TA.
2371 * - The condition TB <= TA is not actually necessary for correctness.
2372 * TA and TB have symmetric roles except for the loop termination
2373 * condition, and the shifts at the beginning of the loop body
2374 * remove any significance from the ordering of TA vs TB before
2375 * the shifts.
2376 * - If TA = 0, the loop goes through 0 iterations and the result is
2377 * correctly TB.
2378 * - The case TB = 0 was short-circuited above.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002379 *
2380 * For the correctness proof below, decompose the original values of
2381 * A and B as
2382 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2383 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2384 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2385 * and gcd(A',B') is odd or 0.
2386 *
2387 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2388 * The code maintains the following invariant:
2389 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine6537bdb2021-06-15 22:09:39 +02002390 */
2391
Gilles Peskineea9aa142021-06-16 13:42:04 +02002392 /* Proof that the loop terminates:
2393 * At each iteration, either the right-shift by 1 is made on a nonzero
2394 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2395 * by at least 1, or the right-shift by 1 is made on zero and then
2396 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2397 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2398 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002399 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskineea9aa142021-06-16 13:42:04 +02002400 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002401 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2402 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002403
Gilles Peskineea9aa142021-06-16 13:42:04 +02002404 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2405 * TA-TB is even so the division by 2 has an integer result.
2406 * Invariant (I) is preserved since any odd divisor of both TA and TB
2407 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case0e7791f2021-12-20 21:14:10 -08002408 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskineea9aa142021-06-16 13:42:04 +02002409 * divides TA.
2410 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002411 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2412 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2413 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2414 } else {
2415 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2416 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002417 }
Gilles Peskineea9aa142021-06-16 13:42:04 +02002418 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002419 }
2420
Gilles Peskineea9aa142021-06-16 13:42:04 +02002421 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2422 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2423 * - If there was at least one loop iteration, then one of TA or TB is odd,
2424 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2425 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2426 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskineb798b352021-06-21 11:40:38 +02002427 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002428 */
2429
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002430 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2431 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
2433cleanup:
2434
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002435 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002437 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002438}
2439
Gilles Peskine8f454702021-04-01 15:57:18 +02002440/* Fill X with n_bytes random bytes.
2441 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002442 * The ordering of the bytes returned from the RNG is suitable for
2443 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002444 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002445 * n_bytes must not be 0.
2446 */
2447static int mpi_fill_random_internal(
2448 mbedtls_mpi *X, size_t n_bytes,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002449 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Gilles Peskine8f454702021-04-01 15:57:18 +02002450{
2451 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002452 const size_t limbs = CHARS_TO_LIMBS(n_bytes);
2453 const size_t overhead = (limbs * ciL) - n_bytes;
Gilles Peskine8f454702021-04-01 15:57:18 +02002454
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002455 if (X->n < limbs) {
2456 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2457 }
Gilles Peskine8f454702021-04-01 15:57:18 +02002458
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002459 memset(X->p, 0, overhead);
2460 memset((unsigned char *) X->p + limbs * ciL, 0, (X->n - limbs) * ciL);
2461 MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X->p + overhead, n_bytes));
2462 mpi_bigendian_to_host(X->p, limbs);
Gilles Peskine8f454702021-04-01 15:57:18 +02002463
2464cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002465 return ret;
Gilles Peskine8f454702021-04-01 15:57:18 +02002466}
2467
Paul Bakker33dc46b2014-04-30 16:11:39 +02002468/*
2469 * Fill X with size bytes of random.
2470 *
2471 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002472 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002473 * deterministic, eg for tests).
2474 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002475int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2476 int (*f_rng)(void *, unsigned char *, size_t),
2477 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002478{
Janos Follath24eed8d2019-11-22 13:21:35 +00002479 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002480 size_t const limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002481
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002482 MPI_VALIDATE_RET(X != NULL);
2483 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002484
Hanno Beckerda1655a2017-10-18 14:21:44 +01002485 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002486 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2487 if (size == 0) {
2488 return 0;
2489 }
Paul Bakker287781a2011-03-26 13:18:49 +00002490
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002491 ret = mpi_fill_random_internal(X, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002492
2493cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002494 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002495}
2496
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002497int mbedtls_mpi_random(mbedtls_mpi *X,
2498 mbedtls_mpi_sint min,
2499 const mbedtls_mpi *N,
2500 int (*f_rng)(void *, unsigned char *, size_t),
2501 void *p_rng)
Gilles Peskine4699fa42021-03-29 22:02:55 +02002502{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002503 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002504 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002505 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002506 size_t n_bits = mbedtls_mpi_bitlen(N);
2507 size_t n_bytes = (n_bits + 7) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002508 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002509
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002510 if (min < 0) {
2511 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2512 }
2513 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2514 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2515 }
Gilles Peskine9312ba52021-03-29 22:14:51 +02002516
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002517 /*
2518 * When min == 0, each try has at worst a probability 1/2 of failing
2519 * (the msb has a probability 1/2 of being 0, and then the result will
2520 * be < N), so after 30 tries failure probability is a most 2**(-30).
2521 *
2522 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002523 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002524 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002525 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002526 * a probability of failing that is almost 1/2.
2527 *
2528 * The probabilities are almost the same if min is nonzero but negligible
2529 * compared to N. This is always the case when N is crypto-sized, but
2530 * it's convenient to support small N for testing purposes. When N
2531 * is small, use a higher repeat count, otherwise the probability of
2532 * failure is macroscopic.
2533 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002534 count = (n_bytes > 4 ? 30 : 250);
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002535
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002536 mbedtls_mpi_init(&lower_bound);
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002537
Gilles Peskine8f454702021-04-01 15:57:18 +02002538 /* Ensure that target MPI has exactly the same number of limbs
2539 * as the upper bound, even if the upper bound has leading zeros.
2540 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002541 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, N->n));
2542 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&lower_bound, N->n));
2543 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&lower_bound, min));
Gilles Peskine8f454702021-04-01 15:57:18 +02002544
Gilles Peskine4699fa42021-03-29 22:02:55 +02002545 /*
2546 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2547 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2548 * - use the same byte ordering;
2549 * - keep the leftmost n_bits bits of the generated octet string;
2550 * - try until result is in the desired range.
2551 * This also avoids any bias, which is especially important for ECDSA.
2552 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002553 do {
2554 MBEDTLS_MPI_CHK(mpi_fill_random_internal(X, n_bytes, f_rng, p_rng));
2555 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, 8 * n_bytes - n_bits));
Gilles Peskine4699fa42021-03-29 22:02:55 +02002556
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002557 if (--count == 0) {
Gilles Peskine4699fa42021-03-29 22:02:55 +02002558 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2559 goto cleanup;
2560 }
2561
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002562 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, &lower_bound, &lt_lower));
2563 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, N, &lt_upper));
2564 } while (lt_lower != 0 || lt_upper == 0);
Gilles Peskine4699fa42021-03-29 22:02:55 +02002565
2566cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002567 mbedtls_mpi_free(&lower_bound);
2568 return ret;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002569}
2570
Paul Bakker5121ce52009-01-03 21:22:43 +00002571/*
2572 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2573 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002574int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002575{
Janos Follath24eed8d2019-11-22 13:21:35 +00002576 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002578 MPI_VALIDATE_RET(X != NULL);
2579 MPI_VALIDATE_RET(A != NULL);
2580 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002581
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002582 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2583 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2584 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002586 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2587 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2588 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002589
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002590 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002592 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002594 goto cleanup;
2595 }
2596
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002597 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2598 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2599 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2600 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002601
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002602 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2603 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2604 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2605 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002606
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002607 do {
2608 while ((TU.p[0] & 1) == 0) {
2609 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002610
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002611 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2612 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2613 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002614 }
2615
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002616 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2617 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002618 }
2619
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002620 while ((TV.p[0] & 1) == 0) {
2621 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002622
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002623 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2624 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2625 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002626 }
2627
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002628 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2629 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002630 }
2631
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002632 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2633 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2634 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2635 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2636 } else {
2637 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2638 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2639 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002640 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002641 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2642
2643 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2644 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002645 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002646
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002647 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2648 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2649 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002650
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002651 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002652
2653cleanup:
2654
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002655 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2656 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2657 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002658
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002659 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002660}
2661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002662#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002663
Paul Bakker5121ce52009-01-03 21:22:43 +00002664static const int small_prime[] =
2665{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002666 3, 5, 7, 11, 13, 17, 19, 23,
2667 29, 31, 37, 41, 43, 47, 53, 59,
2668 61, 67, 71, 73, 79, 83, 89, 97,
2669 101, 103, 107, 109, 113, 127, 131, 137,
2670 139, 149, 151, 157, 163, 167, 173, 179,
2671 181, 191, 193, 197, 199, 211, 223, 227,
2672 229, 233, 239, 241, 251, 257, 263, 269,
2673 271, 277, 281, 283, 293, 307, 311, 313,
2674 317, 331, 337, 347, 349, 353, 359, 367,
2675 373, 379, 383, 389, 397, 401, 409, 419,
2676 421, 431, 433, 439, 443, 449, 457, 461,
2677 463, 467, 479, 487, 491, 499, 503, 509,
2678 521, 523, 541, 547, 557, 563, 569, 571,
2679 577, 587, 593, 599, 601, 607, 613, 617,
2680 619, 631, 641, 643, 647, 653, 659, 661,
2681 673, 677, 683, 691, 701, 709, 719, 727,
2682 733, 739, 743, 751, 757, 761, 769, 773,
2683 787, 797, 809, 811, 821, 823, 827, 829,
2684 839, 853, 857, 859, 863, 877, 881, 883,
2685 887, 907, 911, 919, 929, 937, 941, 947,
2686 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002687};
2688
2689/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002690 * Small divisors test (X must be positive)
2691 *
2692 * Return values:
2693 * 0: no small factor (possible prime, more tests needed)
2694 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002696 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002697 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002698static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002699{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002700 int ret = 0;
2701 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002703
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002704 if ((X->p[0] & 1) == 0) {
2705 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2706 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002707
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002708 for (i = 0; small_prime[i] > 0; i++) {
2709 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2710 return 1;
2711 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002712
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002713 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002714
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002715 if (r == 0) {
2716 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2717 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002718 }
2719
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002720cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002721 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002722}
2723
2724/*
2725 * Miller-Rabin pseudo-primality test (HAC 4.24)
2726 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002727static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2728 int (*f_rng)(void *, unsigned char *, size_t),
2729 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002730{
Pascal Junodb99183d2015-03-11 16:49:45 +01002731 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002732 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002733 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002734
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002735 MPI_VALIDATE_RET(X != NULL);
2736 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002737
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002738 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2739 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2740 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002741
Paul Bakker5121ce52009-01-03 21:22:43 +00002742 /*
2743 * W = |X| - 1
2744 * R = W >> lsb( W )
2745 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002746 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2747 s = mbedtls_mpi_lsb(&W);
2748 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2749 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002750
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002751 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002752 /*
2753 * pick a random A, 1 < A < |X| - 1
2754 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002755 count = 0;
2756 do {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002757 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002758
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002759 j = mbedtls_mpi_bitlen(&A);
2760 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002761 if (j > k) {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002762 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002763 }
2764
2765 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002766 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2767 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002768 }
2769
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002770 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2771 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002772
2773 /*
2774 * A = A^R mod |X|
2775 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002776 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002777
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002778 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2779 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002780 continue;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002781 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002782
2783 j = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002784 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002785 /*
2786 * A = A * A mod |X|
2787 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002788 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2789 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002790
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002791 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002792 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002793 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002794
2795 j++;
2796 }
2797
2798 /*
2799 * not prime if A != |X| - 1 or A == 1
2800 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002801 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2802 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002804 break;
2805 }
2806 }
2807
2808cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002809 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2810 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2811 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002812
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002813 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002814}
2815
2816/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002817 * Pseudo-primality test: small factors, then Miller-Rabin
2818 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002819int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2820 int (*f_rng)(void *, unsigned char *, size_t),
2821 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002822{
Janos Follath24eed8d2019-11-22 13:21:35 +00002823 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002824 mbedtls_mpi XX;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002825 MPI_VALIDATE_RET(X != NULL);
2826 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002827
2828 XX.s = 1;
2829 XX.n = X->n;
2830 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002831
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002832 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2833 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2834 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002835 }
2836
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002837 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2838 return 0;
2839 }
2840
2841 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2842 if (ret == 1) {
2843 return 0;
2844 }
2845
2846 return ret;
2847 }
2848
2849 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002850}
2851
Janos Follatha0b67c22018-09-18 14:48:23 +01002852#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002853/*
2854 * Pseudo-primality test, error probability 2^-80
2855 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002856int mbedtls_mpi_is_prime(const mbedtls_mpi *X,
2857 int (*f_rng)(void *, unsigned char *, size_t),
2858 void *p_rng)
Janos Follathf301d232018-08-14 13:34:01 +01002859{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002860 MPI_VALIDATE_RET(X != NULL);
2861 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002862
Janos Follatha0b67c22018-09-18 14:48:23 +01002863 /*
2864 * In the past our key generation aimed for an error rate of at most
2865 * 2^-80. Since this function is deprecated, aim for the same certainty
2866 * here as well.
2867 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002868 return mbedtls_mpi_is_prime_ext(X, 40, f_rng, p_rng);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002869}
Janos Follatha0b67c22018-09-18 14:48:23 +01002870#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002871
2872/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002873 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002874 *
Janos Follathf301d232018-08-14 13:34:01 +01002875 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2876 * be either 1024 bits or 1536 bits long, and flags must contain
2877 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002878 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002879int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2880 int (*f_rng)(void *, unsigned char *, size_t),
2881 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002882{
Jethro Beekman66689272018-02-14 19:24:10 -08002883#ifdef MBEDTLS_HAVE_INT64
2884// ceil(2^63.5)
2885#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2886#else
2887// ceil(2^31.5)
2888#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2889#endif
2890 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002891 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002892 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002893 mbedtls_mpi_uint r;
2894 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002895
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002896 MPI_VALIDATE_RET(X != NULL);
2897 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002898
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002899 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2900 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2901 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002902
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002903 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002904
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002905 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002906
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002907 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002908 /*
2909 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2910 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002911 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2912 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2913 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2914 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002915 /*
2916 * 2^-100 error probability, number of rounds computed based on HAC,
2917 * fact 4.48
2918 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002919 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2920 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2921 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2922 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002923 }
2924
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002925 while (1) {
2926 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002927 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002928 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2929 continue;
2930 }
Jethro Beekman66689272018-02-14 19:24:10 -08002931
2932 k = n * biL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002933 if (k > nbits) {
2934 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2935 }
Jethro Beekman66689272018-02-14 19:24:10 -08002936 X->p[0] |= 1;
2937
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002938 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2939 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002940
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002941 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002942 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002943 }
2944 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002945 /*
Tom Cosgrove5205c972022-07-28 06:12:08 +01002946 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002947 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2948 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002949 */
Jethro Beekman66689272018-02-14 19:24:10 -08002950
2951 X->p[0] |= 2;
2952
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002953 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2954 if (r == 0) {
2955 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2956 } else if (r == 1) {
2957 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2958 }
Jethro Beekman66689272018-02-14 19:24:10 -08002959
2960 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002961 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2962 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002963
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002964 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002965 /*
2966 * First, check small factors for X and Y
2967 * before doing Miller-Rabin on any of them
2968 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002969 if ((ret = mpi_check_small_factors(X)) == 0 &&
2970 (ret = mpi_check_small_factors(&Y)) == 0 &&
2971 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2972 == 0 &&
2973 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2974 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002975 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002976 }
Jethro Beekman66689272018-02-14 19:24:10 -08002977
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002978 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002979 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002980 }
Jethro Beekman66689272018-02-14 19:24:10 -08002981
2982 /*
2983 * Next candidates. We want to preserve Y = (X-1) / 2 and
2984 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2985 * so up Y by 6 and X by 12.
2986 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002987 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2988 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002989 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002990 }
2991 }
2992
2993cleanup:
2994
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002995 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002996
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002997 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002998}
2999
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003000#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003001
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003002#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003003
Paul Bakker23986e52011-04-24 08:57:21 +00003004#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003005
3006static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3007{
3008 { 693, 609, 21 },
3009 { 1764, 868, 28 },
3010 { 768454923, 542167814, 1 }
3011};
3012
Paul Bakker5121ce52009-01-03 21:22:43 +00003013/*
3014 * Checkup routine
3015 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003016int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00003017{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003018 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003019 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003020
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003021 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
3022 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003023
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003024 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
3025 "EFE021C2645FD1DC586E69184AF4A31E" \
3026 "D5F53E93B5F123FA41680867BA110131" \
3027 "944FE7952E2517337780CB0DB80E61AA" \
3028 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003029
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003030 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
3031 "B2E7EFD37075B9F03FF989C7C5051C20" \
3032 "34D2A323810251127E7BF8625A4F49A5" \
3033 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3034 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003035
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003036 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
3037 "0066A198186C18C10B2F5ED9B522752A" \
3038 "9830B69916E535C8F047518A889A43A5" \
3039 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003040
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003041 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003042
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003043 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3044 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3045 "9E857EA95A03512E2BAE7391688D264A" \
3046 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3047 "8001B72E848A38CAE1C65F78E56ABDEF" \
3048 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3049 "ECF677152EF804370C1A305CAF3B5BF1" \
3050 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003051
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003052 if (verbose != 0) {
3053 mbedtls_printf(" MPI test #1 (mul_mpi): ");
3054 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003055
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003056 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3057 if (verbose != 0) {
3058 mbedtls_printf("failed\n");
3059 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003060
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003061 ret = 1;
3062 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003063 }
3064
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003065 if (verbose != 0) {
3066 mbedtls_printf("passed\n");
3067 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003068
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003069 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003070
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003071 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3072 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003073
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003074 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
3075 "6613F26162223DF488E9CD48CC132C7A" \
3076 "0AC93C701B001B092E4E5B9F73BCD27B" \
3077 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003078
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003079 if (verbose != 0) {
3080 mbedtls_printf(" MPI test #2 (div_mpi): ");
3081 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003082
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003083 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
3084 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
3085 if (verbose != 0) {
3086 mbedtls_printf("failed\n");
3087 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003088
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003089 ret = 1;
3090 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003091 }
3092
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003093 if (verbose != 0) {
3094 mbedtls_printf("passed\n");
3095 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003096
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003097 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00003098
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003099 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3100 "36E139AEA55215609D2816998ED020BB" \
3101 "BD96C37890F65171D948E9BC7CBAA4D9" \
3102 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003103
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003104 if (verbose != 0) {
3105 mbedtls_printf(" MPI test #3 (exp_mod): ");
3106 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003107
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003108 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3109 if (verbose != 0) {
3110 mbedtls_printf("failed\n");
3111 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003112
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003113 ret = 1;
3114 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003115 }
3116
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003117 if (verbose != 0) {
3118 mbedtls_printf("passed\n");
3119 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003120
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003121 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003122
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003123 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3124 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3125 "C3DBA76456363A10869622EAC2DD84EC" \
3126 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003127
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003128 if (verbose != 0) {
3129 mbedtls_printf(" MPI test #4 (inv_mod): ");
3130 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003131
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003132 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3133 if (verbose != 0) {
3134 mbedtls_printf("failed\n");
3135 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003136
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003137 ret = 1;
3138 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003139 }
3140
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003141 if (verbose != 0) {
3142 mbedtls_printf("passed\n");
3143 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003144
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003145 if (verbose != 0) {
3146 mbedtls_printf(" MPI test #5 (simple gcd): ");
3147 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003148
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003149 for (i = 0; i < GCD_PAIR_COUNT; i++) {
3150 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
3151 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003152
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003153 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003154
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003155 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
3156 if (verbose != 0) {
3157 mbedtls_printf("failed at %d\n", i);
3158 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003159
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003160 ret = 1;
3161 goto cleanup;
3162 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003163 }
3164
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003165 if (verbose != 0) {
3166 mbedtls_printf("passed\n");
3167 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003168
Paul Bakker5121ce52009-01-03 21:22:43 +00003169cleanup:
3170
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003171 if (ret != 0 && verbose != 0) {
3172 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
3173 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003174
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003175 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
3176 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003177
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003178 if (verbose != 0) {
3179 mbedtls_printf("\n");
3180 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003181
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003182 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00003183}
3184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003185#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003187#endif /* MBEDTLS_BIGNUM_C */