blob: 74f10af8d5d3bac9e0d9aba4f43fed4f46116775 [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"
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Tom Cosgrove58efe612021-11-15 09:59:53 +000034#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000035#include <string.h>
36
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000037#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020038
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010039#define MPI_VALIDATE_RET(cond) \
40 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
41#define MPI_VALIDATE(cond) \
42 MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker73d7d792018-12-11 10:35:51 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000045#define biL (ciL << 3) /* bits in limb */
46#define biH (ciL << 2) /* half limb size */
47
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010048#define MPI_SIZE_T_MAX ((size_t) -1) /* SIZE_T_MAX is not standard */
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010049
Paul Bakker5121ce52009-01-03 21:22:43 +000050/*
51 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020052 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000053 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010054#define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0))
55#define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0))
Paul Bakker5121ce52009-01-03 21:22:43 +000056
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050057/* Implementation that should never be optimized out by the compiler */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010058static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050059{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010060 mbedtls_platform_zeroize(v, ciL * n);
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050061}
62
Paul Bakker5121ce52009-01-03 21:22:43 +000063/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000064 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000065 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010066void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000067{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010068 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +000069
Paul Bakker6c591fa2011-05-05 11:49:20 +000070 X->s = 1;
71 X->n = 0;
72 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000073}
74
75/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000076 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000077 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010078void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000079{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010080 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010082 }
Paul Bakker5121ce52009-01-03 21:22:43 +000083
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010084 if (X->p != NULL) {
85 mbedtls_mpi_zeroize(X->p, X->n);
86 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +000087 }
88
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 X->s = 1;
90 X->n = 0;
91 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000092}
93
94/*
95 * Enlarge to the specified number of limbs
96 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010097int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +000098{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099 mbedtls_mpi_uint *p;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100100 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000101
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100102 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
103 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
104 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000105
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100106 if (X->n < nblimbs) {
107 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
108 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
109 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000110
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100111 if (X->p != NULL) {
112 memcpy(p, X->p, X->n * ciL);
113 mbedtls_mpi_zeroize(X->p, X->n);
114 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000115 }
116
117 X->n = nblimbs;
118 X->p = p;
119 }
120
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100121 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122}
123
124/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100125 * Resize down as much as possible,
126 * while keeping at least the specified number of limbs
127 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100128int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100129{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100131 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100132 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000133
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100134 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
135 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
136 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100137
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100138 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100139 if (X->n <= nblimbs) {
140 return mbedtls_mpi_grow(X, nblimbs);
141 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100142 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100144 for (i = X->n - 1; i > 0; i--) {
145 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100146 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100147 }
148 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149 i++;
150
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152 i = nblimbs;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100153 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100155 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
156 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
157 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100158
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100159 if (X->p != NULL) {
160 memcpy(p, X->p, i * ciL);
161 mbedtls_mpi_zeroize(X->p, X->n);
162 mbedtls_free(X->p);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163 }
164
165 X->n = i;
166 X->p = p;
167
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100168 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169}
170
Gilles Peskine3130ce22021-06-02 22:17:52 +0200171/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100172static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskine3130ce22021-06-02 22:17:52 +0200173{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100174 if (limbs == 0) {
175 mbedtls_mpi_free(X);
176 return 0;
177 } else if (X->n == limbs) {
178 memset(X->p, 0, limbs * ciL);
Gilles Peskine3130ce22021-06-02 22:17:52 +0200179 X->s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100180 return 0;
181 } else {
182 mbedtls_mpi_free(X);
183 return mbedtls_mpi_grow(X, limbs);
Gilles Peskine3130ce22021-06-02 22:17:52 +0200184 }
185}
186
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100187/*
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200188 * Copy the contents of Y into X.
189 *
190 * This function is not constant-time. Leading zeros in Y may be removed.
191 *
192 * Ensure that X does not shrink. This is not guaranteed by the public API,
193 * but some code in the bignum module relies on this property, for example
194 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000195 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100196int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000197{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100198 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000199 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200 MPI_VALIDATE_RET(X != NULL);
201 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000202
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100203 if (X == Y) {
204 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200205 }
206
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100207 if (Y->n == 0) {
208 if (X->n != 0) {
209 X->s = 1;
210 memset(X->p, 0, X->n * ciL);
211 }
212 return 0;
213 }
214
215 for (i = Y->n - 1; i > 0; i--) {
216 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000217 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100218 }
219 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000220 i++;
221
222 X->s = Y->s;
223
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100224 if (X->n < i) {
225 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
226 } else {
227 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100228 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000229
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000231
232cleanup:
233
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100234 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000235}
236
237/*
238 * Swap the contents of X and Y
239 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100240void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000241{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100243 MPI_VALIDATE(X != NULL);
244 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000245
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100246 memcpy(&T, X, sizeof(mbedtls_mpi));
247 memcpy(X, Y, sizeof(mbedtls_mpi));
248 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000249}
250
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100251static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100252{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100253 if (z >= 0) {
254 return z;
255 }
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100256 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
257 * A naive -z would have undefined behavior.
258 * Write this in a way that makes popular compilers happy (GCC, Clang,
259 * MSVC). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100260 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100261}
262
Paul Bakker5121ce52009-01-03 21:22:43 +0000263/*
264 * Set value from integer
265 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100266int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000267{
Janos Follath24eed8d2019-11-22 13:21:35 +0000268 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100269 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000270
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100271 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
272 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000273
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100274 X->p[0] = mpi_sint_abs(z);
275 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000276
277cleanup:
278
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100279 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000280}
281
282/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000283 * Get a specific bit
284 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100285int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000286{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100287 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000288
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100289 if (X->n * biL <= pos) {
290 return 0;
291 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000292
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100293 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000294}
295
Gilles Peskine11cdb052018-11-20 16:47:47 +0100296/* Get a specific byte, without range checks. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297#define GET_BYTE(X, i) \
298 (((X)->p[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)
Gilles Peskine11cdb052018-11-20 16:47:47 +0100299
Paul Bakker2f5947e2011-05-18 15:47:11 +0000300/*
301 * Set a bit to a specific value of 0 or 1
302 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100303int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000304{
305 int ret = 0;
306 size_t off = pos / biL;
307 size_t idx = pos % biL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100308 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000309
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100310 if (val != 0 && val != 1) {
311 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000312 }
313
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100314 if (X->n * biL <= pos) {
315 if (val == 0) {
316 return 0;
317 }
318
319 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
320 }
321
322 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000324
325cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200326
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100327 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328}
329
330/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200331 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000332 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100333size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000334{
Paul Bakker23986e52011-04-24 08:57:21 +0000335 size_t i, j, count = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100336 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000337
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100338 for (i = 0; i < X->n; i++) {
339 for (j = 0; j < biL; j++, count++) {
340 if (((X->p[i] >> j) & 1) != 0) {
341 return count;
342 }
343 }
344 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000345
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100346 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000347}
348
349/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000350 * Count leading zero bits in a given integer
351 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100352static size_t mbedtls_clz(const mbedtls_mpi_uint x)
Simon Butcher15b15d12015-11-26 19:35:03 +0000353{
354 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100355 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000356
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100357 for (j = 0; j < biL; j++) {
358 if (x & mask) {
359 break;
360 }
Simon Butcher15b15d12015-11-26 19:35:03 +0000361
362 mask >>= 1;
363 }
364
365 return j;
366}
367
368/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200369 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000370 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100371size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000372{
Paul Bakker23986e52011-04-24 08:57:21 +0000373 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000374
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100375 if (X->n == 0) {
376 return 0;
377 }
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200378
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100379 for (i = X->n - 1; i > 0; i--) {
380 if (X->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000381 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100382 }
383 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100385 j = biL - mbedtls_clz(X->p[i]);
Paul Bakker5121ce52009-01-03 21:22:43 +0000386
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100387 return (i * biL) + j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000388}
389
390/*
391 * Return the total size in bytes
392 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100393size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000394{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100395 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000396}
397
398/*
399 * Convert an ASCII character to digit value
400 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100401static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000402{
403 *d = 255;
404
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100405 if (c >= 0x30 && c <= 0x39) {
406 *d = c - 0x30;
407 }
408 if (c >= 0x41 && c <= 0x46) {
409 *d = c - 0x37;
410 }
411 if (c >= 0x61 && c <= 0x66) {
412 *d = c - 0x57;
413 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000414
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100415 if (*d >= (mbedtls_mpi_uint) radix) {
416 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
417 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000418
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100419 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000420}
421
422/*
423 * Import from an ASCII string
424 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100425int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000426{
Janos Follath24eed8d2019-11-22 13:21:35 +0000427 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000428 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200429 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 mbedtls_mpi_uint d;
431 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100432 MPI_VALIDATE_RET(X != NULL);
433 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000434
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100435 if (radix < 2 || radix > 16) {
436 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskined4876132021-06-08 18:32:34 +0200437 }
438
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100439 mbedtls_mpi_init(&T);
440
441 if (s[0] == 0) {
442 mbedtls_mpi_free(X);
443 return 0;
444 }
445
446 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200447 ++s;
448 sign = -1;
449 }
450
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100451 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000452
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100453 if (radix == 16) {
454 if (slen > MPI_SIZE_T_MAX >> 2) {
455 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000456 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000457
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100458 n = BITS_TO_LIMBS(slen << 2);
459
460 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
461 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
462
463 for (i = slen, j = 0; i > 0; i--, j++) {
464 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
465 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
466 }
467 } else {
468 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
469
470 for (i = 0; i < slen; i++) {
471 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
472 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
473 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 }
475 }
476
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100477 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200478 X->s = -1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100479 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200480
Paul Bakker5121ce52009-01-03 21:22:43 +0000481cleanup:
482
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100483 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100485 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000486}
487
488/*
Ron Eldora16fa292018-11-20 14:07:01 +0200489 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000490 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100491static int mpi_write_hlp(mbedtls_mpi *X, int radix,
492 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000493{
Janos Follath24eed8d2019-11-22 13:21:35 +0000494 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200496 size_t length = 0;
497 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000498
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100499 do {
500 if (length >= buflen) {
501 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200502 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100504 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
505 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200506 /*
507 * Write the residue in the current position, as an ASCII character.
508 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100509 if (r < 0xA) {
510 *(--p_end) = (char) ('0' + r);
511 } else {
512 *(--p_end) = (char) ('A' + (r - 0xA));
513 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
Ron Eldora16fa292018-11-20 14:07:01 +0200515 length++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100516 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000517
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100518 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200519 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000520
521cleanup:
522
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100523 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000524}
525
526/*
527 * Export into an ASCII string
528 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100529int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
530 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000531{
Paul Bakker23986e52011-04-24 08:57:21 +0000532 int ret = 0;
533 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000534 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100536 MPI_VALIDATE_RET(X != NULL);
537 MPI_VALIDATE_RET(olen != NULL);
538 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100540 if (radix < 2 || radix > 16) {
541 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
542 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000543
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100544 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
545 if (radix >= 4) {
546 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000547 * `n`. If radix > 4, this might be a strict
548 * overapproximation of the number of
549 * radix-adic digits needed to present `n`. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100550 }
551 if (radix >= 16) {
552 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000553 * present `n`. */
554
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100555 }
Janos Follath80470622019-03-06 13:43:02 +0000556 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000557 n += 1; /* Compensate for the divisions above, which round down `n`
558 * in case it's not even. */
559 n += 1; /* Potential '-'-sign. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100560 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000561 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100563 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100564 *olen = n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100565 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000566 }
567
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100568 p = buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100569 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100571 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000572 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000573 buflen--;
574 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000575
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100576 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000577 int c;
578 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100580 for (i = X->n, k = 0; i > 0; i--) {
581 for (j = ciL; j > 0; j--) {
582 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100584 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000585 continue;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100586 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000588 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000589 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000590 k = 1;
591 }
592 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100593 } else {
594 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000595
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100596 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000597 T.s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100598 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000599
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100600 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 }
602
603 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100604 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
606cleanup:
607
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100608 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100610 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000611}
612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000614/*
615 * Read X from an opened file
616 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100617int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000618{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000620 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000622 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000623 * Buffer should have space for (short) label and decimal formatted MPI,
624 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000625 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100626 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100628 MPI_VALIDATE_RET(X != NULL);
629 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000630
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100631 if (radix < 2 || radix > 16) {
632 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
633 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000634
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100635 memset(s, 0, sizeof(s));
636 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
637 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
638 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100640 slen = strlen(s);
641 if (slen == sizeof(s) - 2) {
642 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
643 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000644
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100645 if (slen > 0 && s[slen - 1] == '\n') {
646 slen--; s[slen] = '\0';
647 }
648 if (slen > 0 && s[slen - 1] == '\r') {
649 slen--; s[slen] = '\0';
650 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
652 p = s + slen;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100653 while (p-- > s) {
654 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000655 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100656 }
657 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100659 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000660}
661
662/*
663 * Write X into an opened file (or stdout if fout == NULL)
664 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100665int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000666{
Janos Follath24eed8d2019-11-22 13:21:35 +0000667 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000668 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000669 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000670 * Buffer should have space for (short) label and decimal formatted MPI,
671 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000672 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100673 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
674 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000675
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100676 if (radix < 2 || radix > 16) {
677 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
678 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100680 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100682 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100684 if (p == NULL) {
685 p = "";
686 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100688 plen = strlen(p);
689 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000690 s[slen++] = '\r';
691 s[slen++] = '\n';
692
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100693 if (fout != NULL) {
694 if (fwrite(p, 1, plen, fout) != plen ||
695 fwrite(s, 1, slen, fout) != slen) {
696 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
697 }
698 } else {
699 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000700 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000701
702cleanup:
703
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100704 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000705}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
Hanno Beckerda1655a2017-10-18 14:21:44 +0100708
709/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
710 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000711
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100712static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000713{
714 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100715 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000716 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100717
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100718 for (i = 0, x_ptr = (unsigned char *) &x; i < ciL; i++, x_ptr++) {
Hanno Becker031d6332019-05-01 17:09:11 +0100719 tmp <<= CHAR_BIT;
720 tmp |= (mbedtls_mpi_uint) *x_ptr;
721 }
722
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100723 return tmp;
Hanno Beckerf8720072018-11-08 11:53:49 +0000724}
725
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100726static mbedtls_mpi_uint mpi_uint_bigendian_to_host(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000727{
728#if defined(__BYTE_ORDER__)
729
730/* Nothing to do on bigendian systems. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100731#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
732 return x;
Hanno Beckerf8720072018-11-08 11:53:49 +0000733#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
734
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100735#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
Hanno Beckerf8720072018-11-08 11:53:49 +0000736
737/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000738#if defined(__GNUC__) && defined(__GNUC_PREREQ)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100739#if __GNUC_PREREQ(4, 3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000740#define have_bswap
741#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000742#endif
743
744#if defined(__clang__) && defined(__has_builtin)
745#if __has_builtin(__builtin_bswap32) && \
746 __has_builtin(__builtin_bswap64)
747#define have_bswap
748#endif
749#endif
750
Hanno Beckerf8720072018-11-08 11:53:49 +0000751#if defined(have_bswap)
752 /* The compiler is hopefully able to statically evaluate this! */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100753 switch (sizeof(mbedtls_mpi_uint)) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000754 case 4:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100755 return __builtin_bswap32(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000756 case 8:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100757 return __builtin_bswap64(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000758 }
759#endif
760#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
761#endif /* __BYTE_ORDER__ */
762
763 /* Fall back to C-based reordering if we don't know the byte order
764 * or we couldn't use a compiler-specific builtin. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100765 return mpi_uint_bigendian_to_host_c(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000766}
767
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100768static void mpi_bigendian_to_host(mbedtls_mpi_uint * const p, size_t limbs)
Hanno Beckerda1655a2017-10-18 14:21:44 +0100769{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100770 mbedtls_mpi_uint *cur_limb_left;
771 mbedtls_mpi_uint *cur_limb_right;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100772 if (limbs == 0) {
Hanno Becker2be8a552018-10-25 12:40:09 +0100773 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100774 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100775
776 /*
777 * Traverse limbs and
778 * - adapt byte-order in each limb
779 * - swap the limbs themselves.
780 * For that, simultaneously traverse the limbs from left to right
781 * and from right to left, as long as the left index is not bigger
782 * than the right index (it's not a problem if limbs is odd and the
783 * indices coincide in the last iteration).
784 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100785 for (cur_limb_left = p, cur_limb_right = p + (limbs - 1);
Hanno Beckerda1655a2017-10-18 14:21:44 +0100786 cur_limb_left <= cur_limb_right;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100787 cur_limb_left++, cur_limb_right--) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000788 mbedtls_mpi_uint tmp;
789 /* Note that if cur_limb_left == cur_limb_right,
790 * this code effectively swaps the bytes only once. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100791 tmp = mpi_uint_bigendian_to_host(*cur_limb_left);
792 *cur_limb_left = mpi_uint_bigendian_to_host(*cur_limb_right);
Hanno Beckerf8720072018-11-08 11:53:49 +0000793 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100794 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100795}
796
Paul Bakker5121ce52009-01-03 21:22:43 +0000797/*
Janos Follatha778a942019-02-13 10:28:28 +0000798 * Import X from unsigned binary data, little endian
799 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100800int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
801 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000802{
Janos Follath24eed8d2019-11-22 13:21:35 +0000803 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000804 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100805 size_t const limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000806
807 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100808 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000809
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100810 for (i = 0; i < buflen; i++) {
Janos Follatha778a942019-02-13 10:28:28 +0000811 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100812 }
Janos Follatha778a942019-02-13 10:28:28 +0000813
814cleanup:
815
Janos Follath171a7ef2019-02-15 16:17:45 +0000816 /*
817 * This function is also used to import keys. However, wiping the buffers
818 * upon failure is not necessary because failure only can happen before any
819 * input is copied.
820 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100821 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000822}
823
824/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000825 * Import X from unsigned binary data, big endian
826 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100827int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000828{
Janos Follath24eed8d2019-11-22 13:21:35 +0000829 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100830 size_t const limbs = CHARS_TO_LIMBS(buflen);
831 size_t const overhead = (limbs * ciL) - buflen;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100832 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000833
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100834 MPI_VALIDATE_RET(X != NULL);
835 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000836
Hanno Becker073c1992017-10-17 15:17:27 +0100837 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100838 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000839
Gilles Peskine3130ce22021-06-02 22:17:52 +0200840 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000841 * even if buflen is 0. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100842 if (buflen != 0) {
843 Xp = (unsigned char *) X->p;
844 memcpy(Xp + overhead, buf, buflen);
Hanno Beckerda1655a2017-10-18 14:21:44 +0100845
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100846 mpi_bigendian_to_host(X->p, limbs);
Hanno Becker0e810b92019-01-03 17:13:11 +0000847 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000848
849cleanup:
850
Janos Follath171a7ef2019-02-15 16:17:45 +0000851 /*
852 * This function is also used to import keys. However, wiping the buffers
853 * upon failure is not necessary because failure only can happen before any
854 * input is copied.
855 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100856 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000857}
858
859/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000860 * Export X into unsigned binary data, little endian
861 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100862int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
863 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000864{
865 size_t stored_bytes = X->n * ciL;
866 size_t bytes_to_copy;
867 size_t i;
868
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100869 if (stored_bytes < buflen) {
Janos Follathe344d0f2019-02-19 16:17:40 +0000870 bytes_to_copy = stored_bytes;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100871 } else {
Janos Follathe344d0f2019-02-19 16:17:40 +0000872 bytes_to_copy = buflen;
873
874 /* The output buffer is smaller than the allocated size of X.
875 * However X may fit if its leading bytes are zero. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100876 for (i = bytes_to_copy; i < stored_bytes; i++) {
877 if (GET_BYTE(X, i) != 0) {
878 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
879 }
Janos Follathe344d0f2019-02-19 16:17:40 +0000880 }
881 }
882
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100883 for (i = 0; i < bytes_to_copy; i++) {
884 buf[i] = GET_BYTE(X, i);
Janos Follathe344d0f2019-02-19 16:17:40 +0000885 }
886
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100887 if (stored_bytes < buflen) {
888 /* Write trailing 0 bytes */
889 memset(buf + stored_bytes, 0, buflen - stored_bytes);
890 }
891
892 return 0;
Janos Follathe344d0f2019-02-19 16:17:40 +0000893}
894
895/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 * Export X into unsigned binary data, big endian
897 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100898int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
899 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000900{
Hanno Becker73d7d792018-12-11 10:35:51 +0000901 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100902 size_t bytes_to_copy;
903 unsigned char *p;
904 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100906 MPI_VALIDATE_RET(X != NULL);
907 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000908
909 stored_bytes = X->n * ciL;
910
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100911 if (stored_bytes < buflen) {
Gilles Peskine11cdb052018-11-20 16:47:47 +0100912 /* There is enough space in the output buffer. Write initial
913 * null bytes and record the position at which to start
914 * writing the significant bytes. In this case, the execution
915 * trace of this function does not depend on the value of the
916 * number. */
917 bytes_to_copy = stored_bytes;
918 p = buf + buflen - stored_bytes;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100919 memset(buf, 0, buflen - stored_bytes);
920 } else {
Gilles Peskine11cdb052018-11-20 16:47:47 +0100921 /* The output buffer is smaller than the allocated size of X.
922 * However X may fit if its leading bytes are zero. */
923 bytes_to_copy = buflen;
924 p = buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100925 for (i = bytes_to_copy; i < stored_bytes; i++) {
926 if (GET_BYTE(X, i) != 0) {
927 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
928 }
Gilles Peskine11cdb052018-11-20 16:47:47 +0100929 }
930 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000931
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100932 for (i = 0; i < bytes_to_copy; i++) {
933 p[bytes_to_copy - i - 1] = GET_BYTE(X, i);
934 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000935
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100936 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000937}
938
939/*
940 * Left-shift: X <<= count
941 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100942int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000943{
Janos Follath24eed8d2019-11-22 13:21:35 +0000944 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000945 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946 mbedtls_mpi_uint r0 = 0, r1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100947 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000948
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100949 v0 = count / (biL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000950 t1 = count & (biL - 1);
951
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100952 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000953
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100954 if (X->n * biL < i) {
955 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
956 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000957
958 ret = 0;
959
960 /*
961 * shift by count / limb_size
962 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100963 if (v0 > 0) {
964 for (i = X->n; i > v0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +0000965 X->p[i - 1] = X->p[i - v0 - 1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100966 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000967
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100968 for (; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +0000969 X->p[i - 1] = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100970 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000971 }
972
973 /*
974 * shift by count % limb_size
975 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100976 if (t1 > 0) {
977 for (i = v0; i < X->n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 r1 = X->p[i] >> (biL - t1);
979 X->p[i] <<= t1;
980 X->p[i] |= r0;
981 r0 = r1;
982 }
983 }
984
985cleanup:
986
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100987 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000988}
989
990/*
991 * Right-shift: X >>= count
992 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100993int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000994{
Paul Bakker23986e52011-04-24 08:57:21 +0000995 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200996 mbedtls_mpi_uint r0 = 0, r1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100997 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000998
999 v0 = count / biL;
1000 v1 = count & (biL - 1);
1001
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001002 if (v0 > X->n || (v0 == X->n && v1 > 0)) {
1003 return mbedtls_mpi_lset(X, 0);
1004 }
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001005
Paul Bakker5121ce52009-01-03 21:22:43 +00001006 /*
1007 * shift by count / limb_size
1008 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001009 if (v0 > 0) {
1010 for (i = 0; i < X->n - v0; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001011 X->p[i] = X->p[i + v0];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001012 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001013
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001014 for (; i < X->n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001015 X->p[i] = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001016 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 }
1018
1019 /*
1020 * shift by count % limb_size
1021 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001022 if (v1 > 0) {
1023 for (i = X->n; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001024 r1 = X->p[i - 1] << (biL - v1);
1025 X->p[i - 1] >>= v1;
1026 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 r0 = r1;
1028 }
1029 }
1030
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001031 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001032}
1033
1034/*
1035 * Compare unsigned values
1036 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001037int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001038{
Paul Bakker23986e52011-04-24 08:57:21 +00001039 size_t i, j;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001040 MPI_VALIDATE_RET(X != NULL);
1041 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001043 for (i = X->n; i > 0; i--) {
1044 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001045 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001046 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 }
1048
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001049 for (j = Y->n; j > 0; j--) {
1050 if (Y->p[j - 1] != 0) {
1051 break;
1052 }
1053 }
1054
1055 if (i == 0 && j == 0) {
1056 return 0;
1057 }
1058
1059 if (i > j) {
1060 return 1;
1061 }
1062 if (j > i) {
1063 return -1;
1064 }
1065
1066 for (; i > 0; i--) {
1067 if (X->p[i - 1] > Y->p[i - 1]) {
1068 return 1;
1069 }
1070 if (X->p[i - 1] < Y->p[i - 1]) {
1071 return -1;
1072 }
1073 }
1074
1075 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001076}
1077
1078/*
1079 * Compare signed values
1080 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001081int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001082{
Paul Bakker23986e52011-04-24 08:57:21 +00001083 size_t i, j;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001084 MPI_VALIDATE_RET(X != NULL);
1085 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001086
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001087 for (i = X->n; i > 0; i--) {
1088 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001089 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001090 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 }
1092
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001093 for (j = Y->n; j > 0; j--) {
1094 if (Y->p[j - 1] != 0) {
1095 break;
1096 }
1097 }
1098
1099 if (i == 0 && j == 0) {
1100 return 0;
1101 }
1102
1103 if (i > j) {
1104 return X->s;
1105 }
1106 if (j > i) {
1107 return -Y->s;
1108 }
1109
1110 if (X->s > 0 && Y->s < 0) {
1111 return 1;
1112 }
1113 if (Y->s > 0 && X->s < 0) {
1114 return -1;
1115 }
1116
1117 for (; i > 0; i--) {
1118 if (X->p[i - 1] > Y->p[i - 1]) {
1119 return X->s;
1120 }
1121 if (X->p[i - 1] < Y->p[i - 1]) {
1122 return -X->s;
1123 }
1124 }
1125
1126 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001127}
1128
Janos Follathee6abce2019-09-05 14:47:19 +01001129/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 * Compare signed values
1131 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001132int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +00001133{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001134 mbedtls_mpi Y;
1135 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001136 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001137
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001138 *p = mpi_sint_abs(z);
1139 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 Y.n = 1;
1141 Y.p = p;
1142
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001143 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00001144}
1145
1146/*
1147 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1148 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001149int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001150{
Janos Follath24eed8d2019-11-22 13:21:35 +00001151 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001152 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001153 mbedtls_mpi_uint *o, *p, c, tmp;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001154 MPI_VALIDATE_RET(X != NULL);
1155 MPI_VALIDATE_RET(A != NULL);
1156 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001157
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001158 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001159 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001160 }
1161
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001162 if (X != A) {
1163 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1164 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001165
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001166 /*
1167 * X should always be positive as a result of unsigned additions.
1168 */
1169 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001170
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001171 for (j = B->n; j > 0; j--) {
1172 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001173 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001174 }
1175 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001176
Gilles Peskine103cf592022-11-15 22:59:00 +01001177 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1178 * and B is 0 (of any size). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001179 if (j == 0) {
1180 return 0;
1181 }
Gilles Peskine103cf592022-11-15 22:59:00 +01001182
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001183 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
1185 o = B->p; p = X->p; c = 0;
1186
Janos Follath6c922682015-10-30 17:43:11 +01001187 /*
1188 * tmp is used because it might happen that p == o
1189 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001190 for (i = 0; i < j; i++, o++, p++) {
1191 tmp = *o;
1192 *p += c; c = (*p < c);
1193 *p += tmp; c += (*p < tmp);
Paul Bakker5121ce52009-01-03 21:22:43 +00001194 }
1195
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001196 while (c != 0) {
1197 if (i >= X->n) {
1198 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001199 p = X->p + i;
1200 }
1201
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001202 *p += c; c = (*p < c); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 }
1204
1205cleanup:
1206
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001207 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001208}
1209
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001210/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001211 * Helper for mbedtls_mpi subtraction.
1212 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001213 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001214 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001215 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001216 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001217 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001218 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001219 * \param n Number of limbs of \p d, \p l and \p r.
1220 * \param[out] d The result of the subtraction.
1221 * \param[in] l The left operand.
1222 * \param[in] r The right operand.
1223 *
1224 * \return 1 if `l < r`.
1225 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001226 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001227static mbedtls_mpi_uint mpi_sub_hlp(size_t n,
1228 mbedtls_mpi_uint *d,
1229 const mbedtls_mpi_uint *l,
1230 const mbedtls_mpi_uint *r)
Paul Bakker5121ce52009-01-03 21:22:43 +00001231{
Paul Bakker23986e52011-04-24 08:57:21 +00001232 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001233 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001234
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001235 for (i = 0; i < n; i++) {
1236 z = (l[i] < c); t = l[i] - c;
1237 c = (t < r[i]) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 }
1239
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001240 return c;
Paul Bakker5121ce52009-01-03 21:22:43 +00001241}
1242
1243/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001244 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001245 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001246int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001247{
Janos Follath24eed8d2019-11-22 13:21:35 +00001248 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001249 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001250 mbedtls_mpi_uint carry;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001251 MPI_VALIDATE_RET(X != NULL);
1252 MPI_VALIDATE_RET(A != NULL);
1253 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001254
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001255 for (n = B->n; n > 0; n--) {
1256 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001257 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001258 }
1259 }
1260 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001261 /* B >= (2^ciL)^n > A */
1262 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1263 goto cleanup;
1264 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001265
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001266 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001267
1268 /* Set the high limbs of X to match A. Don't touch the lower limbs
1269 * because X might be aliased to B, and we must not overwrite the
1270 * significant digits of B. */
Aaron M. Ucko78b823a2023-01-31 15:45:44 -05001271 if (A->n > n && A != X) {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001272 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1273 }
1274 if (X->n > A->n) {
1275 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1276 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001277
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001278 carry = mpi_sub_hlp(n, X->p, A->p, B->p);
1279 if (carry != 0) {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001280 /* Propagate the carry to the first nonzero limb of X. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001281 for (; n < X->n && X->p[n] == 0; n++) {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001282 --X->p[n];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001283 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001284 /* If we ran out of space for the carry, it means that the result
1285 * is negative. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001286 if (n == X->n) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001287 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1288 goto cleanup;
1289 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001290 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001291 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001292
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001293 /* X should always be positive as a result of unsigned subtractions. */
1294 X->s = 1;
1295
Paul Bakker5121ce52009-01-03 21:22:43 +00001296cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001297 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001298}
1299
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001300/* Common function for signed addition and subtraction.
1301 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001302 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001303static int add_sub_mpi(mbedtls_mpi *X,
1304 const mbedtls_mpi *A, const mbedtls_mpi *B,
1305 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001306{
Hanno Becker73d7d792018-12-11 10:35:51 +00001307 int ret, s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001308 MPI_VALIDATE_RET(X != NULL);
1309 MPI_VALIDATE_RET(A != NULL);
1310 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001311
Hanno Becker73d7d792018-12-11 10:35:51 +00001312 s = A->s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001313 if (A->s * B->s * flip_B < 0) {
1314 int cmp = mbedtls_mpi_cmp_abs(A, B);
1315 if (cmp >= 0) {
1316 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine581c4602022-11-09 22:02:16 +01001317 /* If |A| = |B|, the result is 0 and we must set the sign bit
1318 * to +1 regardless of which of A or B was negative. Otherwise,
1319 * since |A| > |B|, the sign is the sign of A. */
1320 X->s = cmp == 0 ? 1 : s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001321 } else {
1322 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine581c4602022-11-09 22:02:16 +01001323 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001324 X->s = -s;
1325 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001326 } else {
1327 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001328 X->s = s;
1329 }
1330
1331cleanup:
1332
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001333 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001334}
1335
1336/*
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001337 * Signed addition: X = A + B
1338 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001339int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001340{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001341 return add_sub_mpi(X, A, B, 1);
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001342}
1343
1344/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001345 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001346 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001347int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001348{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001349 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001350}
1351
1352/*
1353 * Signed addition: X = A + b
1354 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001355int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001356{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001357 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001359 MPI_VALIDATE_RET(X != NULL);
1360 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001362 p[0] = mpi_sint_abs(b);
1363 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001364 B.n = 1;
1365 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001366
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001367 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001368}
1369
1370/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001371 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001372 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001373int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001374{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001375 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001377 MPI_VALIDATE_RET(X != NULL);
1378 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001379
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001380 p[0] = mpi_sint_abs(b);
1381 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001382 B.n = 1;
1383 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001385 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001386}
1387
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001388/** Helper for mbedtls_mpi multiplication.
1389 *
1390 * Add \p b * \p s to \p d.
1391 *
1392 * \param i The number of limbs of \p s.
1393 * \param[in] s A bignum to multiply, of size \p i.
1394 * It may overlap with \p d, but only if
1395 * \p d <= \p s.
1396 * Its leading limb must not be \c 0.
1397 * \param[in,out] d The bignum to add to.
1398 * It must be sufficiently large to store the
1399 * result of the multiplication. This means
1400 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1401 * is not known a priori.
1402 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001403 */
1404static
1405#if defined(__APPLE__) && defined(__arm__)
1406/*
1407 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1408 * appears to need this to prevent bad ARM code generation at -O3.
1409 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001410__attribute__((noinline))
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001411#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001412void mpi_mul_hlp(size_t i,
1413 const mbedtls_mpi_uint *s,
1414 mbedtls_mpi_uint *d,
1415 mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001416{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417 mbedtls_mpi_uint c = 0, t = 0;
Gilles Peskined7848332023-02-24 12:08:01 +01001418 (void) t; /* Unused in some architectures */
Paul Bakker5121ce52009-01-03 21:22:43 +00001419
1420#if defined(MULADDC_HUIT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001421 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001422 MULADDC_INIT
1423 MULADDC_HUIT
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001424 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 }
1426
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001427 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001428 MULADDC_INIT
1429 MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001430 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001431 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001432#else /* MULADDC_HUIT */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001433 for (; i >= 16; i -= 16) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 MULADDC_INIT
1435 MULADDC_CORE MULADDC_CORE
1436 MULADDC_CORE MULADDC_CORE
1437 MULADDC_CORE MULADDC_CORE
1438 MULADDC_CORE MULADDC_CORE
1439
1440 MULADDC_CORE MULADDC_CORE
1441 MULADDC_CORE MULADDC_CORE
1442 MULADDC_CORE MULADDC_CORE
1443 MULADDC_CORE MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001444 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001445 }
1446
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001447 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001448 MULADDC_INIT
1449 MULADDC_CORE MULADDC_CORE
1450 MULADDC_CORE MULADDC_CORE
1451
1452 MULADDC_CORE MULADDC_CORE
1453 MULADDC_CORE MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001454 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001455 }
1456
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001457 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001458 MULADDC_INIT
1459 MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001460 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001462#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001463
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001464 while (c != 0) {
1465 *d += c; c = (*d < c); d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001466 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001467}
1468
1469/*
1470 * Baseline multiplication: X = A * B (HAC 14.12)
1471 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001472int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001473{
Janos Follath24eed8d2019-11-22 13:21:35 +00001474 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001475 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 mbedtls_mpi TA, TB;
Gilles Peskined65b5002021-06-15 21:44:32 +02001477 int result_is_zero = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001478 MPI_VALIDATE_RET(X != NULL);
1479 MPI_VALIDATE_RET(A != NULL);
1480 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001482 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001484 if (X == A) {
1485 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1486 }
1487 if (X == B) {
1488 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1489 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001491 for (i = A->n; i > 0; i--) {
1492 if (A->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001493 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001494 }
1495 }
1496 if (i == 0) {
Gilles Peskined65b5002021-06-15 21:44:32 +02001497 result_is_zero = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001498 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001499
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001500 for (j = B->n; j > 0; j--) {
1501 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001503 }
1504 }
1505 if (j == 0) {
Gilles Peskined65b5002021-06-15 21:44:32 +02001506 result_is_zero = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001507 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001509 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1510 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001511
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001512 for (; j > 0; j--) {
1513 mpi_mul_hlp(i, A->p, X->p + j - 1, B->p[j - 1]);
1514 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001515
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001516 /* If the result is 0, we don't shortcut the operation, which reduces
1517 * but does not eliminate side channels leaking the zero-ness. We do
1518 * need to take care to set the sign bit properly since the library does
1519 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001520 if (result_is_zero) {
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001521 X->s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001522 } else {
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001523 X->s = A->s * B->s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001524 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001525
1526cleanup:
1527
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001528 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001529
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001530 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001531}
1532
1533/*
1534 * Baseline multiplication: X = A * b
1535 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001536int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001537{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001538 MPI_VALIDATE_RET(X != NULL);
1539 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001541 /* mpi_mul_hlp can't deal with a leading 0. */
1542 size_t n = A->n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001543 while (n > 0 && A->p[n - 1] == 0) {
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001544 --n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001545 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001546
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001547 /* The general method below doesn't work if n==0 or b==0. By chance
1548 * calculating the result is trivial in those cases. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001549 if (b == 0 || n == 0) {
1550 return mbedtls_mpi_lset(X, 0);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001551 }
1552
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001553 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001554 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001555 /* In general, A * b requires 1 limb more than b. If
1556 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1557 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001558 * copy() will take care of the growth if needed. However, experimentally,
1559 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001560 * calls to calloc() in ECP code, presumably because it reuses the
1561 * same mpi for a while and this way the mpi is more likely to directly
1562 * grow to its final size. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001563 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1564 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1565 mpi_mul_hlp(n, A->p, X->p, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001566
1567cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001568 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001569}
1570
1571/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001572 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1573 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001574 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001575static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1576 mbedtls_mpi_uint u0,
1577 mbedtls_mpi_uint d,
1578 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001579{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001580#if defined(MBEDTLS_HAVE_UDBL)
1581 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001582#else
Simon Butcher9803d072016-01-03 00:24:34 +00001583 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001584 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001585 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1586 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001587 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001588#endif
1589
Simon Butcher15b15d12015-11-26 19:35:03 +00001590 /*
1591 * Check for overflow
1592 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001593 if (0 == d || u1 >= d) {
1594 if (r != NULL) {
1595 *r = ~(mbedtls_mpi_uint) 0u;
1596 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001597
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001598 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001599 }
1600
1601#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001602 dividend = (mbedtls_t_udbl) u1 << biL;
1603 dividend |= (mbedtls_t_udbl) u0;
1604 quotient = dividend / d;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001605 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1606 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1607 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001608
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001609 if (r != NULL) {
1610 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1611 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001612
1613 return (mbedtls_mpi_uint) quotient;
1614#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001615
1616 /*
1617 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1618 * Vol. 2 - Seminumerical Algorithms, Knuth
1619 */
1620
1621 /*
1622 * Normalize the divisor, d, and dividend, u0, u1
1623 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001624 s = mbedtls_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001625 d = d << s;
1626
1627 u1 = u1 << s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001628 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001629 u0 = u0 << s;
1630
1631 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001632 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001633
1634 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001635 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001636
1637 /*
1638 * Find the first quotient and remainder
1639 */
1640 q1 = u1 / d1;
1641 r0 = u1 - d1 * q1;
1642
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001643 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001644 q1 -= 1;
1645 r0 += d1;
1646
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001647 if (r0 >= radix) {
1648 break;
1649 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001650 }
1651
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001652 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001653 q0 = rAX / d1;
1654 r0 = rAX - q0 * d1;
1655
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001656 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001657 q0 -= 1;
1658 r0 += d1;
1659
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001660 if (r0 >= radix) {
1661 break;
1662 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001663 }
1664
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001665 if (r != NULL) {
1666 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1667 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001668
1669 quotient = q1 * radix + q0;
1670
1671 return quotient;
1672#endif
1673}
1674
1675/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001677 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001678int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1679 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001680{
Janos Follath24eed8d2019-11-22 13:21:35 +00001681 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001682 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001684 mbedtls_mpi_uint TP2[3];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001685 MPI_VALIDATE_RET(A != NULL);
1686 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001688 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1689 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1690 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001692 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1693 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001694 /*
1695 * Avoid dynamic memory allocations for constant-size T2.
1696 *
1697 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1698 * so nobody increase the size of the MPI and we're safe to use an on-stack
1699 * buffer.
1700 */
Alexander K35d6d462019-10-31 14:46:45 +03001701 T2.s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001702 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001703 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001705 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1706 if (Q != NULL) {
1707 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1708 }
1709 if (R != NULL) {
1710 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1711 }
1712 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001713 }
1714
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001715 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1716 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001717 X.s = Y.s = 1;
1718
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001719 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1720 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1721 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001722
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001723 k = mbedtls_mpi_bitlen(&Y) % biL;
1724 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001725 k = biL - 1 - k;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001726 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1727 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1728 } else {
1729 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001730 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001731
1732 n = X.n - 1;
1733 t = Y.n - 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001734 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001735
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001736 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001737 Z.p[n - t]++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001738 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001740 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001741
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001742 for (i = n; i > t; i--) {
1743 if (X.p[i] >= Y.p[t]) {
1744 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1745 } else {
1746 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1747 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001748 }
1749
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001750 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1751 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001752 T2.p[2] = X.p[i];
1753
Paul Bakker5121ce52009-01-03 21:22:43 +00001754 Z.p[i - t - 1]++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001755 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 Z.p[i - t - 1]--;
1757
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001758 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1759 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 T1.p[1] = Y.p[t];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001761 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1762 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001763
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001764 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1765 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1766 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001768 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1769 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1770 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1771 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001772 Z.p[i - t - 1]--;
1773 }
1774 }
1775
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001776 if (Q != NULL) {
1777 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 Q->s = A->s * B->s;
1779 }
1780
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001781 if (R != NULL) {
1782 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001783 X.s = A->s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001784 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001786 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001787 R->s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001788 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001789 }
1790
1791cleanup:
1792
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001793 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1794 mbedtls_mpi_free(&T1);
1795 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001797 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001798}
1799
1800/*
1801 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001802 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001803int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1804 const mbedtls_mpi *A,
1805 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001806{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001807 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001809 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001811 p[0] = mpi_sint_abs(b);
1812 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001813 B.n = 1;
1814 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001816 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001817}
1818
1819/*
1820 * Modulo: R = A mod B
1821 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001822int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001823{
Janos Follath24eed8d2019-11-22 13:21:35 +00001824 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001825 MPI_VALIDATE_RET(R != NULL);
1826 MPI_VALIDATE_RET(A != NULL);
1827 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001829 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1830 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1831 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001832
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001833 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001834
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001835 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1836 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1837 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001838
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001839 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1840 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1841 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001842
1843cleanup:
1844
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001845 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001846}
1847
1848/*
1849 * Modulo: r = A mod b
1850 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001851int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001852{
Paul Bakker23986e52011-04-24 08:57:21 +00001853 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 mbedtls_mpi_uint x, y, z;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001855 MPI_VALIDATE_RET(r != NULL);
1856 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001857
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001858 if (b == 0) {
1859 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1860 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001861
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001862 if (b < 0) {
1863 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1864 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001865
1866 /*
1867 * handle trivial cases
1868 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001869 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001870 *r = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001871 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 }
1873
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001874 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 *r = A->p[0] & 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001876 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001877 }
1878
1879 /*
1880 * general case
1881 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001882 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001883 x = A->p[i - 1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001884 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 z = y / b;
1886 y -= z * b;
1887
1888 x <<= biH;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001889 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001890 z = y / b;
1891 y -= z * b;
1892 }
1893
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001894 /*
1895 * If A is negative, then the current y represents a negative value.
1896 * Flipping it to the positive side.
1897 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001898 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001899 y = b - y;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001900 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001901
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 *r = y;
1903
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001904 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001905}
1906
1907/*
1908 * Fast Montgomery initialization (thanks to Tom St Denis)
1909 */
Janos Follath8cdb6062024-01-09 09:28:48 +00001910mbedtls_mpi_uint mbedtls_mpi_montmul_init(const mbedtls_mpi_uint *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001911{
Janos Follath8cdb6062024-01-09 09:28:48 +00001912 mbedtls_mpi_uint x = N[0];
Paul Bakker5121ce52009-01-03 21:22:43 +00001913
Janos Follath8cdb6062024-01-09 09:28:48 +00001914 x += ((N[0] + 2) & 4) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
Janos Follath8cdb6062024-01-09 09:28:48 +00001916 for (unsigned int i = biL; i >= 8; i /= 2) {
1917 x *= (2 - (N[0] * x));
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001918 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001919
Janos Follath8cdb6062024-01-09 09:28:48 +00001920 return ~x + 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001921}
1922
Janos Follath4fe396f2024-01-08 14:08:17 +00001923void mbedtls_mpi_montmul(mbedtls_mpi *A,
1924 const mbedtls_mpi *B,
1925 const mbedtls_mpi *N,
1926 mbedtls_mpi_uint mm,
1927 const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001928{
Paul Bakker23986e52011-04-24 08:57:21 +00001929 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001930 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001931
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001932 memset(T->p, 0, T->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
1934 d = T->p;
1935 n = N->n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001936 m = (B->n < n) ? B->n : n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001938 for (i = 0; i < n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 /*
1940 * T = (T + u0*B + u1*N) / 2^biL
1941 */
1942 u0 = A->p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001943 u1 = (d[0] + u0 * B->p[0]) * mm;
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001945 mpi_mul_hlp(m, B->p, d, u0);
1946 mpi_mul_hlp(n, N->p, d, u1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001947
1948 *d++ = u0; d[n + 1] = 0;
1949 }
1950
Gilles Peskine221626f2020-06-08 22:37:50 +02001951 /* At this point, d is either the desired result or the desired result
1952 * plus N. We now potentially subtract N, avoiding leaking whether the
1953 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001954
Gilles Peskine221626f2020-06-08 22:37:50 +02001955 /* Copy the n least significant limbs of d to A, so that
1956 * A = d if d < N (recall that N has n limbs). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001957 memcpy(A->p, d, n * ciL);
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001958 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02001959 * do the calculation without using conditional tests. */
1960 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02001961 d[n] += 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001962 d[n] -= mpi_sub_hlp(n, d, d, N->p);
Gilles Peskine221626f2020-06-08 22:37:50 +02001963 /* If d0 < N then d < (2^biL)^n
1964 * so d[n] == 0 and we want to keep A as it is.
1965 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1966 * so d[n] == 1 and we want to set A to the result of the subtraction
1967 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1968 * This exactly corresponds to a conditional assignment. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001969 mbedtls_ct_mpi_uint_cond_assign(n, A->p, d, (unsigned char) d[n]);
Paul Bakker5121ce52009-01-03 21:22:43 +00001970}
1971
1972/*
1973 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001974 *
Janos Follath4fe396f2024-01-08 14:08:17 +00001975 * See mbedtls_mpi_montmul() regarding constraints and guarantees on the
1976 * parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001977 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001978static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1979 mbedtls_mpi_uint mm, const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001980{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 mbedtls_mpi_uint z = 1;
1982 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
Paul Bakker8ddb6452013-02-27 14:56:33 +01001984 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001985 U.p = &z;
1986
Janos Follath4fe396f2024-01-08 14:08:17 +00001987 mbedtls_mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001988}
1989
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01001990/**
1991 * Select an MPI from a table without leaking the index.
1992 *
1993 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1994 * reads the entire table in order to avoid leaking the value of idx to an
1995 * attacker able to observe memory access patterns.
1996 *
1997 * \param[out] R Where to write the selected MPI.
1998 * \param[in] T The table to read from.
1999 * \param[in] T_size The number of elements in the table.
2000 * \param[in] idx The index of the element to select;
2001 * this must satisfy 0 <= idx < T_size.
2002 *
2003 * \return \c 0 on success, or a negative error code.
2004 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002005static 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 +01002006{
2007 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2008
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002009 for (size_t i = 0; i < T_size; i++) {
2010 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
2011 (unsigned char) mbedtls_ct_size_bool_eq(i,
2012 idx)));
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002013 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002014
2015cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002016 return ret;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002017}
2018
Janos Follath42175032024-01-08 13:45:49 +00002019int mbedtls_mpi_get_mont_r2_unsafe(mbedtls_mpi *X,
2020 const mbedtls_mpi *N)
2021{
2022 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2023
2024 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1));
2025 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, N->n * 2 * biL));
2026 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
2027 MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(X, N->n));
2028
2029cleanup:
2030 return ret;
2031}
2032
Paul Bakker5121ce52009-01-03 21:22:43 +00002033/*
2034 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2035 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002036int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
2037 const mbedtls_mpi *E, const mbedtls_mpi *N,
2038 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00002039{
Janos Follath24eed8d2019-11-22 13:21:35 +00002040 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathd88e2192022-11-21 15:54:20 +00002041 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00002042 size_t i, j, nblimbs;
2043 size_t bufsize, nbits;
Paul Elliottfc820d92023-01-13 16:29:30 +00002044 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002046 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002047 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002048
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002049 MPI_VALIDATE_RET(X != NULL);
2050 MPI_VALIDATE_RET(A != NULL);
2051 MPI_VALIDATE_RET(E != NULL);
2052 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002053
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002054 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
2055 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2056 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002057
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002058 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
2059 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2060 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00002061
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002062 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
2063 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
2064 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2065 }
Chris Jones9246d042020-11-25 15:12:39 +00002066
Paul Bakkerf6198c12012-05-16 08:02:29 +00002067 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002068 * Init temps and window size
2069 */
Janos Follath8cdb6062024-01-09 09:28:48 +00002070 mm = mbedtls_mpi_montmul_init(N->p);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002071 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
2072 mbedtls_mpi_init(&Apos);
2073 mbedtls_mpi_init(&WW);
2074 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00002075
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002076 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00002077
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002078 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
2079 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002080
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002081#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
2082 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath66323832022-11-21 14:48:02 +00002083 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002084 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002085#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002086
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002087 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath6fa7a762022-11-22 10:18:06 +00002088
Paul Bakker5121ce52009-01-03 21:22:43 +00002089 /*
Janos Follath6e2d8e32022-11-21 16:14:54 +00002090 * This function is not constant-trace: its memory accesses depend on the
2091 * exponent value. To defend against timing attacks, callers (such as RSA
2092 * and DHM) should use exponent blinding. However this is not enough if the
2093 * adversary can find the exponent in a single trace, so this function
2094 * takes extra precautions against adversaries who can observe memory
2095 * access patterns.
Janos Follath3a3c50c2022-11-11 15:56:38 +00002096 *
Janos Follath6e2d8e32022-11-21 16:14:54 +00002097 * This function performs a series of multiplications by table elements and
2098 * squarings, and we want the prevent the adversary from finding out which
2099 * table element was used, and from distinguishing between multiplications
2100 * and squarings. Firstly, when multiplying by an element of the window
2101 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
2102 * squarings as having a different memory access patterns from other
Gilles Peskine20d54e32023-08-10 15:59:28 +02002103 * multiplications. So secondly, we put the accumulator in the table as
2104 * well, and also do a constant-trace table lookup to multiply by the
2105 * accumulator which is W[x_index].
Janos Follath6e2d8e32022-11-21 16:14:54 +00002106 *
2107 * This way, all multiplications take the form of a lookup-and-multiply.
2108 * The number of lookup-and-multiply operations inside each iteration of
2109 * the main loop still depends on the bits of the exponent, but since the
2110 * other operations in the loop don't have an easily recognizable memory
2111 * trace, an adversary is unlikely to be able to observe the exact
2112 * patterns.
2113 *
2114 * An adversary may still be able to recover the exponent if they can
2115 * observe both memory accesses and branches. However, branch prediction
2116 * exploitation typically requires many traces of execution over the same
2117 * data, which is defeated by randomized blinding.
Janos Follath91c02862022-10-04 13:27:40 +01002118 */
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002119 const size_t x_index = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002120 mbedtls_mpi_init(&W[x_index]);
Janos Follathf0ceb1c2022-11-21 14:31:22 +00002121
2122 j = N->n + 1;
Gilles Peskine20d54e32023-08-10 15:59:28 +02002123 /* All W[i] including the accumulator must have at least N->n limbs for
Janos Follath4fe396f2024-01-08 14:08:17 +00002124 * the mbedtls_mpi_montmul() and mpi_montred() calls later. Here we ensure
2125 * that W[1] and the accumulator W[x_index] are large enough. later we'll
2126 * grow other W[i] to the same length. They must not be shrunk midway
2127 * through this function!
Janos Follath3a3c50c2022-11-11 15:56:38 +00002128 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002129 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
2130 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
2131 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Janos Follath91c02862022-10-04 13:27:40 +01002132
2133 /*
Paul Bakker50546922012-05-19 08:40:49 +00002134 * Compensate for negative A (and correct at the end)
2135 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002136 neg = (A->s == -1);
2137 if (neg) {
2138 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00002139 Apos.s = 1;
2140 A = &Apos;
2141 }
2142
2143 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002144 * If 1st call, pre-compute R^2 mod N
2145 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002146 if (prec_RR == NULL || prec_RR->p == NULL) {
Janos Follath42175032024-01-08 13:45:49 +00002147 mbedtls_mpi_get_mont_r2_unsafe(&RR, N);
Paul Bakker5121ce52009-01-03 21:22:43 +00002148
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002149 if (prec_RR != NULL) {
2150 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
2151 }
2152 } else {
2153 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00002154 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
2156 /*
2157 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2158 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002159 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
2160 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002161 /* This should be a no-op because W[1] is already that large before
2162 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Janos Follath4fe396f2024-01-08 14:08:17 +00002163 * in mbedtls_mpi_montmul() below, so let's make sure. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002164 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
2165 } else {
2166 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002167 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002168
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002169 /* Note that this is safe because W[1] always has at least N->n limbs
2170 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Janos Follath4fe396f2024-01-08 14:08:17 +00002171 mbedtls_mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
2173 /*
Janos Follath91c02862022-10-04 13:27:40 +01002174 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002175 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002176 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
2177 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002179
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002180 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002181 /*
Janos Follathd88e2192022-11-21 15:54:20 +00002182 * W[i] = W[1] ^ i
2183 *
2184 * The first bit of the sliding window is always 1 and therefore we
2185 * only need to store the second half of the table.
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002186 *
2187 * (There are two special elements in the table: W[0] for the
2188 * accumulator/result and W[1] for A in Montgomery form. Both of these
2189 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 */
Janos Follathd88e2192022-11-21 15:54:20 +00002191 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002192
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002193 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
2194 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002195
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002196 for (i = 0; i < window_bitsize - 1; i++) {
Janos Follath4fe396f2024-01-08 14:08:17 +00002197 mbedtls_mpi_montmul(&W[j], &W[j], N, mm, &T);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002198 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01002199
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 /*
2201 * W[i] = W[i - 1] * W[1]
2202 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002203 for (i = j + 1; i < w_table_used_size; i++) {
2204 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
2205 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002206
Janos Follath4fe396f2024-01-08 14:08:17 +00002207 mbedtls_mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002208 }
2209 }
2210
2211 nblimbs = E->n;
2212 bufsize = 0;
2213 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002214 state = 0;
2215
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002216 while (1) {
2217 if (bufsize == 0) {
2218 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002219 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002220 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002221
Paul Bakker0d7702c2013-10-29 16:18:35 +01002222 nblimbs--;
2223
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002224 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002225 }
2226
2227 bufsize--;
2228
2229 ei = (E->p[nblimbs] >> bufsize) & 1;
2230
2231 /*
2232 * skip leading 0s
2233 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002234 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002235 continue;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002236 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002238 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002239 /*
Janos Follath91c02862022-10-04 13:27:40 +01002240 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00002241 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002242 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
Janos Follath4fe396f2024-01-08 14:08:17 +00002243 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 continue;
2245 }
2246
2247 /*
2248 * add ei to current window
2249 */
2250 state = 2;
2251
2252 nbits++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002253 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002255 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002256 /*
Janos Follath66323832022-11-21 14:48:02 +00002257 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002258 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002259 for (i = 0; i < window_bitsize; i++) {
2260 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
2261 x_index));
Janos Follath4fe396f2024-01-08 14:08:17 +00002262 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follath95655a22022-10-04 14:00:09 +01002263 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002264
2265 /*
Janos Follath66323832022-11-21 14:48:02 +00002266 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002268 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
2269 exponent_bits_in_window));
Janos Follath4fe396f2024-01-08 14:08:17 +00002270 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002271
2272 state--;
2273 nbits = 0;
Janos Follath66323832022-11-21 14:48:02 +00002274 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002275 }
2276 }
2277
2278 /*
2279 * process the remaining bits
2280 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002281 for (i = 0; i < nbits; i++) {
2282 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
Janos Follath4fe396f2024-01-08 14:08:17 +00002283 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
Janos Follath66323832022-11-21 14:48:02 +00002285 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002287 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
2288 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
Janos Follath4fe396f2024-01-08 14:08:17 +00002289 mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follath95655a22022-10-04 14:00:09 +01002290 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002291 }
2292
2293 /*
Janos Follath91c02862022-10-04 13:27:40 +01002294 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002295 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002296 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002298 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath91c02862022-10-04 13:27:40 +01002299 W[x_index].s = -1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002300 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00002301 }
2302
Janos Follath91c02862022-10-04 13:27:40 +01002303 /*
2304 * Load the result in the output variable.
2305 */
Chien Wong0118a1d2023-08-01 21:38:46 +08002306 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
Janos Follath91c02862022-10-04 13:27:40 +01002307
Paul Bakker5121ce52009-01-03 21:22:43 +00002308cleanup:
2309
Janos Follatha92f9152022-11-21 15:05:31 +00002310 /* The first bit of the sliding window is always 1 and therefore the first
2311 * half of the table was unused. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002312 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
2313 mbedtls_mpi_free(&W[i]);
2314 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002316 mbedtls_mpi_free(&W[x_index]);
2317 mbedtls_mpi_free(&W[1]);
2318 mbedtls_mpi_free(&T);
2319 mbedtls_mpi_free(&Apos);
2320 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00002321
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002322 if (prec_RR == NULL || prec_RR->p == NULL) {
2323 mbedtls_mpi_free(&RR);
2324 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002326 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002327}
2328
Paul Bakker5121ce52009-01-03 21:22:43 +00002329/*
2330 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2331 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002332int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002333{
Janos Follath24eed8d2019-11-22 13:21:35 +00002334 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002335 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002336 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002338 MPI_VALIDATE_RET(G != NULL);
2339 MPI_VALIDATE_RET(A != NULL);
2340 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002341
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002342 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002344 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2345 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002347 lz = mbedtls_mpi_lsb(&TA);
2348 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002349
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002350 /* The loop below gives the correct result when A==0 but not when B==0.
2351 * So have a special case for B==0. Leverage the fact that we just
2352 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2353 * slightly more efficient than cmp_int(). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002354 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
2355 ret = mbedtls_mpi_copy(G, A);
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002356 goto cleanup;
2357 }
2358
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002359 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002360 lz = lzt;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002361 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002362
Paul Bakker5121ce52009-01-03 21:22:43 +00002363 TA.s = TB.s = 1;
2364
Gilles Peskineea9aa142021-06-16 13:42:04 +02002365 /* We mostly follow the procedure described in HAC 14.54, but with some
2366 * minor differences:
2367 * - Sequences of multiplications or divisions by 2 are grouped into a
2368 * single shift operation.
Gilles Peskine37d690c2021-06-21 18:58:39 +02002369 * - The procedure in HAC assumes that 0 < TB <= TA.
2370 * - The condition TB <= TA is not actually necessary for correctness.
2371 * TA and TB have symmetric roles except for the loop termination
2372 * condition, and the shifts at the beginning of the loop body
2373 * remove any significance from the ordering of TA vs TB before
2374 * the shifts.
2375 * - If TA = 0, the loop goes through 0 iterations and the result is
2376 * correctly TB.
2377 * - The case TB = 0 was short-circuited above.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002378 *
2379 * For the correctness proof below, decompose the original values of
2380 * A and B as
2381 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2382 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2383 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2384 * and gcd(A',B') is odd or 0.
2385 *
2386 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2387 * The code maintains the following invariant:
2388 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine6537bdb2021-06-15 22:09:39 +02002389 */
2390
Gilles Peskineea9aa142021-06-16 13:42:04 +02002391 /* Proof that the loop terminates:
2392 * At each iteration, either the right-shift by 1 is made on a nonzero
2393 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2394 * by at least 1, or the right-shift by 1 is made on zero and then
2395 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2396 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2397 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002398 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskineea9aa142021-06-16 13:42:04 +02002399 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002400 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2401 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
Gilles Peskineea9aa142021-06-16 13:42:04 +02002403 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2404 * TA-TB is even so the division by 2 has an integer result.
2405 * Invariant (I) is preserved since any odd divisor of both TA and TB
2406 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case0e7791f2021-12-20 21:14:10 -08002407 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskineea9aa142021-06-16 13:42:04 +02002408 * divides TA.
2409 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002410 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2411 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2412 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2413 } else {
2414 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2415 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002416 }
Gilles Peskineea9aa142021-06-16 13:42:04 +02002417 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002418 }
2419
Gilles Peskineea9aa142021-06-16 13:42:04 +02002420 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2421 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2422 * - If there was at least one loop iteration, then one of TA or TB is odd,
2423 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2424 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2425 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskineb798b352021-06-21 11:40:38 +02002426 * 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 +02002427 */
2428
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002429 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2430 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
2432cleanup:
2433
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002434 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002436 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002437}
2438
Gilles Peskine8f454702021-04-01 15:57:18 +02002439/* Fill X with n_bytes random bytes.
2440 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002441 * The ordering of the bytes returned from the RNG is suitable for
2442 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002443 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002444 * n_bytes must not be 0.
2445 */
2446static int mpi_fill_random_internal(
2447 mbedtls_mpi *X, size_t n_bytes,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002448 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Gilles Peskine8f454702021-04-01 15:57:18 +02002449{
2450 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002451 const size_t limbs = CHARS_TO_LIMBS(n_bytes);
2452 const size_t overhead = (limbs * ciL) - n_bytes;
Gilles Peskine8f454702021-04-01 15:57:18 +02002453
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002454 if (X->n < limbs) {
2455 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2456 }
Gilles Peskine8f454702021-04-01 15:57:18 +02002457
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002458 memset(X->p, 0, overhead);
2459 memset((unsigned char *) X->p + limbs * ciL, 0, (X->n - limbs) * ciL);
2460 MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X->p + overhead, n_bytes));
2461 mpi_bigendian_to_host(X->p, limbs);
Gilles Peskine8f454702021-04-01 15:57:18 +02002462
2463cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002464 return ret;
Gilles Peskine8f454702021-04-01 15:57:18 +02002465}
2466
Paul Bakker33dc46b2014-04-30 16:11:39 +02002467/*
2468 * Fill X with size bytes of random.
2469 *
2470 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002471 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002472 * deterministic, eg for tests).
2473 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002474int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2475 int (*f_rng)(void *, unsigned char *, size_t),
2476 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002477{
Janos Follath24eed8d2019-11-22 13:21:35 +00002478 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002479 size_t const limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002480
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002481 MPI_VALIDATE_RET(X != NULL);
2482 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002483
Hanno Beckerda1655a2017-10-18 14:21:44 +01002484 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002485 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2486 if (size == 0) {
2487 return 0;
2488 }
Paul Bakker287781a2011-03-26 13:18:49 +00002489
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002490 ret = mpi_fill_random_internal(X, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002491
2492cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002493 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002494}
2495
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002496int mbedtls_mpi_random(mbedtls_mpi *X,
2497 mbedtls_mpi_sint min,
2498 const mbedtls_mpi *N,
2499 int (*f_rng)(void *, unsigned char *, size_t),
2500 void *p_rng)
Gilles Peskine4699fa42021-03-29 22:02:55 +02002501{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002502 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002503 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002504 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002505 size_t n_bits = mbedtls_mpi_bitlen(N);
2506 size_t n_bytes = (n_bits + 7) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002507 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002508
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002509 if (min < 0) {
2510 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2511 }
2512 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2513 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2514 }
Gilles Peskine9312ba52021-03-29 22:14:51 +02002515
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002516 /*
2517 * When min == 0, each try has at worst a probability 1/2 of failing
2518 * (the msb has a probability 1/2 of being 0, and then the result will
2519 * be < N), so after 30 tries failure probability is a most 2**(-30).
2520 *
2521 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002522 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002523 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002524 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002525 * a probability of failing that is almost 1/2.
2526 *
2527 * The probabilities are almost the same if min is nonzero but negligible
2528 * compared to N. This is always the case when N is crypto-sized, but
2529 * it's convenient to support small N for testing purposes. When N
2530 * is small, use a higher repeat count, otherwise the probability of
2531 * failure is macroscopic.
2532 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002533 count = (n_bytes > 4 ? 30 : 250);
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002534
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002535 mbedtls_mpi_init(&lower_bound);
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002536
Gilles Peskine8f454702021-04-01 15:57:18 +02002537 /* Ensure that target MPI has exactly the same number of limbs
2538 * as the upper bound, even if the upper bound has leading zeros.
2539 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002540 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, N->n));
2541 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&lower_bound, N->n));
2542 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&lower_bound, min));
Gilles Peskine8f454702021-04-01 15:57:18 +02002543
Gilles Peskine4699fa42021-03-29 22:02:55 +02002544 /*
2545 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2546 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2547 * - use the same byte ordering;
2548 * - keep the leftmost n_bits bits of the generated octet string;
2549 * - try until result is in the desired range.
2550 * This also avoids any bias, which is especially important for ECDSA.
2551 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002552 do {
2553 MBEDTLS_MPI_CHK(mpi_fill_random_internal(X, n_bytes, f_rng, p_rng));
2554 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, 8 * n_bytes - n_bits));
Gilles Peskine4699fa42021-03-29 22:02:55 +02002555
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002556 if (--count == 0) {
Gilles Peskine4699fa42021-03-29 22:02:55 +02002557 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2558 goto cleanup;
2559 }
2560
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002561 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, &lower_bound, &lt_lower));
2562 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, N, &lt_upper));
2563 } while (lt_lower != 0 || lt_upper == 0);
Gilles Peskine4699fa42021-03-29 22:02:55 +02002564
2565cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002566 mbedtls_mpi_free(&lower_bound);
2567 return ret;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002568}
2569
Paul Bakker5121ce52009-01-03 21:22:43 +00002570/*
2571 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2572 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002573int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002574{
Janos Follath24eed8d2019-11-22 13:21:35 +00002575 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002577 MPI_VALIDATE_RET(X != NULL);
2578 MPI_VALIDATE_RET(A != NULL);
2579 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002580
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002581 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2582 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2583 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002584
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002585 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2586 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2587 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002588
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002589 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002590
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002591 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002593 goto cleanup;
2594 }
2595
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002596 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2597 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2598 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2599 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002600
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002601 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2602 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2603 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2604 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002605
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002606 do {
2607 while ((TU.p[0] & 1) == 0) {
2608 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002609
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002610 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2611 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2612 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002613 }
2614
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002615 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2616 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002617 }
2618
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002619 while ((TV.p[0] & 1) == 0) {
2620 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002621
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002622 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2623 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2624 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002625 }
2626
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002627 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2628 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002629 }
2630
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002631 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2632 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2633 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2634 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2635 } else {
2636 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2637 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2638 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002639 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002640 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2641
2642 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2643 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002644 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002645
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002646 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2647 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2648 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002649
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002650 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002651
2652cleanup:
2653
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002654 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2655 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2656 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002657
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002658 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002659}
2660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002662
Paul Bakker5121ce52009-01-03 21:22:43 +00002663static const int small_prime[] =
2664{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002665 3, 5, 7, 11, 13, 17, 19, 23,
2666 29, 31, 37, 41, 43, 47, 53, 59,
2667 61, 67, 71, 73, 79, 83, 89, 97,
2668 101, 103, 107, 109, 113, 127, 131, 137,
2669 139, 149, 151, 157, 163, 167, 173, 179,
2670 181, 191, 193, 197, 199, 211, 223, 227,
2671 229, 233, 239, 241, 251, 257, 263, 269,
2672 271, 277, 281, 283, 293, 307, 311, 313,
2673 317, 331, 337, 347, 349, 353, 359, 367,
2674 373, 379, 383, 389, 397, 401, 409, 419,
2675 421, 431, 433, 439, 443, 449, 457, 461,
2676 463, 467, 479, 487, 491, 499, 503, 509,
2677 521, 523, 541, 547, 557, 563, 569, 571,
2678 577, 587, 593, 599, 601, 607, 613, 617,
2679 619, 631, 641, 643, 647, 653, 659, 661,
2680 673, 677, 683, 691, 701, 709, 719, 727,
2681 733, 739, 743, 751, 757, 761, 769, 773,
2682 787, 797, 809, 811, 821, 823, 827, 829,
2683 839, 853, 857, 859, 863, 877, 881, 883,
2684 887, 907, 911, 919, 929, 937, 941, 947,
2685 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002686};
2687
2688/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002689 * Small divisors test (X must be positive)
2690 *
2691 * Return values:
2692 * 0: no small factor (possible prime, more tests needed)
2693 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002695 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002696 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002697static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002698{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002699 int ret = 0;
2700 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002702
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002703 if ((X->p[0] & 1) == 0) {
2704 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2705 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002706
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002707 for (i = 0; small_prime[i] > 0; i++) {
2708 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2709 return 1;
2710 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002711
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002712 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002713
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002714 if (r == 0) {
2715 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2716 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002717 }
2718
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002719cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002720 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002721}
2722
2723/*
2724 * Miller-Rabin pseudo-primality test (HAC 4.24)
2725 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002726static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2727 int (*f_rng)(void *, unsigned char *, size_t),
2728 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002729{
Pascal Junodb99183d2015-03-11 16:49:45 +01002730 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002731 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002732 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002733
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002734 MPI_VALIDATE_RET(X != NULL);
2735 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002736
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002737 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2738 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2739 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002740
Paul Bakker5121ce52009-01-03 21:22:43 +00002741 /*
2742 * W = |X| - 1
2743 * R = W >> lsb( W )
2744 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002745 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2746 s = mbedtls_mpi_lsb(&W);
2747 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2748 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002749
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002750 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002751 /*
2752 * pick a random A, 1 < A < |X| - 1
2753 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002754 count = 0;
2755 do {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002756 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002757
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002758 j = mbedtls_mpi_bitlen(&A);
2759 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002760 if (j > k) {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002761 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002762 }
2763
2764 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002765 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2766 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002767 }
2768
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002769 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2770 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002771
2772 /*
2773 * A = A^R mod |X|
2774 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002775 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002776
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002777 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2778 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002779 continue;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002780 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002781
2782 j = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002783 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002784 /*
2785 * A = A * A mod |X|
2786 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002787 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2788 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002789
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002790 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002791 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002792 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002793
2794 j++;
2795 }
2796
2797 /*
2798 * not prime if A != |X| - 1 or A == 1
2799 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002800 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2801 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002802 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002803 break;
2804 }
2805 }
2806
2807cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002808 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2809 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2810 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002811
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002812 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002813}
2814
2815/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002816 * Pseudo-primality test: small factors, then Miller-Rabin
2817 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002818int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2819 int (*f_rng)(void *, unsigned char *, size_t),
2820 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002821{
Janos Follath24eed8d2019-11-22 13:21:35 +00002822 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002823 mbedtls_mpi XX;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002824 MPI_VALIDATE_RET(X != NULL);
2825 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002826
2827 XX.s = 1;
2828 XX.n = X->n;
2829 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002830
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002831 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2832 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2833 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002834 }
2835
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002836 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2837 return 0;
2838 }
2839
2840 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2841 if (ret == 1) {
2842 return 0;
2843 }
2844
2845 return ret;
2846 }
2847
2848 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002849}
2850
Janos Follatha0b67c22018-09-18 14:48:23 +01002851#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002852/*
2853 * Pseudo-primality test, error probability 2^-80
2854 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002855int mbedtls_mpi_is_prime(const mbedtls_mpi *X,
2856 int (*f_rng)(void *, unsigned char *, size_t),
2857 void *p_rng)
Janos Follathf301d232018-08-14 13:34:01 +01002858{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002859 MPI_VALIDATE_RET(X != NULL);
2860 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002861
Janos Follatha0b67c22018-09-18 14:48:23 +01002862 /*
2863 * In the past our key generation aimed for an error rate of at most
2864 * 2^-80. Since this function is deprecated, aim for the same certainty
2865 * here as well.
2866 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002867 return mbedtls_mpi_is_prime_ext(X, 40, f_rng, p_rng);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002868}
Janos Follatha0b67c22018-09-18 14:48:23 +01002869#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002870
2871/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002872 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002873 *
Janos Follathf301d232018-08-14 13:34:01 +01002874 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2875 * be either 1024 bits or 1536 bits long, and flags must contain
2876 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002877 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002878int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2879 int (*f_rng)(void *, unsigned char *, size_t),
2880 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002881{
Jethro Beekman66689272018-02-14 19:24:10 -08002882#ifdef MBEDTLS_HAVE_INT64
2883// ceil(2^63.5)
2884#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2885#else
2886// ceil(2^31.5)
2887#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2888#endif
2889 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002890 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002891 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002892 mbedtls_mpi_uint r;
2893 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002894
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002895 MPI_VALIDATE_RET(X != NULL);
2896 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002897
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002898 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2899 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2900 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002901
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002902 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002903
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002904 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002905
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002906 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002907 /*
2908 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2909 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002910 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2911 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2912 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2913 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002914 /*
2915 * 2^-100 error probability, number of rounds computed based on HAC,
2916 * fact 4.48
2917 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002918 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2919 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2920 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2921 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002922 }
2923
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002924 while (1) {
2925 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002926 /* 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 +01002927 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2928 continue;
2929 }
Jethro Beekman66689272018-02-14 19:24:10 -08002930
2931 k = n * biL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002932 if (k > nbits) {
2933 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2934 }
Jethro Beekman66689272018-02-14 19:24:10 -08002935 X->p[0] |= 1;
2936
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002937 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2938 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002939
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002940 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002941 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002942 }
2943 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002944 /*
Tom Cosgrove5205c972022-07-28 06:12:08 +01002945 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002946 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2947 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002948 */
Jethro Beekman66689272018-02-14 19:24:10 -08002949
2950 X->p[0] |= 2;
2951
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002952 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2953 if (r == 0) {
2954 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2955 } else if (r == 1) {
2956 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2957 }
Jethro Beekman66689272018-02-14 19:24:10 -08002958
2959 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002960 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2961 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002962
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002963 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002964 /*
2965 * First, check small factors for X and Y
2966 * before doing Miller-Rabin on any of them
2967 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002968 if ((ret = mpi_check_small_factors(X)) == 0 &&
2969 (ret = mpi_check_small_factors(&Y)) == 0 &&
2970 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2971 == 0 &&
2972 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2973 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002974 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002975 }
Jethro Beekman66689272018-02-14 19:24:10 -08002976
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002977 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002978 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002979 }
Jethro Beekman66689272018-02-14 19:24:10 -08002980
2981 /*
2982 * Next candidates. We want to preserve Y = (X-1) / 2 and
2983 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2984 * so up Y by 6 and X by 12.
2985 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002986 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2987 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002988 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002989 }
2990 }
2991
2992cleanup:
2993
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002994 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002995
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002996 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002997}
2998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002999#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003001#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003002
Paul Bakker23986e52011-04-24 08:57:21 +00003003#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003004
3005static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3006{
3007 { 693, 609, 21 },
3008 { 1764, 868, 28 },
3009 { 768454923, 542167814, 1 }
3010};
3011
Paul Bakker5121ce52009-01-03 21:22:43 +00003012/*
3013 * Checkup routine
3014 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003015int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00003016{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003017 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003018 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003019
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003020 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
3021 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003022
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003023 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
3024 "EFE021C2645FD1DC586E69184AF4A31E" \
3025 "D5F53E93B5F123FA41680867BA110131" \
3026 "944FE7952E2517337780CB0DB80E61AA" \
3027 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003028
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003029 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
3030 "B2E7EFD37075B9F03FF989C7C5051C20" \
3031 "34D2A323810251127E7BF8625A4F49A5" \
3032 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3033 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003034
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003035 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
3036 "0066A198186C18C10B2F5ED9B522752A" \
3037 "9830B69916E535C8F047518A889A43A5" \
3038 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003039
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003040 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003041
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003042 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3043 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3044 "9E857EA95A03512E2BAE7391688D264A" \
3045 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3046 "8001B72E848A38CAE1C65F78E56ABDEF" \
3047 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3048 "ECF677152EF804370C1A305CAF3B5BF1" \
3049 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003050
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003051 if (verbose != 0) {
3052 mbedtls_printf(" MPI test #1 (mul_mpi): ");
3053 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003054
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003055 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3056 if (verbose != 0) {
3057 mbedtls_printf("failed\n");
3058 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003059
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003060 ret = 1;
3061 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003062 }
3063
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003064 if (verbose != 0) {
3065 mbedtls_printf("passed\n");
3066 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003067
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003068 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003069
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003070 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3071 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003072
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003073 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
3074 "6613F26162223DF488E9CD48CC132C7A" \
3075 "0AC93C701B001B092E4E5B9F73BCD27B" \
3076 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003077
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003078 if (verbose != 0) {
3079 mbedtls_printf(" MPI test #2 (div_mpi): ");
3080 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003081
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003082 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
3083 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
3084 if (verbose != 0) {
3085 mbedtls_printf("failed\n");
3086 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003087
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003088 ret = 1;
3089 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003090 }
3091
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003092 if (verbose != 0) {
3093 mbedtls_printf("passed\n");
3094 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003095
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003096 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00003097
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003098 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3099 "36E139AEA55215609D2816998ED020BB" \
3100 "BD96C37890F65171D948E9BC7CBAA4D9" \
3101 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003102
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003103 if (verbose != 0) {
3104 mbedtls_printf(" MPI test #3 (exp_mod): ");
3105 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003106
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003107 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3108 if (verbose != 0) {
3109 mbedtls_printf("failed\n");
3110 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003111
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003112 ret = 1;
3113 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003114 }
3115
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003116 if (verbose != 0) {
3117 mbedtls_printf("passed\n");
3118 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003119
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003120 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003121
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003122 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3123 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3124 "C3DBA76456363A10869622EAC2DD84EC" \
3125 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003126
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003127 if (verbose != 0) {
3128 mbedtls_printf(" MPI test #4 (inv_mod): ");
3129 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003130
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003131 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3132 if (verbose != 0) {
3133 mbedtls_printf("failed\n");
3134 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003135
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003136 ret = 1;
3137 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003138 }
3139
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003140 if (verbose != 0) {
3141 mbedtls_printf("passed\n");
3142 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003143
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003144 if (verbose != 0) {
3145 mbedtls_printf(" MPI test #5 (simple gcd): ");
3146 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003147
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003148 for (i = 0; i < GCD_PAIR_COUNT; i++) {
3149 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
3150 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003151
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003152 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003153
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003154 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
3155 if (verbose != 0) {
3156 mbedtls_printf("failed at %d\n", i);
3157 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003158
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003159 ret = 1;
3160 goto cleanup;
3161 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003162 }
3163
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003164 if (verbose != 0) {
3165 mbedtls_printf("passed\n");
3166 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003167
Paul Bakker5121ce52009-01-03 21:22:43 +00003168cleanup:
3169
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003170 if (ret != 0 && verbose != 0) {
3171 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
3172 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003173
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003174 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
3175 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003176
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003177 if (verbose != 0) {
3178 mbedtls_printf("\n");
3179 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003180
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003181 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00003182}
3183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003184#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003186#endif /* MBEDTLS_BIGNUM_C */