blob: 5ec0541e84a8d02445bea7da6f8288b93239b201 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
Simon Butcher15b15d12015-11-26 19:35:03 +000019
Paul Bakker5121ce52009-01-03 21:22:43 +000020/*
Simon Butcher15b15d12015-11-26 19:35:03 +000021 * The following sources were referenced in the design of this Multi-precision
22 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000023 *
Simon Butcher15b15d12015-11-26 19:35:03 +000024 * [1] Handbook of Applied Cryptography - 1997
25 * Menezes, van Oorschot and Vanstone
26 *
27 * [2] Multi-Precision Math
28 * Tom St Denis
29 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30 *
31 * [3] GNU Multi-Precision Arithmetic Library
32 * https://gmplib.org/manual/index.html
33 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000034 */
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Gilles Peskinedb09ef62020-06-03 01:43:33 +020036#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/bignum.h"
41#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050042#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000043#include "mbedtls/error.h"
Gabor Mezeic0ae1cf2021-10-20 12:09:35 +020044#include "constant_time_internal.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Tom Cosgrove58efe612021-11-15 09:59:53 +000046#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000047#include <string.h>
48
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020050
David Horstmannceeaeb92023-01-05 15:44:23 +000051#define MPI_VALIDATE_RET(cond) \
52 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
53#define MPI_VALIDATE(cond) \
54 MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker73d7d792018-12-11 10:35:51 +000055
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000057#define biL (ciL << 3) /* bits in limb */
58#define biH (ciL << 2) /* half limb size */
59
David Horstmannceeaeb92023-01-05 15:44:23 +000060#define MPI_SIZE_T_MAX ((size_t) -1) /* SIZE_T_MAX is not standard */
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010061
Paul Bakker5121ce52009-01-03 21:22:43 +000062/*
63 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020064 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000065 */
David Horstmannceeaeb92023-01-05 15:44:23 +000066#define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0))
67#define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0))
Paul Bakker5121ce52009-01-03 21:22:43 +000068
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050069/* Implementation that should never be optimized out by the compiler */
David Horstmannceeaeb92023-01-05 15:44:23 +000070static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050071{
David Horstmannceeaeb92023-01-05 15:44:23 +000072 mbedtls_platform_zeroize(v, ciL * n);
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050073}
74
Paul Bakker5121ce52009-01-03 21:22:43 +000075/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000076 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000077 */
David Horstmannceeaeb92023-01-05 15:44:23 +000078void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000079{
David Horstmannceeaeb92023-01-05 15:44:23 +000080 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +000081
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 X->s = 1;
83 X->n = 0;
84 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000085}
86
87/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000089 */
David Horstmannceeaeb92023-01-05 15:44:23 +000090void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000091{
David Horstmannceeaeb92023-01-05 15:44:23 +000092 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 return;
David Horstmannceeaeb92023-01-05 15:44:23 +000094 }
Paul Bakker5121ce52009-01-03 21:22:43 +000095
David Horstmannceeaeb92023-01-05 15:44:23 +000096 if (X->p != NULL) {
97 mbedtls_mpi_zeroize(X->p, X->n);
98 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +000099 }
100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 X->s = 1;
102 X->n = 0;
103 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104}
105
106/*
107 * Enlarge to the specified number of limbs
108 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000109int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +0000110{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 mbedtls_mpi_uint *p;
David Horstmannceeaeb92023-01-05 15:44:23 +0000112 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000113
David Horstmannceeaeb92023-01-05 15:44:23 +0000114 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
115 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
116 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000117
David Horstmannceeaeb92023-01-05 15:44:23 +0000118 if (X->n < nblimbs) {
119 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
120 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
121 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
David Horstmannceeaeb92023-01-05 15:44:23 +0000123 if (X->p != NULL) {
124 memcpy(p, X->p, X->n * ciL);
125 mbedtls_mpi_zeroize(X->p, X->n);
126 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000127 }
128
129 X->n = nblimbs;
130 X->p = p;
131 }
132
David Horstmannceeaeb92023-01-05 15:44:23 +0000133 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000134}
135
136/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100137 * Resize down as much as possible,
138 * while keeping at least the specified number of limbs
139 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000140int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143 size_t i;
David Horstmannceeaeb92023-01-05 15:44:23 +0000144 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000145
David Horstmannceeaeb92023-01-05 15:44:23 +0000146 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
147 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
148 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100150 /* Actually resize up if there are currently fewer than nblimbs limbs. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000151 if (X->n <= nblimbs) {
152 return mbedtls_mpi_grow(X, nblimbs);
153 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100154 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155
David Horstmannceeaeb92023-01-05 15:44:23 +0000156 for (i = X->n - 1; i > 0; i--) {
157 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100158 break;
David Horstmannceeaeb92023-01-05 15:44:23 +0000159 }
160 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100161 i++;
162
David Horstmannceeaeb92023-01-05 15:44:23 +0000163 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 i = nblimbs;
David Horstmannceeaeb92023-01-05 15:44:23 +0000165 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100166
David Horstmannceeaeb92023-01-05 15:44:23 +0000167 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
168 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
169 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170
David Horstmannceeaeb92023-01-05 15:44:23 +0000171 if (X->p != NULL) {
172 memcpy(p, X->p, i * ciL);
173 mbedtls_mpi_zeroize(X->p, X->n);
174 mbedtls_free(X->p);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 }
176
177 X->n = i;
178 X->p = p;
179
David Horstmannceeaeb92023-01-05 15:44:23 +0000180 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100181}
182
Gilles Peskine3130ce22021-06-02 22:17:52 +0200183/* Resize X to have exactly n limbs and set it to 0. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000184static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskine3130ce22021-06-02 22:17:52 +0200185{
David Horstmannceeaeb92023-01-05 15:44:23 +0000186 if (limbs == 0) {
187 mbedtls_mpi_free(X);
188 return 0;
189 } else if (X->n == limbs) {
190 memset(X->p, 0, limbs * ciL);
Gilles Peskine3130ce22021-06-02 22:17:52 +0200191 X->s = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +0000192 return 0;
193 } else {
194 mbedtls_mpi_free(X);
195 return mbedtls_mpi_grow(X, limbs);
Gilles Peskine3130ce22021-06-02 22:17:52 +0200196 }
197}
198
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100199/*
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200200 * Copy the contents of Y into X.
201 *
202 * This function is not constant-time. Leading zeros in Y may be removed.
203 *
204 * Ensure that X does not shrink. This is not guaranteed by the public API,
205 * but some code in the bignum module relies on this property, for example
206 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000208int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000209{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100210 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000211 size_t i;
David Horstmannceeaeb92023-01-05 15:44:23 +0000212 MPI_VALIDATE_RET(X != NULL);
213 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
David Horstmannceeaeb92023-01-05 15:44:23 +0000215 if (X == Y) {
216 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200217 }
218
David Horstmannceeaeb92023-01-05 15:44:23 +0000219 if (Y->n == 0) {
220 if (X->n != 0) {
221 X->s = 1;
222 memset(X->p, 0, X->n * ciL);
223 }
224 return 0;
225 }
226
227 for (i = Y->n - 1; i > 0; i--) {
228 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000229 break;
David Horstmannceeaeb92023-01-05 15:44:23 +0000230 }
231 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000232 i++;
233
234 X->s = Y->s;
235
David Horstmannceeaeb92023-01-05 15:44:23 +0000236 if (X->n < i) {
237 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
238 } else {
239 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100240 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000241
David Horstmannceeaeb92023-01-05 15:44:23 +0000242 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000243
244cleanup:
245
David Horstmannceeaeb92023-01-05 15:44:23 +0000246 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000247}
248
249/*
250 * Swap the contents of X and Y
251 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000252void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000253{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 mbedtls_mpi T;
David Horstmannceeaeb92023-01-05 15:44:23 +0000255 MPI_VALIDATE(X != NULL);
256 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000257
David Horstmannceeaeb92023-01-05 15:44:23 +0000258 memcpy(&T, X, sizeof(mbedtls_mpi));
259 memcpy(X, Y, sizeof(mbedtls_mpi));
260 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000261}
262
David Horstmannceeaeb92023-01-05 15:44:23 +0000263static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100264{
David Horstmannceeaeb92023-01-05 15:44:23 +0000265 if (z >= 0) {
266 return z;
267 }
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100268 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
269 * A naive -z would have undefined behavior.
270 * Write this in a way that makes popular compilers happy (GCC, Clang,
271 * MSVC). */
David Horstmannceeaeb92023-01-05 15:44:23 +0000272 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100273}
274
Paul Bakker5121ce52009-01-03 21:22:43 +0000275/*
276 * Set value from integer
277 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000278int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000279{
Janos Follath24eed8d2019-11-22 13:21:35 +0000280 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
David Horstmannceeaeb92023-01-05 15:44:23 +0000281 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000282
David Horstmannceeaeb92023-01-05 15:44:23 +0000283 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
284 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000285
David Horstmannceeaeb92023-01-05 15:44:23 +0000286 X->p[0] = mpi_sint_abs(z);
287 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000288
289cleanup:
290
David Horstmannceeaeb92023-01-05 15:44:23 +0000291 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000292}
293
294/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000295 * Get a specific bit
296 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000297int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000298{
David Horstmannceeaeb92023-01-05 15:44:23 +0000299 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000300
David Horstmannceeaeb92023-01-05 15:44:23 +0000301 if (X->n * biL <= pos) {
302 return 0;
303 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000304
David Horstmannceeaeb92023-01-05 15:44:23 +0000305 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000306}
307
Gilles Peskine11cdb052018-11-20 16:47:47 +0100308/* Get a specific byte, without range checks. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000309#define GET_BYTE(X, i) \
310 (((X)->p[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)
Gilles Peskine11cdb052018-11-20 16:47:47 +0100311
Paul Bakker2f5947e2011-05-18 15:47:11 +0000312/*
313 * Set a bit to a specific value of 0 or 1
314 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000315int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000316{
317 int ret = 0;
318 size_t off = pos / biL;
319 size_t idx = pos % biL;
David Horstmannceeaeb92023-01-05 15:44:23 +0000320 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000321
David Horstmannceeaeb92023-01-05 15:44:23 +0000322 if (val != 0 && val != 1) {
323 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000324 }
325
David Horstmannceeaeb92023-01-05 15:44:23 +0000326 if (X->n * biL <= pos) {
327 if (val == 0) {
328 return 0;
329 }
330
331 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
332 }
333
334 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000336
337cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200338
David Horstmannceeaeb92023-01-05 15:44:23 +0000339 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000340}
341
342/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200343 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000344 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000345size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000346{
Paul Bakker23986e52011-04-24 08:57:21 +0000347 size_t i, j, count = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +0000348 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000349
David Horstmannceeaeb92023-01-05 15:44:23 +0000350 for (i = 0; i < X->n; i++) {
351 for (j = 0; j < biL; j++, count++) {
352 if (((X->p[i] >> j) & 1) != 0) {
353 return count;
354 }
355 }
356 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000357
David Horstmannceeaeb92023-01-05 15:44:23 +0000358 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000359}
360
361/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000362 * Count leading zero bits in a given integer
363 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000364static size_t mbedtls_clz(const mbedtls_mpi_uint x)
Simon Butcher15b15d12015-11-26 19:35:03 +0000365{
366 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100367 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000368
David Horstmannceeaeb92023-01-05 15:44:23 +0000369 for (j = 0; j < biL; j++) {
370 if (x & mask) {
371 break;
372 }
Simon Butcher15b15d12015-11-26 19:35:03 +0000373
374 mask >>= 1;
375 }
376
377 return j;
378}
379
380/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200381 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000382 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000383size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000384{
Paul Bakker23986e52011-04-24 08:57:21 +0000385 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000386
David Horstmannceeaeb92023-01-05 15:44:23 +0000387 if (X->n == 0) {
388 return 0;
389 }
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200390
David Horstmannceeaeb92023-01-05 15:44:23 +0000391 for (i = X->n - 1; i > 0; i--) {
392 if (X->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000393 break;
David Horstmannceeaeb92023-01-05 15:44:23 +0000394 }
395 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000396
David Horstmannceeaeb92023-01-05 15:44:23 +0000397 j = biL - mbedtls_clz(X->p[i]);
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
David Horstmannceeaeb92023-01-05 15:44:23 +0000399 return (i * biL) + j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000400}
401
402/*
403 * Return the total size in bytes
404 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000405size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000406{
David Horstmannceeaeb92023-01-05 15:44:23 +0000407 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000408}
409
410/*
411 * Convert an ASCII character to digit value
412 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000413static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000414{
415 *d = 255;
416
David Horstmannceeaeb92023-01-05 15:44:23 +0000417 if (c >= 0x30 && c <= 0x39) {
418 *d = c - 0x30;
419 }
420 if (c >= 0x41 && c <= 0x46) {
421 *d = c - 0x37;
422 }
423 if (c >= 0x61 && c <= 0x66) {
424 *d = c - 0x57;
425 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
David Horstmannceeaeb92023-01-05 15:44:23 +0000427 if (*d >= (mbedtls_mpi_uint) radix) {
428 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
429 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
David Horstmannceeaeb92023-01-05 15:44:23 +0000431 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000432}
433
434/*
435 * Import from an ASCII string
436 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000437int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000438{
Janos Follath24eed8d2019-11-22 13:21:35 +0000439 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000440 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200441 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 mbedtls_mpi_uint d;
443 mbedtls_mpi T;
David Horstmannceeaeb92023-01-05 15:44:23 +0000444 MPI_VALIDATE_RET(X != NULL);
445 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000446
David Horstmannceeaeb92023-01-05 15:44:23 +0000447 if (radix < 2 || radix > 16) {
448 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskined4876132021-06-08 18:32:34 +0200449 }
450
David Horstmannceeaeb92023-01-05 15:44:23 +0000451 mbedtls_mpi_init(&T);
452
453 if (s[0] == 0) {
454 mbedtls_mpi_free(X);
455 return 0;
456 }
457
458 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200459 ++s;
460 sign = -1;
461 }
462
David Horstmannceeaeb92023-01-05 15:44:23 +0000463 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000464
David Horstmannceeaeb92023-01-05 15:44:23 +0000465 if (radix == 16) {
466 if (slen > MPI_SIZE_T_MAX >> 2) {
467 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000468 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
David Horstmannceeaeb92023-01-05 15:44:23 +0000470 n = BITS_TO_LIMBS(slen << 2);
471
472 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
473 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
474
475 for (i = slen, j = 0; i > 0; i--, j++) {
476 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
477 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
478 }
479 } else {
480 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
481
482 for (i = 0; i < slen; i++) {
483 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
484 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
485 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000486 }
487 }
488
David Horstmannceeaeb92023-01-05 15:44:23 +0000489 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200490 X->s = -1;
David Horstmannceeaeb92023-01-05 15:44:23 +0000491 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200492
Paul Bakker5121ce52009-01-03 21:22:43 +0000493cleanup:
494
David Horstmannceeaeb92023-01-05 15:44:23 +0000495 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000496
David Horstmannceeaeb92023-01-05 15:44:23 +0000497 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000498}
499
500/*
Ron Eldora16fa292018-11-20 14:07:01 +0200501 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000503static int mpi_write_hlp(mbedtls_mpi *X, int radix,
504 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000505{
Janos Follath24eed8d2019-11-22 13:21:35 +0000506 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200508 size_t length = 0;
509 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000510
David Horstmannceeaeb92023-01-05 15:44:23 +0000511 do {
512 if (length >= buflen) {
513 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200514 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000515
David Horstmannceeaeb92023-01-05 15:44:23 +0000516 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
517 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200518 /*
519 * Write the residue in the current position, as an ASCII character.
520 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000521 if (r < 0xA) {
522 *(--p_end) = (char) ('0' + r);
523 } else {
524 *(--p_end) = (char) ('A' + (r - 0xA));
525 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000526
Ron Eldora16fa292018-11-20 14:07:01 +0200527 length++;
David Horstmannceeaeb92023-01-05 15:44:23 +0000528 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
David Horstmannceeaeb92023-01-05 15:44:23 +0000530 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200531 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
533cleanup:
534
David Horstmannceeaeb92023-01-05 15:44:23 +0000535 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536}
537
538/*
539 * Export into an ASCII string
540 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000541int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
542 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000543{
Paul Bakker23986e52011-04-24 08:57:21 +0000544 int ret = 0;
545 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000546 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 mbedtls_mpi T;
David Horstmannceeaeb92023-01-05 15:44:23 +0000548 MPI_VALIDATE_RET(X != NULL);
549 MPI_VALIDATE_RET(olen != NULL);
550 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
David Horstmannceeaeb92023-01-05 15:44:23 +0000552 if (radix < 2 || radix > 16) {
553 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
554 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
David Horstmannceeaeb92023-01-05 15:44:23 +0000556 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
557 if (radix >= 4) {
558 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000559 * `n`. If radix > 4, this might be a strict
560 * overapproximation of the number of
561 * radix-adic digits needed to present `n`. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000562 }
563 if (radix >= 16) {
564 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000565 * present `n`. */
566
David Horstmannceeaeb92023-01-05 15:44:23 +0000567 }
Janos Follath80470622019-03-06 13:43:02 +0000568 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000569 n += 1; /* Compensate for the divisions above, which round down `n`
570 * in case it's not even. */
571 n += 1; /* Potential '-'-sign. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000572 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000573 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000574
David Horstmannceeaeb92023-01-05 15:44:23 +0000575 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100576 *olen = n;
David Horstmannceeaeb92023-01-05 15:44:23 +0000577 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 }
579
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100580 p = buf;
David Horstmannceeaeb92023-01-05 15:44:23 +0000581 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
David Horstmannceeaeb92023-01-05 15:44:23 +0000583 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000585 buflen--;
586 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
David Horstmannceeaeb92023-01-05 15:44:23 +0000588 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000589 int c;
590 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
David Horstmannceeaeb92023-01-05 15:44:23 +0000592 for (i = X->n, k = 0; i > 0; i--) {
593 for (j = ciL; j > 0; j--) {
594 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
David Horstmannceeaeb92023-01-05 15:44:23 +0000596 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000597 continue;
David Horstmannceeaeb92023-01-05 15:44:23 +0000598 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000600 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000601 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000602 k = 1;
603 }
604 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000605 } else {
606 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000607
David Horstmannceeaeb92023-01-05 15:44:23 +0000608 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000609 T.s = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +0000610 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000611
David Horstmannceeaeb92023-01-05 15:44:23 +0000612 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 }
614
615 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100616 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
618cleanup:
619
David Horstmannceeaeb92023-01-05 15:44:23 +0000620 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
David Horstmannceeaeb92023-01-05 15:44:23 +0000622 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000623}
624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000626/*
627 * Read X from an opened file
628 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000629int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000630{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000632 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000634 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000635 * Buffer should have space for (short) label and decimal formatted MPI,
636 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000637 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000638 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
David Horstmannceeaeb92023-01-05 15:44:23 +0000640 MPI_VALIDATE_RET(X != NULL);
641 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000642
David Horstmannceeaeb92023-01-05 15:44:23 +0000643 if (radix < 2 || radix > 16) {
644 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
645 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000646
David Horstmannceeaeb92023-01-05 15:44:23 +0000647 memset(s, 0, sizeof(s));
648 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
649 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
650 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
David Horstmannceeaeb92023-01-05 15:44:23 +0000652 slen = strlen(s);
653 if (slen == sizeof(s) - 2) {
654 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
655 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000656
David Horstmannceeaeb92023-01-05 15:44:23 +0000657 if (slen > 0 && s[slen - 1] == '\n') {
658 slen--; s[slen] = '\0';
659 }
660 if (slen > 0 && s[slen - 1] == '\r') {
661 slen--; s[slen] = '\0';
662 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664 p = s + slen;
David Horstmannceeaeb92023-01-05 15:44:23 +0000665 while (p-- > s) {
666 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000667 break;
David Horstmannceeaeb92023-01-05 15:44:23 +0000668 }
669 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
David Horstmannceeaeb92023-01-05 15:44:23 +0000671 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000672}
673
674/*
675 * Write X into an opened file (or stdout if fout == NULL)
676 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000677int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000678{
Janos Follath24eed8d2019-11-22 13:21:35 +0000679 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000680 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000681 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000682 * Buffer should have space for (short) label and decimal formatted MPI,
683 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000684 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000685 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
686 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000687
David Horstmannceeaeb92023-01-05 15:44:23 +0000688 if (radix < 2 || radix > 16) {
689 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
690 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
David Horstmannceeaeb92023-01-05 15:44:23 +0000692 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
David Horstmannceeaeb92023-01-05 15:44:23 +0000694 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
David Horstmannceeaeb92023-01-05 15:44:23 +0000696 if (p == NULL) {
697 p = "";
698 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
David Horstmannceeaeb92023-01-05 15:44:23 +0000700 plen = strlen(p);
701 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000702 s[slen++] = '\r';
703 s[slen++] = '\n';
704
David Horstmannceeaeb92023-01-05 15:44:23 +0000705 if (fout != NULL) {
706 if (fwrite(p, 1, plen, fout) != plen ||
707 fwrite(s, 1, slen, fout) != slen) {
708 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
709 }
710 } else {
711 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000712 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
714cleanup:
715
David Horstmannceeaeb92023-01-05 15:44:23 +0000716 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000717}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
Hanno Beckerda1655a2017-10-18 14:21:44 +0100720
721/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
722 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000723
David Horstmannceeaeb92023-01-05 15:44:23 +0000724static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000725{
726 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100727 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000728 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100729
David Horstmannceeaeb92023-01-05 15:44:23 +0000730 for (i = 0, x_ptr = (unsigned char *) &x; i < ciL; i++, x_ptr++) {
Hanno Becker031d6332019-05-01 17:09:11 +0100731 tmp <<= CHAR_BIT;
732 tmp |= (mbedtls_mpi_uint) *x_ptr;
733 }
734
David Horstmannceeaeb92023-01-05 15:44:23 +0000735 return tmp;
Hanno Beckerf8720072018-11-08 11:53:49 +0000736}
737
David Horstmannceeaeb92023-01-05 15:44:23 +0000738static mbedtls_mpi_uint mpi_uint_bigendian_to_host(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000739{
740#if defined(__BYTE_ORDER__)
741
742/* Nothing to do on bigendian systems. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000743#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
744 return x;
Hanno Beckerf8720072018-11-08 11:53:49 +0000745#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
746
David Horstmannceeaeb92023-01-05 15:44:23 +0000747#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
Hanno Beckerf8720072018-11-08 11:53:49 +0000748
749/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000750#if defined(__GNUC__) && defined(__GNUC_PREREQ)
David Horstmannceeaeb92023-01-05 15:44:23 +0000751#if __GNUC_PREREQ(4, 3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000752#define have_bswap
753#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000754#endif
755
756#if defined(__clang__) && defined(__has_builtin)
757#if __has_builtin(__builtin_bswap32) && \
758 __has_builtin(__builtin_bswap64)
759#define have_bswap
760#endif
761#endif
762
Hanno Beckerf8720072018-11-08 11:53:49 +0000763#if defined(have_bswap)
764 /* The compiler is hopefully able to statically evaluate this! */
David Horstmannceeaeb92023-01-05 15:44:23 +0000765 switch (sizeof(mbedtls_mpi_uint)) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000766 case 4:
David Horstmannceeaeb92023-01-05 15:44:23 +0000767 return __builtin_bswap32(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000768 case 8:
David Horstmannceeaeb92023-01-05 15:44:23 +0000769 return __builtin_bswap64(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000770 }
771#endif
772#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
773#endif /* __BYTE_ORDER__ */
774
775 /* Fall back to C-based reordering if we don't know the byte order
776 * or we couldn't use a compiler-specific builtin. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000777 return mpi_uint_bigendian_to_host_c(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000778}
779
David Horstmannceeaeb92023-01-05 15:44:23 +0000780static void mpi_bigendian_to_host(mbedtls_mpi_uint * const p, size_t limbs)
Hanno Beckerda1655a2017-10-18 14:21:44 +0100781{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100782 mbedtls_mpi_uint *cur_limb_left;
783 mbedtls_mpi_uint *cur_limb_right;
David Horstmannceeaeb92023-01-05 15:44:23 +0000784 if (limbs == 0) {
Hanno Becker2be8a552018-10-25 12:40:09 +0100785 return;
David Horstmannceeaeb92023-01-05 15:44:23 +0000786 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100787
788 /*
789 * Traverse limbs and
790 * - adapt byte-order in each limb
791 * - swap the limbs themselves.
792 * For that, simultaneously traverse the limbs from left to right
793 * and from right to left, as long as the left index is not bigger
794 * than the right index (it's not a problem if limbs is odd and the
795 * indices coincide in the last iteration).
796 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000797 for (cur_limb_left = p, cur_limb_right = p + (limbs - 1);
Hanno Beckerda1655a2017-10-18 14:21:44 +0100798 cur_limb_left <= cur_limb_right;
David Horstmannceeaeb92023-01-05 15:44:23 +0000799 cur_limb_left++, cur_limb_right--) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000800 mbedtls_mpi_uint tmp;
801 /* Note that if cur_limb_left == cur_limb_right,
802 * this code effectively swaps the bytes only once. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000803 tmp = mpi_uint_bigendian_to_host(*cur_limb_left);
804 *cur_limb_left = mpi_uint_bigendian_to_host(*cur_limb_right);
Hanno Beckerf8720072018-11-08 11:53:49 +0000805 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100806 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100807}
808
Paul Bakker5121ce52009-01-03 21:22:43 +0000809/*
Janos Follatha778a942019-02-13 10:28:28 +0000810 * Import X from unsigned binary data, little endian
811 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000812int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
813 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000814{
Janos Follath24eed8d2019-11-22 13:21:35 +0000815 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000816 size_t i;
David Horstmannceeaeb92023-01-05 15:44:23 +0000817 size_t const limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000818
819 /* Ensure that target MPI has exactly the necessary number of limbs */
David Horstmannceeaeb92023-01-05 15:44:23 +0000820 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000821
David Horstmannceeaeb92023-01-05 15:44:23 +0000822 for (i = 0; i < buflen; i++) {
Janos Follatha778a942019-02-13 10:28:28 +0000823 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
David Horstmannceeaeb92023-01-05 15:44:23 +0000824 }
Janos Follatha778a942019-02-13 10:28:28 +0000825
826cleanup:
827
Janos Follath171a7ef2019-02-15 16:17:45 +0000828 /*
829 * This function is also used to import keys. However, wiping the buffers
830 * upon failure is not necessary because failure only can happen before any
831 * input is copied.
832 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000833 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000834}
835
836/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000837 * Import X from unsigned binary data, big endian
838 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000839int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000840{
Janos Follath24eed8d2019-11-22 13:21:35 +0000841 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
David Horstmannceeaeb92023-01-05 15:44:23 +0000842 size_t const limbs = CHARS_TO_LIMBS(buflen);
843 size_t const overhead = (limbs * ciL) - buflen;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100844 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
David Horstmannceeaeb92023-01-05 15:44:23 +0000846 MPI_VALIDATE_RET(X != NULL);
847 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000848
Hanno Becker073c1992017-10-17 15:17:27 +0100849 /* Ensure that target MPI has exactly the necessary number of limbs */
David Horstmannceeaeb92023-01-05 15:44:23 +0000850 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000851
Gilles Peskine3130ce22021-06-02 22:17:52 +0200852 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000853 * even if buflen is 0. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000854 if (buflen != 0) {
855 Xp = (unsigned char *) X->p;
856 memcpy(Xp + overhead, buf, buflen);
Hanno Beckerda1655a2017-10-18 14:21:44 +0100857
David Horstmannceeaeb92023-01-05 15:44:23 +0000858 mpi_bigendian_to_host(X->p, limbs);
Hanno Becker0e810b92019-01-03 17:13:11 +0000859 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000860
861cleanup:
862
Janos Follath171a7ef2019-02-15 16:17:45 +0000863 /*
864 * This function is also used to import keys. However, wiping the buffers
865 * upon failure is not necessary because failure only can happen before any
866 * input is copied.
867 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000868 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000869}
870
871/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000872 * Export X into unsigned binary data, little endian
873 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000874int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
875 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000876{
877 size_t stored_bytes = X->n * ciL;
878 size_t bytes_to_copy;
879 size_t i;
880
David Horstmannceeaeb92023-01-05 15:44:23 +0000881 if (stored_bytes < buflen) {
Janos Follathe344d0f2019-02-19 16:17:40 +0000882 bytes_to_copy = stored_bytes;
David Horstmannceeaeb92023-01-05 15:44:23 +0000883 } else {
Janos Follathe344d0f2019-02-19 16:17:40 +0000884 bytes_to_copy = buflen;
885
886 /* The output buffer is smaller than the allocated size of X.
887 * However X may fit if its leading bytes are zero. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000888 for (i = bytes_to_copy; i < stored_bytes; i++) {
889 if (GET_BYTE(X, i) != 0) {
890 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
891 }
Janos Follathe344d0f2019-02-19 16:17:40 +0000892 }
893 }
894
David Horstmannceeaeb92023-01-05 15:44:23 +0000895 for (i = 0; i < bytes_to_copy; i++) {
896 buf[i] = GET_BYTE(X, i);
Janos Follathe344d0f2019-02-19 16:17:40 +0000897 }
898
David Horstmannceeaeb92023-01-05 15:44:23 +0000899 if (stored_bytes < buflen) {
900 /* Write trailing 0 bytes */
901 memset(buf + stored_bytes, 0, buflen - stored_bytes);
902 }
903
904 return 0;
Janos Follathe344d0f2019-02-19 16:17:40 +0000905}
906
907/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000908 * Export X into unsigned binary data, big endian
909 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000910int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
911 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000912{
Hanno Becker73d7d792018-12-11 10:35:51 +0000913 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100914 size_t bytes_to_copy;
915 unsigned char *p;
916 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
David Horstmannceeaeb92023-01-05 15:44:23 +0000918 MPI_VALIDATE_RET(X != NULL);
919 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000920
921 stored_bytes = X->n * ciL;
922
David Horstmannceeaeb92023-01-05 15:44:23 +0000923 if (stored_bytes < buflen) {
Gilles Peskine11cdb052018-11-20 16:47:47 +0100924 /* There is enough space in the output buffer. Write initial
925 * null bytes and record the position at which to start
926 * writing the significant bytes. In this case, the execution
927 * trace of this function does not depend on the value of the
928 * number. */
929 bytes_to_copy = stored_bytes;
930 p = buf + buflen - stored_bytes;
David Horstmannceeaeb92023-01-05 15:44:23 +0000931 memset(buf, 0, buflen - stored_bytes);
932 } else {
Gilles Peskine11cdb052018-11-20 16:47:47 +0100933 /* The output buffer is smaller than the allocated size of X.
934 * However X may fit if its leading bytes are zero. */
935 bytes_to_copy = buflen;
936 p = buf;
David Horstmannceeaeb92023-01-05 15:44:23 +0000937 for (i = bytes_to_copy; i < stored_bytes; i++) {
938 if (GET_BYTE(X, i) != 0) {
939 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
940 }
Gilles Peskine11cdb052018-11-20 16:47:47 +0100941 }
942 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000943
David Horstmannceeaeb92023-01-05 15:44:23 +0000944 for (i = 0; i < bytes_to_copy; i++) {
945 p[bytes_to_copy - i - 1] = GET_BYTE(X, i);
946 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000947
David Horstmannceeaeb92023-01-05 15:44:23 +0000948 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000949}
950
951/*
952 * Left-shift: X <<= count
953 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000954int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000955{
Janos Follath24eed8d2019-11-22 13:21:35 +0000956 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000957 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958 mbedtls_mpi_uint r0 = 0, r1;
David Horstmannceeaeb92023-01-05 15:44:23 +0000959 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000960
David Horstmannceeaeb92023-01-05 15:44:23 +0000961 v0 = count / (biL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000962 t1 = count & (biL - 1);
963
David Horstmannceeaeb92023-01-05 15:44:23 +0000964 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000965
David Horstmannceeaeb92023-01-05 15:44:23 +0000966 if (X->n * biL < i) {
967 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
968 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
970 ret = 0;
971
972 /*
973 * shift by count / limb_size
974 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000975 if (v0 > 0) {
976 for (i = X->n; i > v0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +0000977 X->p[i - 1] = X->p[i - v0 - 1];
David Horstmannceeaeb92023-01-05 15:44:23 +0000978 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000979
David Horstmannceeaeb92023-01-05 15:44:23 +0000980 for (; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +0000981 X->p[i - 1] = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +0000982 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000983 }
984
985 /*
986 * shift by count % limb_size
987 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000988 if (t1 > 0) {
989 for (i = v0; i < X->n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 r1 = X->p[i] >> (biL - t1);
991 X->p[i] <<= t1;
992 X->p[i] |= r0;
993 r0 = r1;
994 }
995 }
996
997cleanup:
998
David Horstmannceeaeb92023-01-05 15:44:23 +0000999 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001000}
1001
1002/*
1003 * Right-shift: X >>= count
1004 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001005int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +00001006{
Paul Bakker23986e52011-04-24 08:57:21 +00001007 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001008 mbedtls_mpi_uint r0 = 0, r1;
David Horstmannceeaeb92023-01-05 15:44:23 +00001009 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001010
1011 v0 = count / biL;
1012 v1 = count & (biL - 1);
1013
David Horstmannceeaeb92023-01-05 15:44:23 +00001014 if (v0 > X->n || (v0 == X->n && v1 > 0)) {
1015 return mbedtls_mpi_lset(X, 0);
1016 }
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001017
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 /*
1019 * shift by count / limb_size
1020 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001021 if (v0 > 0) {
1022 for (i = 0; i < X->n - v0; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 X->p[i] = X->p[i + v0];
David Horstmannceeaeb92023-01-05 15:44:23 +00001024 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001025
David Horstmannceeaeb92023-01-05 15:44:23 +00001026 for (; i < X->n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 X->p[i] = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +00001028 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001029 }
1030
1031 /*
1032 * shift by count % limb_size
1033 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001034 if (v1 > 0) {
1035 for (i = X->n; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001036 r1 = X->p[i - 1] << (biL - v1);
1037 X->p[i - 1] >>= v1;
1038 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 r0 = r1;
1040 }
1041 }
1042
David Horstmannceeaeb92023-01-05 15:44:23 +00001043 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001044}
1045
1046/*
1047 * Compare unsigned values
1048 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001049int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001050{
Paul Bakker23986e52011-04-24 08:57:21 +00001051 size_t i, j;
David Horstmannceeaeb92023-01-05 15:44:23 +00001052 MPI_VALIDATE_RET(X != NULL);
1053 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
David Horstmannceeaeb92023-01-05 15:44:23 +00001055 for (i = X->n; i > 0; i--) {
1056 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 break;
David Horstmannceeaeb92023-01-05 15:44:23 +00001058 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001059 }
1060
David Horstmannceeaeb92023-01-05 15:44:23 +00001061 for (j = Y->n; j > 0; j--) {
1062 if (Y->p[j - 1] != 0) {
1063 break;
1064 }
1065 }
1066
1067 if (i == 0 && j == 0) {
1068 return 0;
1069 }
1070
1071 if (i > j) {
1072 return 1;
1073 }
1074 if (j > i) {
1075 return -1;
1076 }
1077
1078 for (; i > 0; i--) {
1079 if (X->p[i - 1] > Y->p[i - 1]) {
1080 return 1;
1081 }
1082 if (X->p[i - 1] < Y->p[i - 1]) {
1083 return -1;
1084 }
1085 }
1086
1087 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001088}
1089
1090/*
1091 * Compare signed values
1092 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001093int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001094{
Paul Bakker23986e52011-04-24 08:57:21 +00001095 size_t i, j;
David Horstmannceeaeb92023-01-05 15:44:23 +00001096 MPI_VALIDATE_RET(X != NULL);
1097 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001098
David Horstmannceeaeb92023-01-05 15:44:23 +00001099 for (i = X->n; i > 0; i--) {
1100 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 break;
David Horstmannceeaeb92023-01-05 15:44:23 +00001102 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001103 }
1104
David Horstmannceeaeb92023-01-05 15:44:23 +00001105 for (j = Y->n; j > 0; j--) {
1106 if (Y->p[j - 1] != 0) {
1107 break;
1108 }
1109 }
1110
1111 if (i == 0 && j == 0) {
1112 return 0;
1113 }
1114
1115 if (i > j) {
1116 return X->s;
1117 }
1118 if (j > i) {
1119 return -Y->s;
1120 }
1121
1122 if (X->s > 0 && Y->s < 0) {
1123 return 1;
1124 }
1125 if (Y->s > 0 && X->s < 0) {
1126 return -1;
1127 }
1128
1129 for (; i > 0; i--) {
1130 if (X->p[i - 1] > Y->p[i - 1]) {
1131 return X->s;
1132 }
1133 if (X->p[i - 1] < Y->p[i - 1]) {
1134 return -X->s;
1135 }
1136 }
1137
1138 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001139}
1140
Janos Follathee6abce2019-09-05 14:47:19 +01001141/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001142 * Compare signed values
1143 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001144int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +00001145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001146 mbedtls_mpi Y;
1147 mbedtls_mpi_uint p[1];
David Horstmannceeaeb92023-01-05 15:44:23 +00001148 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001149
David Horstmannceeaeb92023-01-05 15:44:23 +00001150 *p = mpi_sint_abs(z);
1151 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001152 Y.n = 1;
1153 Y.p = p;
1154
David Horstmannceeaeb92023-01-05 15:44:23 +00001155 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00001156}
1157
1158/*
1159 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1160 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001161int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001162{
Janos Follath24eed8d2019-11-22 13:21:35 +00001163 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001164 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001165 mbedtls_mpi_uint *o, *p, c, tmp;
David Horstmannceeaeb92023-01-05 15:44:23 +00001166 MPI_VALIDATE_RET(X != NULL);
1167 MPI_VALIDATE_RET(A != NULL);
1168 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001169
David Horstmannceeaeb92023-01-05 15:44:23 +00001170 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001171 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 }
1173
David Horstmannceeaeb92023-01-05 15:44:23 +00001174 if (X != A) {
1175 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1176 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001177
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001178 /*
1179 * X should always be positive as a result of unsigned additions.
1180 */
1181 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
David Horstmannceeaeb92023-01-05 15:44:23 +00001183 for (j = B->n; j > 0; j--) {
1184 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 break;
David Horstmannceeaeb92023-01-05 15:44:23 +00001186 }
1187 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001188
Gilles Peskine103cf592022-11-15 22:59:00 +01001189 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1190 * and B is 0 (of any size). */
David Horstmannceeaeb92023-01-05 15:44:23 +00001191 if (j == 0) {
1192 return 0;
1193 }
Gilles Peskine103cf592022-11-15 22:59:00 +01001194
David Horstmannceeaeb92023-01-05 15:44:23 +00001195 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
1197 o = B->p; p = X->p; c = 0;
1198
Janos Follath6c922682015-10-30 17:43:11 +01001199 /*
1200 * tmp is used because it might happen that p == o
1201 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001202 for (i = 0; i < j; i++, o++, p++) {
1203 tmp = *o;
1204 *p += c; c = (*p < c);
1205 *p += tmp; c += (*p < tmp);
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 }
1207
David Horstmannceeaeb92023-01-05 15:44:23 +00001208 while (c != 0) {
1209 if (i >= X->n) {
1210 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001211 p = X->p + i;
1212 }
1213
David Horstmannceeaeb92023-01-05 15:44:23 +00001214 *p += c; c = (*p < c); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001215 }
1216
1217cleanup:
1218
David Horstmannceeaeb92023-01-05 15:44:23 +00001219 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001220}
1221
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001222/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001223 * Helper for mbedtls_mpi subtraction.
1224 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001225 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001226 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001227 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001228 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001229 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001230 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001231 * \param n Number of limbs of \p d, \p l and \p r.
1232 * \param[out] d The result of the subtraction.
1233 * \param[in] l The left operand.
1234 * \param[in] r The right operand.
1235 *
1236 * \return 1 if `l < r`.
1237 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001239static mbedtls_mpi_uint mpi_sub_hlp(size_t n,
1240 mbedtls_mpi_uint *d,
1241 const mbedtls_mpi_uint *l,
1242 const mbedtls_mpi_uint *r)
Paul Bakker5121ce52009-01-03 21:22:43 +00001243{
Paul Bakker23986e52011-04-24 08:57:21 +00001244 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001245 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001246
David Horstmannceeaeb92023-01-05 15:44:23 +00001247 for (i = 0; i < n; i++) {
1248 z = (l[i] < c); t = l[i] - c;
1249 c = (t < r[i]) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001250 }
1251
David Horstmannceeaeb92023-01-05 15:44:23 +00001252 return c;
Paul Bakker5121ce52009-01-03 21:22:43 +00001253}
1254
1255/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001256 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001257 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001258int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001259{
Janos Follath24eed8d2019-11-22 13:21:35 +00001260 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001261 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001262 mbedtls_mpi_uint carry;
David Horstmannceeaeb92023-01-05 15:44:23 +00001263 MPI_VALIDATE_RET(X != NULL);
1264 MPI_VALIDATE_RET(A != NULL);
1265 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
David Horstmannceeaeb92023-01-05 15:44:23 +00001267 for (n = B->n; n > 0; n--) {
1268 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001269 break;
David Horstmannceeaeb92023-01-05 15:44:23 +00001270 }
1271 }
1272 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001273 /* B >= (2^ciL)^n > A */
1274 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1275 goto cleanup;
1276 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
David Horstmannceeaeb92023-01-05 15:44:23 +00001278 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001279
1280 /* Set the high limbs of X to match A. Don't touch the lower limbs
1281 * because X might be aliased to B, and we must not overwrite the
1282 * significant digits of B. */
David Horstmannceeaeb92023-01-05 15:44:23 +00001283 if (A->n > n) {
1284 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1285 }
1286 if (X->n > A->n) {
1287 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1288 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001289
David Horstmannceeaeb92023-01-05 15:44:23 +00001290 carry = mpi_sub_hlp(n, X->p, A->p, B->p);
1291 if (carry != 0) {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001292 /* Propagate the carry to the first nonzero limb of X. */
David Horstmannceeaeb92023-01-05 15:44:23 +00001293 for (; n < X->n && X->p[n] == 0; n++) {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001294 --X->p[n];
David Horstmannceeaeb92023-01-05 15:44:23 +00001295 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001296 /* If we ran out of space for the carry, it means that the result
1297 * is negative. */
David Horstmannceeaeb92023-01-05 15:44:23 +00001298 if (n == X->n) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001299 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1300 goto cleanup;
1301 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001302 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001303 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001304
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001305 /* X should always be positive as a result of unsigned subtractions. */
1306 X->s = 1;
1307
Paul Bakker5121ce52009-01-03 21:22:43 +00001308cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +00001309 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001310}
1311
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001312/* Common function for signed addition and subtraction.
1313 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001314 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001315static int add_sub_mpi(mbedtls_mpi *X,
1316 const mbedtls_mpi *A, const mbedtls_mpi *B,
1317 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001318{
Hanno Becker73d7d792018-12-11 10:35:51 +00001319 int ret, s;
David Horstmannceeaeb92023-01-05 15:44:23 +00001320 MPI_VALIDATE_RET(X != NULL);
1321 MPI_VALIDATE_RET(A != NULL);
1322 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001323
Hanno Becker73d7d792018-12-11 10:35:51 +00001324 s = A->s;
David Horstmannceeaeb92023-01-05 15:44:23 +00001325 if (A->s * B->s * flip_B < 0) {
1326 int cmp = mbedtls_mpi_cmp_abs(A, B);
1327 if (cmp >= 0) {
1328 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine581c4602022-11-09 22:02:16 +01001329 /* If |A| = |B|, the result is 0 and we must set the sign bit
1330 * to +1 regardless of which of A or B was negative. Otherwise,
1331 * since |A| > |B|, the sign is the sign of A. */
1332 X->s = cmp == 0 ? 1 : s;
David Horstmannceeaeb92023-01-05 15:44:23 +00001333 } else {
1334 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine581c4602022-11-09 22:02:16 +01001335 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001336 X->s = -s;
1337 }
David Horstmannceeaeb92023-01-05 15:44:23 +00001338 } else {
1339 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 X->s = s;
1341 }
1342
1343cleanup:
1344
David Horstmannceeaeb92023-01-05 15:44:23 +00001345 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001346}
1347
1348/*
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001349 * Signed addition: X = A + B
1350 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001351int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001352{
David Horstmannceeaeb92023-01-05 15:44:23 +00001353 return add_sub_mpi(X, A, B, 1);
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001354}
1355
1356/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001357 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001359int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001360{
David Horstmannceeaeb92023-01-05 15:44:23 +00001361 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001362}
1363
1364/*
1365 * Signed addition: X = A + b
1366 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001367int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001368{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001369 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 mbedtls_mpi_uint p[1];
David Horstmannceeaeb92023-01-05 15:44:23 +00001371 MPI_VALIDATE_RET(X != NULL);
1372 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
David Horstmannceeaeb92023-01-05 15:44:23 +00001374 p[0] = mpi_sint_abs(b);
1375 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001376 B.n = 1;
1377 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001378
David Horstmannceeaeb92023-01-05 15:44:23 +00001379 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001380}
1381
1382/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001383 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001385int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001386{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001387 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 mbedtls_mpi_uint p[1];
David Horstmannceeaeb92023-01-05 15:44:23 +00001389 MPI_VALIDATE_RET(X != NULL);
1390 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001391
David Horstmannceeaeb92023-01-05 15:44:23 +00001392 p[0] = mpi_sint_abs(b);
1393 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001394 B.n = 1;
1395 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
David Horstmannceeaeb92023-01-05 15:44:23 +00001397 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001398}
1399
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001400/** Helper for mbedtls_mpi multiplication.
1401 *
1402 * Add \p b * \p s to \p d.
1403 *
1404 * \param i The number of limbs of \p s.
1405 * \param[in] s A bignum to multiply, of size \p i.
1406 * It may overlap with \p d, but only if
1407 * \p d <= \p s.
1408 * Its leading limb must not be \c 0.
1409 * \param[in,out] d The bignum to add to.
1410 * It must be sufficiently large to store the
1411 * result of the multiplication. This means
1412 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1413 * is not known a priori.
1414 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001415 */
1416static
1417#if defined(__APPLE__) && defined(__arm__)
1418/*
1419 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1420 * appears to need this to prevent bad ARM code generation at -O3.
1421 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001422__attribute__((noinline))
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001423#endif
David Horstmannceeaeb92023-01-05 15:44:23 +00001424void mpi_mul_hlp(size_t i,
1425 const mbedtls_mpi_uint *s,
1426 mbedtls_mpi_uint *d,
1427 mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001428{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001429 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001430
1431#if defined(MULADDC_HUIT)
David Horstmannceeaeb92023-01-05 15:44:23 +00001432 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 MULADDC_INIT
1434 MULADDC_HUIT
David Horstmannceeaeb92023-01-05 15:44:23 +00001435 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 }
1437
David Horstmannceeaeb92023-01-05 15:44:23 +00001438 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 MULADDC_INIT
1440 MULADDC_CORE
David Horstmannceeaeb92023-01-05 15:44:23 +00001441 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001442 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001443#else /* MULADDC_HUIT */
David Horstmannceeaeb92023-01-05 15:44:23 +00001444 for (; i >= 16; i -= 16) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001445 MULADDC_INIT
1446 MULADDC_CORE MULADDC_CORE
1447 MULADDC_CORE MULADDC_CORE
1448 MULADDC_CORE MULADDC_CORE
1449 MULADDC_CORE MULADDC_CORE
1450
1451 MULADDC_CORE MULADDC_CORE
1452 MULADDC_CORE MULADDC_CORE
1453 MULADDC_CORE MULADDC_CORE
1454 MULADDC_CORE MULADDC_CORE
David Horstmannceeaeb92023-01-05 15:44:23 +00001455 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001456 }
1457
David Horstmannceeaeb92023-01-05 15:44:23 +00001458 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001459 MULADDC_INIT
1460 MULADDC_CORE MULADDC_CORE
1461 MULADDC_CORE MULADDC_CORE
1462
1463 MULADDC_CORE MULADDC_CORE
1464 MULADDC_CORE MULADDC_CORE
David Horstmannceeaeb92023-01-05 15:44:23 +00001465 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001466 }
1467
David Horstmannceeaeb92023-01-05 15:44:23 +00001468 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001469 MULADDC_INIT
1470 MULADDC_CORE
David Horstmannceeaeb92023-01-05 15:44:23 +00001471 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001472 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001473#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001474
1475 t++;
1476
David Horstmannceeaeb92023-01-05 15:44:23 +00001477 while (c != 0) {
1478 *d += c; c = (*d < c); d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001479 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001480}
1481
1482/*
1483 * Baseline multiplication: X = A * B (HAC 14.12)
1484 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001485int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001486{
Janos Follath24eed8d2019-11-22 13:21:35 +00001487 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001488 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489 mbedtls_mpi TA, TB;
Gilles Peskined65b5002021-06-15 21:44:32 +02001490 int result_is_zero = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +00001491 MPI_VALIDATE_RET(X != NULL);
1492 MPI_VALIDATE_RET(A != NULL);
1493 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001494
David Horstmannceeaeb92023-01-05 15:44:23 +00001495 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001496
David Horstmannceeaeb92023-01-05 15:44:23 +00001497 if (X == A) {
1498 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1499 }
1500 if (X == B) {
1501 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1502 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001503
David Horstmannceeaeb92023-01-05 15:44:23 +00001504 for (i = A->n; i > 0; i--) {
1505 if (A->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001506 break;
David Horstmannceeaeb92023-01-05 15:44:23 +00001507 }
1508 }
1509 if (i == 0) {
Gilles Peskined65b5002021-06-15 21:44:32 +02001510 result_is_zero = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +00001511 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
David Horstmannceeaeb92023-01-05 15:44:23 +00001513 for (j = B->n; j > 0; j--) {
1514 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001515 break;
David Horstmannceeaeb92023-01-05 15:44:23 +00001516 }
1517 }
1518 if (j == 0) {
Gilles Peskined65b5002021-06-15 21:44:32 +02001519 result_is_zero = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +00001520 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001521
David Horstmannceeaeb92023-01-05 15:44:23 +00001522 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1523 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001524
David Horstmannceeaeb92023-01-05 15:44:23 +00001525 for (; j > 0; j--) {
1526 mpi_mul_hlp(i, A->p, X->p + j - 1, B->p[j - 1]);
1527 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001528
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001529 /* If the result is 0, we don't shortcut the operation, which reduces
1530 * but does not eliminate side channels leaking the zero-ness. We do
1531 * need to take care to set the sign bit properly since the library does
1532 * not fully support an MPI object with a value of 0 and s == -1. */
David Horstmannceeaeb92023-01-05 15:44:23 +00001533 if (result_is_zero) {
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001534 X->s = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +00001535 } else {
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001536 X->s = A->s * B->s;
David Horstmannceeaeb92023-01-05 15:44:23 +00001537 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
1539cleanup:
1540
David Horstmannceeaeb92023-01-05 15:44:23 +00001541 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001542
David Horstmannceeaeb92023-01-05 15:44:23 +00001543 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001544}
1545
1546/*
1547 * Baseline multiplication: X = A * b
1548 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001549int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001550{
David Horstmannceeaeb92023-01-05 15:44:23 +00001551 MPI_VALIDATE_RET(X != NULL);
1552 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001554 /* mpi_mul_hlp can't deal with a leading 0. */
1555 size_t n = A->n;
David Horstmannceeaeb92023-01-05 15:44:23 +00001556 while (n > 0 && A->p[n - 1] == 0) {
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001557 --n;
David Horstmannceeaeb92023-01-05 15:44:23 +00001558 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001560 /* The general method below doesn't work if n==0 or b==0. By chance
1561 * calculating the result is trivial in those cases. */
David Horstmannceeaeb92023-01-05 15:44:23 +00001562 if (b == 0 || n == 0) {
1563 return mbedtls_mpi_lset(X, 0);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001564 }
1565
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001566 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001567 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001568 /* In general, A * b requires 1 limb more than b. If
1569 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1570 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001571 * copy() will take care of the growth if needed. However, experimentally,
1572 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001573 * calls to calloc() in ECP code, presumably because it reuses the
1574 * same mpi for a while and this way the mpi is more likely to directly
1575 * grow to its final size. */
David Horstmannceeaeb92023-01-05 15:44:23 +00001576 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1577 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1578 mpi_mul_hlp(n, A->p, X->p, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001579
1580cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +00001581 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001582}
1583
1584/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001585 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1586 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001587 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001588static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1589 mbedtls_mpi_uint u0,
1590 mbedtls_mpi_uint d,
1591 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001592{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001593#if defined(MBEDTLS_HAVE_UDBL)
1594 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001595#else
Simon Butcher9803d072016-01-03 00:24:34 +00001596 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
David Horstmannceeaeb92023-01-05 15:44:23 +00001597 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001598 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1599 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001600 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001601#endif
1602
Simon Butcher15b15d12015-11-26 19:35:03 +00001603 /*
1604 * Check for overflow
1605 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001606 if (0 == d || u1 >= d) {
1607 if (r != NULL) {
Glenn Straussbf4826b2023-01-06 11:29:04 +00001608 *r = ~(mbedtls_mpi_uint) 0u;
David Horstmannceeaeb92023-01-05 15:44:23 +00001609 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001610
Glenn Straussbf4826b2023-01-06 11:29:04 +00001611 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001612 }
1613
1614#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001615 dividend = (mbedtls_t_udbl) u1 << biL;
1616 dividend |= (mbedtls_t_udbl) u0;
1617 quotient = dividend / d;
David Horstmannceeaeb92023-01-05 15:44:23 +00001618 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1619 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1620 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001621
David Horstmannceeaeb92023-01-05 15:44:23 +00001622 if (r != NULL) {
1623 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1624 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001625
1626 return (mbedtls_mpi_uint) quotient;
1627#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001628
1629 /*
1630 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1631 * Vol. 2 - Seminumerical Algorithms, Knuth
1632 */
1633
1634 /*
1635 * Normalize the divisor, d, and dividend, u0, u1
1636 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001637 s = mbedtls_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001638 d = d << s;
1639
1640 u1 = u1 << s;
David Horstmannceeaeb92023-01-05 15:44:23 +00001641 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001642 u0 = u0 << s;
1643
1644 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001645 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001646
1647 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001648 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001649
1650 /*
1651 * Find the first quotient and remainder
1652 */
1653 q1 = u1 / d1;
1654 r0 = u1 - d1 * q1;
1655
David Horstmannceeaeb92023-01-05 15:44:23 +00001656 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001657 q1 -= 1;
1658 r0 += d1;
1659
David Horstmannceeaeb92023-01-05 15:44:23 +00001660 if (r0 >= radix) {
1661 break;
1662 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001663 }
1664
David Horstmannceeaeb92023-01-05 15:44:23 +00001665 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001666 q0 = rAX / d1;
1667 r0 = rAX - q0 * d1;
1668
David Horstmannceeaeb92023-01-05 15:44:23 +00001669 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001670 q0 -= 1;
1671 r0 += d1;
1672
David Horstmannceeaeb92023-01-05 15:44:23 +00001673 if (r0 >= radix) {
1674 break;
1675 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001676 }
1677
David Horstmannceeaeb92023-01-05 15:44:23 +00001678 if (r != NULL) {
1679 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1680 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001681
1682 quotient = q1 * radix + q0;
1683
1684 return quotient;
1685#endif
1686}
1687
1688/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001689 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001691int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1692 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001693{
Janos Follath24eed8d2019-11-22 13:21:35 +00001694 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001695 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001697 mbedtls_mpi_uint TP2[3];
David Horstmannceeaeb92023-01-05 15:44:23 +00001698 MPI_VALIDATE_RET(A != NULL);
1699 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001700
David Horstmannceeaeb92023-01-05 15:44:23 +00001701 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1702 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1703 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
David Horstmannceeaeb92023-01-05 15:44:23 +00001705 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1706 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001707 /*
1708 * Avoid dynamic memory allocations for constant-size T2.
1709 *
1710 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1711 * so nobody increase the size of the MPI and we're safe to use an on-stack
1712 * buffer.
1713 */
Alexander K35d6d462019-10-31 14:46:45 +03001714 T2.s = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +00001715 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001716 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001717
David Horstmannceeaeb92023-01-05 15:44:23 +00001718 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1719 if (Q != NULL) {
1720 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1721 }
1722 if (R != NULL) {
1723 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1724 }
1725 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 }
1727
David Horstmannceeaeb92023-01-05 15:44:23 +00001728 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1729 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001730 X.s = Y.s = 1;
1731
David Horstmannceeaeb92023-01-05 15:44:23 +00001732 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1733 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1734 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001735
David Horstmannceeaeb92023-01-05 15:44:23 +00001736 k = mbedtls_mpi_bitlen(&Y) % biL;
1737 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001738 k = biL - 1 - k;
David Horstmannceeaeb92023-01-05 15:44:23 +00001739 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1740 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1741 } else {
1742 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001743 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001744
1745 n = X.n - 1;
1746 t = Y.n - 1;
David Horstmannceeaeb92023-01-05 15:44:23 +00001747 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
David Horstmannceeaeb92023-01-05 15:44:23 +00001749 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001750 Z.p[n - t]++;
David Horstmannceeaeb92023-01-05 15:44:23 +00001751 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001752 }
David Horstmannceeaeb92023-01-05 15:44:23 +00001753 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
David Horstmannceeaeb92023-01-05 15:44:23 +00001755 for (i = n; i > t; i--) {
1756 if (X.p[i] >= Y.p[t]) {
Glenn Straussbf4826b2023-01-06 11:29:04 +00001757 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
David Horstmannceeaeb92023-01-05 15:44:23 +00001758 } else {
1759 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1760 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001761 }
1762
David Horstmannceeaeb92023-01-05 15:44:23 +00001763 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1764 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001765 T2.p[2] = X.p[i];
1766
Paul Bakker5121ce52009-01-03 21:22:43 +00001767 Z.p[i - t - 1]++;
David Horstmannceeaeb92023-01-05 15:44:23 +00001768 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001769 Z.p[i - t - 1]--;
1770
David Horstmannceeaeb92023-01-05 15:44:23 +00001771 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1772 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001773 T1.p[1] = Y.p[t];
David Horstmannceeaeb92023-01-05 15:44:23 +00001774 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1775 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001776
David Horstmannceeaeb92023-01-05 15:44:23 +00001777 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1778 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1779 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001780
David Horstmannceeaeb92023-01-05 15:44:23 +00001781 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1782 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1783 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1784 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001785 Z.p[i - t - 1]--;
1786 }
1787 }
1788
David Horstmannceeaeb92023-01-05 15:44:23 +00001789 if (Q != NULL) {
1790 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001791 Q->s = A->s * B->s;
1792 }
1793
David Horstmannceeaeb92023-01-05 15:44:23 +00001794 if (R != NULL) {
1795 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001796 X.s = A->s;
David Horstmannceeaeb92023-01-05 15:44:23 +00001797 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001798
David Horstmannceeaeb92023-01-05 15:44:23 +00001799 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001800 R->s = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +00001801 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001802 }
1803
1804cleanup:
1805
David Horstmannceeaeb92023-01-05 15:44:23 +00001806 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1807 mbedtls_mpi_free(&T1);
1808 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
David Horstmannceeaeb92023-01-05 15:44:23 +00001810 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001811}
1812
1813/*
1814 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001815 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001816int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1817 const mbedtls_mpi *A,
1818 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001819{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001820 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 mbedtls_mpi_uint p[1];
David Horstmannceeaeb92023-01-05 15:44:23 +00001822 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
David Horstmannceeaeb92023-01-05 15:44:23 +00001824 p[0] = mpi_sint_abs(b);
1825 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001826 B.n = 1;
1827 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
David Horstmannceeaeb92023-01-05 15:44:23 +00001829 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001830}
1831
1832/*
1833 * Modulo: R = A mod B
1834 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001835int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001836{
Janos Follath24eed8d2019-11-22 13:21:35 +00001837 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
David Horstmannceeaeb92023-01-05 15:44:23 +00001838 MPI_VALIDATE_RET(R != NULL);
1839 MPI_VALIDATE_RET(A != NULL);
1840 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
David Horstmannceeaeb92023-01-05 15:44:23 +00001842 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1843 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1844 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001845
David Horstmannceeaeb92023-01-05 15:44:23 +00001846 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001847
David Horstmannceeaeb92023-01-05 15:44:23 +00001848 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1849 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1850 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
David Horstmannceeaeb92023-01-05 15:44:23 +00001852 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1853 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1854 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
1856cleanup:
1857
David Horstmannceeaeb92023-01-05 15:44:23 +00001858 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001859}
1860
1861/*
1862 * Modulo: r = A mod b
1863 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001864int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001865{
Paul Bakker23986e52011-04-24 08:57:21 +00001866 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 mbedtls_mpi_uint x, y, z;
David Horstmannceeaeb92023-01-05 15:44:23 +00001868 MPI_VALIDATE_RET(r != NULL);
1869 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001870
David Horstmannceeaeb92023-01-05 15:44:23 +00001871 if (b == 0) {
1872 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1873 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001874
David Horstmannceeaeb92023-01-05 15:44:23 +00001875 if (b < 0) {
1876 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1877 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
1879 /*
1880 * handle trivial cases
1881 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001882 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001883 *r = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +00001884 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 }
1886
David Horstmannceeaeb92023-01-05 15:44:23 +00001887 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001888 *r = A->p[0] & 1;
David Horstmannceeaeb92023-01-05 15:44:23 +00001889 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001890 }
1891
1892 /*
1893 * general case
1894 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001895 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001896 x = A->p[i - 1];
David Horstmannceeaeb92023-01-05 15:44:23 +00001897 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001898 z = y / b;
1899 y -= z * b;
1900
1901 x <<= biH;
David Horstmannceeaeb92023-01-05 15:44:23 +00001902 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 z = y / b;
1904 y -= z * b;
1905 }
1906
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001907 /*
1908 * If A is negative, then the current y represents a negative value.
1909 * Flipping it to the positive side.
1910 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001911 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001912 y = b - y;
David Horstmannceeaeb92023-01-05 15:44:23 +00001913 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001914
Paul Bakker5121ce52009-01-03 21:22:43 +00001915 *r = y;
1916
David Horstmannceeaeb92023-01-05 15:44:23 +00001917 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001918}
1919
1920/*
1921 * Fast Montgomery initialization (thanks to Tom St Denis)
1922 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001923static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001924{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001926 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
1928 x = m0;
David Horstmannceeaeb92023-01-05 15:44:23 +00001929 x += ((m0 + 2) & 4) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
David Horstmannceeaeb92023-01-05 15:44:23 +00001931 for (i = biL; i >= 8; i /= 2) {
1932 x *= (2 - (m0 * x));
1933 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001934
1935 *mm = ~x + 1;
1936}
1937
Gilles Peskine2a82f722020-06-04 15:00:49 +02001938/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1939 *
1940 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02001941 * It must have at least as many limbs as N
1942 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02001943 * On successful completion, A contains the result of
1944 * the multiplication A * B * R^-1 mod N where
1945 * R = (2^ciL)^n.
1946 * \param[in] B One of the numbers to multiply.
1947 * It must be nonzero and must not have more limbs than N
1948 * (B->n <= N->n).
1949 * \param[in] N The modulo. N must be odd.
1950 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1951 * This is -N^-1 mod 2^ciL.
1952 * \param[in,out] T A bignum for temporary storage.
1953 * It must be at least twice the limb size of N plus 2
1954 * (T->n >= 2 * (N->n + 1)).
1955 * Its initial content is unused and
1956 * its final content is indeterminate.
1957 * Note that unlike the usual convention in the library
1958 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001959 */
David Horstmannceeaeb92023-01-05 15:44:23 +00001960static void mpi_montmul(mbedtls_mpi *A,
1961 const mbedtls_mpi *B,
1962 const mbedtls_mpi *N,
1963 mbedtls_mpi_uint mm,
1964 const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001965{
Paul Bakker23986e52011-04-24 08:57:21 +00001966 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
David Horstmannceeaeb92023-01-05 15:44:23 +00001969 memset(T->p, 0, T->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001970
1971 d = T->p;
1972 n = N->n;
David Horstmannceeaeb92023-01-05 15:44:23 +00001973 m = (B->n < n) ? B->n : n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
David Horstmannceeaeb92023-01-05 15:44:23 +00001975 for (i = 0; i < n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001976 /*
1977 * T = (T + u0*B + u1*N) / 2^biL
1978 */
1979 u0 = A->p[i];
David Horstmannceeaeb92023-01-05 15:44:23 +00001980 u1 = (d[0] + u0 * B->p[0]) * mm;
Paul Bakker5121ce52009-01-03 21:22:43 +00001981
David Horstmannceeaeb92023-01-05 15:44:23 +00001982 mpi_mul_hlp(m, B->p, d, u0);
1983 mpi_mul_hlp(n, N->p, d, u1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
1985 *d++ = u0; d[n + 1] = 0;
1986 }
1987
Gilles Peskine221626f2020-06-08 22:37:50 +02001988 /* At this point, d is either the desired result or the desired result
1989 * plus N. We now potentially subtract N, avoiding leaking whether the
1990 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
Gilles Peskine221626f2020-06-08 22:37:50 +02001992 /* Copy the n least significant limbs of d to A, so that
1993 * A = d if d < N (recall that N has n limbs). */
David Horstmannceeaeb92023-01-05 15:44:23 +00001994 memcpy(A->p, d, n * ciL);
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001995 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02001996 * do the calculation without using conditional tests. */
1997 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02001998 d[n] += 1;
David Horstmannceeaeb92023-01-05 15:44:23 +00001999 d[n] -= mpi_sub_hlp(n, d, d, N->p);
Gilles Peskine221626f2020-06-08 22:37:50 +02002000 /* If d0 < N then d < (2^biL)^n
2001 * so d[n] == 0 and we want to keep A as it is.
2002 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2003 * so d[n] == 1 and we want to set A to the result of the subtraction
2004 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2005 * This exactly corresponds to a conditional assignment. */
David Horstmannceeaeb92023-01-05 15:44:23 +00002006 mbedtls_ct_mpi_uint_cond_assign(n, A->p, d, (unsigned char) d[n]);
Paul Bakker5121ce52009-01-03 21:22:43 +00002007}
2008
2009/*
2010 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002011 *
2012 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002013 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002014static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
2015 mbedtls_mpi_uint mm, const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00002016{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017 mbedtls_mpi_uint z = 1;
2018 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
Paul Bakker8ddb6452013-02-27 14:56:33 +01002020 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002021 U.p = &z;
2022
David Horstmannceeaeb92023-01-05 15:44:23 +00002023 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002024}
2025
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002026/**
2027 * Select an MPI from a table without leaking the index.
2028 *
2029 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2030 * reads the entire table in order to avoid leaking the value of idx to an
2031 * attacker able to observe memory access patterns.
2032 *
2033 * \param[out] R Where to write the selected MPI.
2034 * \param[in] T The table to read from.
2035 * \param[in] T_size The number of elements in the table.
2036 * \param[in] idx The index of the element to select;
2037 * this must satisfy 0 <= idx < T_size.
2038 *
2039 * \return \c 0 on success, or a negative error code.
2040 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002041static 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 +01002042{
2043 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2044
David Horstmannceeaeb92023-01-05 15:44:23 +00002045 for (size_t i = 0; i < T_size; i++) {
2046 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
2047 (unsigned char) mbedtls_ct_size_bool_eq(i,
2048 idx)));
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002049 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002050
2051cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +00002052 return ret;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002053}
2054
Paul Bakker5121ce52009-01-03 21:22:43 +00002055/*
2056 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2057 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002058int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
2059 const mbedtls_mpi *E, const mbedtls_mpi *N,
2060 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00002061{
Janos Follath24eed8d2019-11-22 13:21:35 +00002062 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathd88e2192022-11-21 15:54:20 +00002063 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00002064 size_t i, j, nblimbs;
2065 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 mbedtls_mpi_uint ei, mm, state;
David Horstmannceeaeb92023-01-05 15:44:23 +00002067 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002068 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
David Horstmannceeaeb92023-01-05 15:44:23 +00002070 MPI_VALIDATE_RET(X != NULL);
2071 MPI_VALIDATE_RET(A != NULL);
2072 MPI_VALIDATE_RET(E != NULL);
2073 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002074
David Horstmannceeaeb92023-01-05 15:44:23 +00002075 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
2076 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2077 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
David Horstmannceeaeb92023-01-05 15:44:23 +00002079 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
2080 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2081 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00002082
David Horstmannceeaeb92023-01-05 15:44:23 +00002083 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
2084 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
2085 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2086 }
Chris Jones9246d042020-11-25 15:12:39 +00002087
Paul Bakkerf6198c12012-05-16 08:02:29 +00002088 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002089 * Init temps and window size
2090 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002091 mpi_montg_init(&mm, N);
2092 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
2093 mbedtls_mpi_init(&Apos);
2094 mbedtls_mpi_init(&WW);
2095 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
David Horstmannceeaeb92023-01-05 15:44:23 +00002097 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00002098
David Horstmannceeaeb92023-01-05 15:44:23 +00002099 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
2100 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
David Horstmannceeaeb92023-01-05 15:44:23 +00002102#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
2103 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath66323832022-11-21 14:48:02 +00002104 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
David Horstmannceeaeb92023-01-05 15:44:23 +00002105 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002106#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002107
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002108 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath6fa7a762022-11-22 10:18:06 +00002109
Paul Bakker5121ce52009-01-03 21:22:43 +00002110 /*
Janos Follath6e2d8e32022-11-21 16:14:54 +00002111 * This function is not constant-trace: its memory accesses depend on the
2112 * exponent value. To defend against timing attacks, callers (such as RSA
2113 * and DHM) should use exponent blinding. However this is not enough if the
2114 * adversary can find the exponent in a single trace, so this function
2115 * takes extra precautions against adversaries who can observe memory
2116 * access patterns.
Janos Follath3a3c50c2022-11-11 15:56:38 +00002117 *
Janos Follath6e2d8e32022-11-21 16:14:54 +00002118 * This function performs a series of multiplications by table elements and
2119 * squarings, and we want the prevent the adversary from finding out which
2120 * table element was used, and from distinguishing between multiplications
2121 * and squarings. Firstly, when multiplying by an element of the window
2122 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
2123 * squarings as having a different memory access patterns from other
2124 * multiplications. So secondly, we put the accumulator X in the table as
2125 * well, and also do a constant-trace table lookup to multiply by X.
2126 *
2127 * This way, all multiplications take the form of a lookup-and-multiply.
2128 * The number of lookup-and-multiply operations inside each iteration of
2129 * the main loop still depends on the bits of the exponent, but since the
2130 * other operations in the loop don't have an easily recognizable memory
2131 * trace, an adversary is unlikely to be able to observe the exact
2132 * patterns.
2133 *
2134 * An adversary may still be able to recover the exponent if they can
2135 * observe both memory accesses and branches. However, branch prediction
2136 * exploitation typically requires many traces of execution over the same
2137 * data, which is defeated by randomized blinding.
Janos Follathf0ceb1c2022-11-21 14:31:22 +00002138 *
2139 * To achieve this, we make a copy of X and we use the table entry in each
2140 * calculation from this point on.
Janos Follath91c02862022-10-04 13:27:40 +01002141 */
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002142 const size_t x_index = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +00002143 mbedtls_mpi_init(&W[x_index]);
2144 mbedtls_mpi_copy(&W[x_index], X);
Janos Follathf0ceb1c2022-11-21 14:31:22 +00002145
2146 j = N->n + 1;
2147 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2148 * and mpi_montred() calls later. Here we ensure that W[1] and X are
2149 * large enough, and later we'll grow other W[i] to the same length.
2150 * They must not be shrunk midway through this function!
Janos Follath3a3c50c2022-11-11 15:56:38 +00002151 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002152 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
2153 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
2154 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Janos Follath91c02862022-10-04 13:27:40 +01002155
2156 /*
Paul Bakker50546922012-05-19 08:40:49 +00002157 * Compensate for negative A (and correct at the end)
2158 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002159 neg = (A->s == -1);
2160 if (neg) {
2161 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00002162 Apos.s = 1;
2163 A = &Apos;
2164 }
2165
2166 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002167 * If 1st call, pre-compute R^2 mod N
2168 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002169 if (prec_RR == NULL || prec_RR->p == NULL) {
2170 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
2171 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
2172 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002173
David Horstmannceeaeb92023-01-05 15:44:23 +00002174 if (prec_RR != NULL) {
2175 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
2176 }
2177 } else {
2178 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00002179 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
2181 /*
2182 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2183 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002184 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
2185 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002186 /* This should be a no-op because W[1] is already that large before
2187 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2188 * in mpi_montmul() below, so let's make sure. */
David Horstmannceeaeb92023-01-05 15:44:23 +00002189 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
2190 } else {
2191 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002192 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002193
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002194 /* Note that this is safe because W[1] always has at least N->n limbs
2195 * (it grew above and was preserved by mbedtls_mpi_copy()). */
David Horstmannceeaeb92023-01-05 15:44:23 +00002196 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
2198 /*
Janos Follath91c02862022-10-04 13:27:40 +01002199 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002201 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
2202 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002204
David Horstmannceeaeb92023-01-05 15:44:23 +00002205 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002206 /*
Janos Follathd88e2192022-11-21 15:54:20 +00002207 * W[i] = W[1] ^ i
2208 *
2209 * The first bit of the sliding window is always 1 and therefore we
2210 * only need to store the second half of the table.
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002211 *
2212 * (There are two special elements in the table: W[0] for the
2213 * accumulator/result and W[1] for A in Montgomery form. Both of these
2214 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00002215 */
Janos Follathd88e2192022-11-21 15:54:20 +00002216 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
David Horstmannceeaeb92023-01-05 15:44:23 +00002218 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
2219 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002220
David Horstmannceeaeb92023-01-05 15:44:23 +00002221 for (i = 0; i < window_bitsize - 1; i++) {
2222 mpi_montmul(&W[j], &W[j], N, mm, &T);
2223 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01002224
Paul Bakker5121ce52009-01-03 21:22:43 +00002225 /*
2226 * W[i] = W[i - 1] * W[1]
2227 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002228 for (i = j + 1; i < w_table_used_size; i++) {
2229 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
2230 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
David Horstmannceeaeb92023-01-05 15:44:23 +00002232 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 }
2234 }
2235
2236 nblimbs = E->n;
2237 bufsize = 0;
2238 nbits = 0;
Janos Follath66323832022-11-21 14:48:02 +00002239 size_t exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002240 state = 0;
2241
David Horstmannceeaeb92023-01-05 15:44:23 +00002242 while (1) {
2243 if (bufsize == 0) {
2244 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 break;
David Horstmannceeaeb92023-01-05 15:44:23 +00002246 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002247
Paul Bakker0d7702c2013-10-29 16:18:35 +01002248 nblimbs--;
2249
David Horstmannceeaeb92023-01-05 15:44:23 +00002250 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 }
2252
2253 bufsize--;
2254
2255 ei = (E->p[nblimbs] >> bufsize) & 1;
2256
2257 /*
2258 * skip leading 0s
2259 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002260 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002261 continue;
David Horstmannceeaeb92023-01-05 15:44:23 +00002262 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
David Horstmannceeaeb92023-01-05 15:44:23 +00002264 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 /*
Janos Follath91c02862022-10-04 13:27:40 +01002266 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002268 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
2269 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 continue;
2271 }
2272
2273 /*
2274 * add ei to current window
2275 */
2276 state = 2;
2277
2278 nbits++;
David Horstmannceeaeb92023-01-05 15:44:23 +00002279 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00002280
David Horstmannceeaeb92023-01-05 15:44:23 +00002281 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002282 /*
Janos Follath66323832022-11-21 14:48:02 +00002283 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002284 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002285 for (i = 0; i < window_bitsize; i++) {
2286 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
2287 x_index));
2288 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follath95655a22022-10-04 14:00:09 +01002289 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
2291 /*
Janos Follath66323832022-11-21 14:48:02 +00002292 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002294 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
2295 exponent_bits_in_window));
2296 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
2298 state--;
2299 nbits = 0;
Janos Follath66323832022-11-21 14:48:02 +00002300 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 }
2302 }
2303
2304 /*
2305 * process the remaining bits
2306 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002307 for (i = 0; i < nbits; i++) {
2308 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
2309 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
Janos Follath66323832022-11-21 14:48:02 +00002311 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002312
David Horstmannceeaeb92023-01-05 15:44:23 +00002313 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
2314 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
2315 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follath95655a22022-10-04 14:00:09 +01002316 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 }
2318
2319 /*
Janos Follath91c02862022-10-04 13:27:40 +01002320 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002321 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002322 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002323
David Horstmannceeaeb92023-01-05 15:44:23 +00002324 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath91c02862022-10-04 13:27:40 +01002325 W[x_index].s = -1;
David Horstmannceeaeb92023-01-05 15:44:23 +00002326 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00002327 }
2328
Janos Follath91c02862022-10-04 13:27:40 +01002329 /*
2330 * Load the result in the output variable.
2331 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002332 mbedtls_mpi_copy(X, &W[x_index]);
Janos Follath91c02862022-10-04 13:27:40 +01002333
Paul Bakker5121ce52009-01-03 21:22:43 +00002334cleanup:
2335
Janos Follatha92f9152022-11-21 15:05:31 +00002336 /* The first bit of the sliding window is always 1 and therefore the first
2337 * half of the table was unused. */
David Horstmannceeaeb92023-01-05 15:44:23 +00002338 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
2339 mbedtls_mpi_free(&W[i]);
2340 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
David Horstmannceeaeb92023-01-05 15:44:23 +00002342 mbedtls_mpi_free(&W[x_index]);
2343 mbedtls_mpi_free(&W[1]);
2344 mbedtls_mpi_free(&T);
2345 mbedtls_mpi_free(&Apos);
2346 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00002347
David Horstmannceeaeb92023-01-05 15:44:23 +00002348 if (prec_RR == NULL || prec_RR->p == NULL) {
2349 mbedtls_mpi_free(&RR);
2350 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
David Horstmannceeaeb92023-01-05 15:44:23 +00002352 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002353}
2354
Paul Bakker5121ce52009-01-03 21:22:43 +00002355/*
2356 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2357 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002358int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002359{
Janos Follath24eed8d2019-11-22 13:21:35 +00002360 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002361 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002362 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
David Horstmannceeaeb92023-01-05 15:44:23 +00002364 MPI_VALIDATE_RET(G != NULL);
2365 MPI_VALIDATE_RET(A != NULL);
2366 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002367
David Horstmannceeaeb92023-01-05 15:44:23 +00002368 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
David Horstmannceeaeb92023-01-05 15:44:23 +00002370 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2371 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
David Horstmannceeaeb92023-01-05 15:44:23 +00002373 lz = mbedtls_mpi_lsb(&TA);
2374 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002375
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002376 /* The loop below gives the correct result when A==0 but not when B==0.
2377 * So have a special case for B==0. Leverage the fact that we just
2378 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2379 * slightly more efficient than cmp_int(). */
David Horstmannceeaeb92023-01-05 15:44:23 +00002380 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
2381 ret = mbedtls_mpi_copy(G, A);
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002382 goto cleanup;
2383 }
2384
David Horstmannceeaeb92023-01-05 15:44:23 +00002385 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002386 lz = lzt;
David Horstmannceeaeb92023-01-05 15:44:23 +00002387 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002388
Paul Bakker5121ce52009-01-03 21:22:43 +00002389 TA.s = TB.s = 1;
2390
Gilles Peskineea9aa142021-06-16 13:42:04 +02002391 /* We mostly follow the procedure described in HAC 14.54, but with some
2392 * minor differences:
2393 * - Sequences of multiplications or divisions by 2 are grouped into a
2394 * single shift operation.
Gilles Peskine37d690c2021-06-21 18:58:39 +02002395 * - The procedure in HAC assumes that 0 < TB <= TA.
2396 * - The condition TB <= TA is not actually necessary for correctness.
2397 * TA and TB have symmetric roles except for the loop termination
2398 * condition, and the shifts at the beginning of the loop body
2399 * remove any significance from the ordering of TA vs TB before
2400 * the shifts.
2401 * - If TA = 0, the loop goes through 0 iterations and the result is
2402 * correctly TB.
2403 * - The case TB = 0 was short-circuited above.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002404 *
2405 * For the correctness proof below, decompose the original values of
2406 * A and B as
2407 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2408 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2409 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2410 * and gcd(A',B') is odd or 0.
2411 *
2412 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2413 * The code maintains the following invariant:
2414 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine6537bdb2021-06-15 22:09:39 +02002415 */
2416
Gilles Peskineea9aa142021-06-16 13:42:04 +02002417 /* Proof that the loop terminates:
2418 * At each iteration, either the right-shift by 1 is made on a nonzero
2419 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2420 * by at least 1, or the right-shift by 1 is made on zero and then
2421 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2422 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2423 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002424 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskineea9aa142021-06-16 13:42:04 +02002425 /* Divisions by 2 preserve the invariant (I). */
David Horstmannceeaeb92023-01-05 15:44:23 +00002426 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2427 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
Gilles Peskineea9aa142021-06-16 13:42:04 +02002429 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2430 * TA-TB is even so the division by 2 has an integer result.
2431 * Invariant (I) is preserved since any odd divisor of both TA and TB
2432 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case0e7791f2021-12-20 21:14:10 -08002433 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskineea9aa142021-06-16 13:42:04 +02002434 * divides TA.
2435 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002436 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2437 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2438 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2439 } else {
2440 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2441 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002442 }
Gilles Peskineea9aa142021-06-16 13:42:04 +02002443 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002444 }
2445
Gilles Peskineea9aa142021-06-16 13:42:04 +02002446 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2447 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2448 * - If there was at least one loop iteration, then one of TA or TB is odd,
2449 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2450 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2451 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskineb798b352021-06-21 11:40:38 +02002452 * 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 +02002453 */
2454
David Horstmannceeaeb92023-01-05 15:44:23 +00002455 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2456 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002457
2458cleanup:
2459
David Horstmannceeaeb92023-01-05 15:44:23 +00002460 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002461
David Horstmannceeaeb92023-01-05 15:44:23 +00002462 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002463}
2464
Gilles Peskine8f454702021-04-01 15:57:18 +02002465/* Fill X with n_bytes random bytes.
2466 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002467 * The ordering of the bytes returned from the RNG is suitable for
2468 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002469 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002470 * n_bytes must not be 0.
2471 */
2472static int mpi_fill_random_internal(
2473 mbedtls_mpi *X, size_t n_bytes,
David Horstmannceeaeb92023-01-05 15:44:23 +00002474 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Gilles Peskine8f454702021-04-01 15:57:18 +02002475{
2476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
David Horstmannceeaeb92023-01-05 15:44:23 +00002477 const size_t limbs = CHARS_TO_LIMBS(n_bytes);
2478 const size_t overhead = (limbs * ciL) - n_bytes;
Gilles Peskine8f454702021-04-01 15:57:18 +02002479
David Horstmannceeaeb92023-01-05 15:44:23 +00002480 if (X->n < limbs) {
2481 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2482 }
Gilles Peskine8f454702021-04-01 15:57:18 +02002483
David Horstmannceeaeb92023-01-05 15:44:23 +00002484 memset(X->p, 0, overhead);
2485 memset((unsigned char *) X->p + limbs * ciL, 0, (X->n - limbs) * ciL);
2486 MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X->p + overhead, n_bytes));
2487 mpi_bigendian_to_host(X->p, limbs);
Gilles Peskine8f454702021-04-01 15:57:18 +02002488
2489cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +00002490 return ret;
Gilles Peskine8f454702021-04-01 15:57:18 +02002491}
2492
Paul Bakker33dc46b2014-04-30 16:11:39 +02002493/*
2494 * Fill X with size bytes of random.
2495 *
2496 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002497 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002498 * deterministic, eg for tests).
2499 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002500int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2501 int (*f_rng)(void *, unsigned char *, size_t),
2502 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002503{
Janos Follath24eed8d2019-11-22 13:21:35 +00002504 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
David Horstmannceeaeb92023-01-05 15:44:23 +00002505 size_t const limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002506
David Horstmannceeaeb92023-01-05 15:44:23 +00002507 MPI_VALIDATE_RET(X != NULL);
2508 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002509
Hanno Beckerda1655a2017-10-18 14:21:44 +01002510 /* Ensure that target MPI has exactly the necessary number of limbs */
David Horstmannceeaeb92023-01-05 15:44:23 +00002511 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2512 if (size == 0) {
2513 return 0;
2514 }
Paul Bakker287781a2011-03-26 13:18:49 +00002515
David Horstmannceeaeb92023-01-05 15:44:23 +00002516 ret = mpi_fill_random_internal(X, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002517
2518cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +00002519 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002520}
2521
David Horstmannceeaeb92023-01-05 15:44:23 +00002522int mbedtls_mpi_random(mbedtls_mpi *X,
2523 mbedtls_mpi_sint min,
2524 const mbedtls_mpi *N,
2525 int (*f_rng)(void *, unsigned char *, size_t),
2526 void *p_rng)
Gilles Peskine4699fa42021-03-29 22:02:55 +02002527{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002528 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002529 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002530 unsigned lt_lower = 1, lt_upper = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +00002531 size_t n_bits = mbedtls_mpi_bitlen(N);
2532 size_t n_bytes = (n_bits + 7) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002533 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002534
David Horstmannceeaeb92023-01-05 15:44:23 +00002535 if (min < 0) {
2536 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2537 }
2538 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2539 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2540 }
Gilles Peskine9312ba52021-03-29 22:14:51 +02002541
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002542 /*
2543 * When min == 0, each try has at worst a probability 1/2 of failing
2544 * (the msb has a probability 1/2 of being 0, and then the result will
2545 * be < N), so after 30 tries failure probability is a most 2**(-30).
2546 *
2547 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002548 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002549 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002550 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002551 * a probability of failing that is almost 1/2.
2552 *
2553 * The probabilities are almost the same if min is nonzero but negligible
2554 * compared to N. This is always the case when N is crypto-sized, but
2555 * it's convenient to support small N for testing purposes. When N
2556 * is small, use a higher repeat count, otherwise the probability of
2557 * failure is macroscopic.
2558 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002559 count = (n_bytes > 4 ? 30 : 250);
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002560
David Horstmannceeaeb92023-01-05 15:44:23 +00002561 mbedtls_mpi_init(&lower_bound);
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002562
Gilles Peskine8f454702021-04-01 15:57:18 +02002563 /* Ensure that target MPI has exactly the same number of limbs
2564 * as the upper bound, even if the upper bound has leading zeros.
2565 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
David Horstmannceeaeb92023-01-05 15:44:23 +00002566 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, N->n));
2567 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&lower_bound, N->n));
2568 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&lower_bound, min));
Gilles Peskine8f454702021-04-01 15:57:18 +02002569
Gilles Peskine4699fa42021-03-29 22:02:55 +02002570 /*
2571 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2572 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2573 * - use the same byte ordering;
2574 * - keep the leftmost n_bits bits of the generated octet string;
2575 * - try until result is in the desired range.
2576 * This also avoids any bias, which is especially important for ECDSA.
2577 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002578 do {
2579 MBEDTLS_MPI_CHK(mpi_fill_random_internal(X, n_bytes, f_rng, p_rng));
2580 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, 8 * n_bytes - n_bits));
Gilles Peskine4699fa42021-03-29 22:02:55 +02002581
David Horstmannceeaeb92023-01-05 15:44:23 +00002582 if (--count == 0) {
Gilles Peskine4699fa42021-03-29 22:02:55 +02002583 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2584 goto cleanup;
2585 }
2586
David Horstmannceeaeb92023-01-05 15:44:23 +00002587 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, &lower_bound, &lt_lower));
2588 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, N, &lt_upper));
2589 } while (lt_lower != 0 || lt_upper == 0);
Gilles Peskine4699fa42021-03-29 22:02:55 +02002590
2591cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +00002592 mbedtls_mpi_free(&lower_bound);
2593 return ret;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002594}
2595
Paul Bakker5121ce52009-01-03 21:22:43 +00002596/*
2597 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2598 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002599int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002600{
Janos Follath24eed8d2019-11-22 13:21:35 +00002601 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002602 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
David Horstmannceeaeb92023-01-05 15:44:23 +00002603 MPI_VALIDATE_RET(X != NULL);
2604 MPI_VALIDATE_RET(A != NULL);
2605 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002606
David Horstmannceeaeb92023-01-05 15:44:23 +00002607 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2608 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2609 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002610
David Horstmannceeaeb92023-01-05 15:44:23 +00002611 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2612 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2613 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002614
David Horstmannceeaeb92023-01-05 15:44:23 +00002615 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002616
David Horstmannceeaeb92023-01-05 15:44:23 +00002617 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002619 goto cleanup;
2620 }
2621
David Horstmannceeaeb92023-01-05 15:44:23 +00002622 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2623 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2624 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2625 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002626
David Horstmannceeaeb92023-01-05 15:44:23 +00002627 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2628 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2629 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2630 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002631
David Horstmannceeaeb92023-01-05 15:44:23 +00002632 do {
2633 while ((TU.p[0] & 1) == 0) {
2634 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002635
David Horstmannceeaeb92023-01-05 15:44:23 +00002636 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2637 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2638 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002639 }
2640
David Horstmannceeaeb92023-01-05 15:44:23 +00002641 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2642 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002643 }
2644
David Horstmannceeaeb92023-01-05 15:44:23 +00002645 while ((TV.p[0] & 1) == 0) {
2646 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002647
David Horstmannceeaeb92023-01-05 15:44:23 +00002648 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2649 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2650 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002651 }
2652
David Horstmannceeaeb92023-01-05 15:44:23 +00002653 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2654 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002655 }
2656
David Horstmannceeaeb92023-01-05 15:44:23 +00002657 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2658 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2659 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2660 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2661 } else {
2662 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2663 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2664 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002665 }
David Horstmannceeaeb92023-01-05 15:44:23 +00002666 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2667
2668 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2669 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002670 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002671
David Horstmannceeaeb92023-01-05 15:44:23 +00002672 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2673 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2674 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002675
David Horstmannceeaeb92023-01-05 15:44:23 +00002676 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002677
2678cleanup:
2679
David Horstmannceeaeb92023-01-05 15:44:23 +00002680 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2681 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2682 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
David Horstmannceeaeb92023-01-05 15:44:23 +00002684 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002685}
2686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002688
Paul Bakker5121ce52009-01-03 21:22:43 +00002689static const int small_prime[] =
2690{
David Horstmannceeaeb92023-01-05 15:44:23 +00002691 3, 5, 7, 11, 13, 17, 19, 23,
2692 29, 31, 37, 41, 43, 47, 53, 59,
2693 61, 67, 71, 73, 79, 83, 89, 97,
2694 101, 103, 107, 109, 113, 127, 131, 137,
2695 139, 149, 151, 157, 163, 167, 173, 179,
2696 181, 191, 193, 197, 199, 211, 223, 227,
2697 229, 233, 239, 241, 251, 257, 263, 269,
2698 271, 277, 281, 283, 293, 307, 311, 313,
2699 317, 331, 337, 347, 349, 353, 359, 367,
2700 373, 379, 383, 389, 397, 401, 409, 419,
2701 421, 431, 433, 439, 443, 449, 457, 461,
2702 463, 467, 479, 487, 491, 499, 503, 509,
2703 521, 523, 541, 547, 557, 563, 569, 571,
2704 577, 587, 593, 599, 601, 607, 613, 617,
2705 619, 631, 641, 643, 647, 653, 659, 661,
2706 673, 677, 683, 691, 701, 709, 719, 727,
2707 733, 739, 743, 751, 757, 761, 769, 773,
2708 787, 797, 809, 811, 821, 823, 827, 829,
2709 839, 853, 857, 859, 863, 877, 881, 883,
2710 887, 907, 911, 919, 929, 937, 941, 947,
2711 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002712};
2713
2714/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002715 * Small divisors test (X must be positive)
2716 *
2717 * Return values:
2718 * 0: no small factor (possible prime, more tests needed)
2719 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002720 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002721 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002723static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002724{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002725 int ret = 0;
2726 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002727 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002728
David Horstmannceeaeb92023-01-05 15:44:23 +00002729 if ((X->p[0] & 1) == 0) {
2730 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2731 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002732
David Horstmannceeaeb92023-01-05 15:44:23 +00002733 for (i = 0; small_prime[i] > 0; i++) {
2734 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2735 return 1;
2736 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002737
David Horstmannceeaeb92023-01-05 15:44:23 +00002738 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002739
David Horstmannceeaeb92023-01-05 15:44:23 +00002740 if (r == 0) {
2741 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2742 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002743 }
2744
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002745cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +00002746 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002747}
2748
2749/*
2750 * Miller-Rabin pseudo-primality test (HAC 4.24)
2751 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002752static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2753 int (*f_rng)(void *, unsigned char *, size_t),
2754 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002755{
Pascal Junodb99183d2015-03-11 16:49:45 +01002756 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002757 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002758 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002759
David Horstmannceeaeb92023-01-05 15:44:23 +00002760 MPI_VALIDATE_RET(X != NULL);
2761 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002762
David Horstmannceeaeb92023-01-05 15:44:23 +00002763 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2764 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2765 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002766
Paul Bakker5121ce52009-01-03 21:22:43 +00002767 /*
2768 * W = |X| - 1
2769 * R = W >> lsb( W )
2770 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002771 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2772 s = mbedtls_mpi_lsb(&W);
2773 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2774 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002775
David Horstmannceeaeb92023-01-05 15:44:23 +00002776 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002777 /*
2778 * pick a random A, 1 < A < |X| - 1
2779 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002780 count = 0;
2781 do {
David Horstmannceeaeb92023-01-05 15:44:23 +00002782 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002783
David Horstmannceeaeb92023-01-05 15:44:23 +00002784 j = mbedtls_mpi_bitlen(&A);
2785 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002786 if (j > k) {
David Horstmannceeaeb92023-01-05 15:44:23 +00002787 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002788 }
2789
2790 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002791 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2792 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002793 }
2794
David Horstmannceeaeb92023-01-05 15:44:23 +00002795 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2796 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002797
2798 /*
2799 * A = A^R mod |X|
2800 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002801 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002802
David Horstmannceeaeb92023-01-05 15:44:23 +00002803 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2804 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002805 continue;
David Horstmannceeaeb92023-01-05 15:44:23 +00002806 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002807
2808 j = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +00002809 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002810 /*
2811 * A = A * A mod |X|
2812 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002813 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2814 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002815
David Horstmannceeaeb92023-01-05 15:44:23 +00002816 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002817 break;
David Horstmannceeaeb92023-01-05 15:44:23 +00002818 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002819
2820 j++;
2821 }
2822
2823 /*
2824 * not prime if A != |X| - 1 or A == 1
2825 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002826 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2827 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002828 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002829 break;
2830 }
2831 }
2832
2833cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +00002834 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2835 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2836 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002837
David Horstmannceeaeb92023-01-05 15:44:23 +00002838 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002839}
2840
2841/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002842 * Pseudo-primality test: small factors, then Miller-Rabin
2843 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002844int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2845 int (*f_rng)(void *, unsigned char *, size_t),
2846 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002847{
Janos Follath24eed8d2019-11-22 13:21:35 +00002848 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002849 mbedtls_mpi XX;
David Horstmannceeaeb92023-01-05 15:44:23 +00002850 MPI_VALIDATE_RET(X != NULL);
2851 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002852
2853 XX.s = 1;
2854 XX.n = X->n;
2855 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002856
David Horstmannceeaeb92023-01-05 15:44:23 +00002857 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2858 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2859 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002860 }
2861
David Horstmannceeaeb92023-01-05 15:44:23 +00002862 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2863 return 0;
2864 }
2865
2866 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2867 if (ret == 1) {
2868 return 0;
2869 }
2870
2871 return ret;
2872 }
2873
2874 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002875}
2876
Janos Follatha0b67c22018-09-18 14:48:23 +01002877#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002878/*
2879 * Pseudo-primality test, error probability 2^-80
2880 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002881int mbedtls_mpi_is_prime(const mbedtls_mpi *X,
2882 int (*f_rng)(void *, unsigned char *, size_t),
2883 void *p_rng)
Janos Follathf301d232018-08-14 13:34:01 +01002884{
David Horstmannceeaeb92023-01-05 15:44:23 +00002885 MPI_VALIDATE_RET(X != NULL);
2886 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002887
Janos Follatha0b67c22018-09-18 14:48:23 +01002888 /*
2889 * In the past our key generation aimed for an error rate of at most
2890 * 2^-80. Since this function is deprecated, aim for the same certainty
2891 * here as well.
2892 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002893 return mbedtls_mpi_is_prime_ext(X, 40, f_rng, p_rng);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002894}
Janos Follatha0b67c22018-09-18 14:48:23 +01002895#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002896
2897/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002898 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002899 *
Janos Follathf301d232018-08-14 13:34:01 +01002900 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2901 * be either 1024 bits or 1536 bits long, and flags must contain
2902 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002903 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002904int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2905 int (*f_rng)(void *, unsigned char *, size_t),
2906 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002907{
Jethro Beekman66689272018-02-14 19:24:10 -08002908#ifdef MBEDTLS_HAVE_INT64
2909// ceil(2^63.5)
2910#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2911#else
2912// ceil(2^31.5)
2913#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2914#endif
2915 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002916 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002917 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002918 mbedtls_mpi_uint r;
2919 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002920
David Horstmannceeaeb92023-01-05 15:44:23 +00002921 MPI_VALIDATE_RET(X != NULL);
2922 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002923
David Horstmannceeaeb92023-01-05 15:44:23 +00002924 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2925 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2926 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002927
David Horstmannceeaeb92023-01-05 15:44:23 +00002928 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002929
David Horstmannceeaeb92023-01-05 15:44:23 +00002930 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002931
David Horstmannceeaeb92023-01-05 15:44:23 +00002932 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002933 /*
2934 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2935 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002936 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2937 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2938 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2939 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002940 /*
2941 * 2^-100 error probability, number of rounds computed based on HAC,
2942 * fact 4.48
2943 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002944 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2945 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2946 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2947 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002948 }
2949
David Horstmannceeaeb92023-01-05 15:44:23 +00002950 while (1) {
2951 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002952 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
David Horstmannceeaeb92023-01-05 15:44:23 +00002953 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2954 continue;
2955 }
Jethro Beekman66689272018-02-14 19:24:10 -08002956
2957 k = n * biL;
David Horstmannceeaeb92023-01-05 15:44:23 +00002958 if (k > nbits) {
2959 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2960 }
Jethro Beekman66689272018-02-14 19:24:10 -08002961 X->p[0] |= 1;
2962
David Horstmannceeaeb92023-01-05 15:44:23 +00002963 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2964 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002965
David Horstmannceeaeb92023-01-05 15:44:23 +00002966 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002967 goto cleanup;
David Horstmannceeaeb92023-01-05 15:44:23 +00002968 }
2969 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002970 /*
Tom Cosgrove5205c972022-07-28 06:12:08 +01002971 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002972 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2973 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002974 */
Jethro Beekman66689272018-02-14 19:24:10 -08002975
2976 X->p[0] |= 2;
2977
David Horstmannceeaeb92023-01-05 15:44:23 +00002978 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2979 if (r == 0) {
2980 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2981 } else if (r == 1) {
2982 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2983 }
Jethro Beekman66689272018-02-14 19:24:10 -08002984
2985 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
David Horstmannceeaeb92023-01-05 15:44:23 +00002986 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2987 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002988
David Horstmannceeaeb92023-01-05 15:44:23 +00002989 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002990 /*
2991 * First, check small factors for X and Y
2992 * before doing Miller-Rabin on any of them
2993 */
David Horstmannceeaeb92023-01-05 15:44:23 +00002994 if ((ret = mpi_check_small_factors(X)) == 0 &&
2995 (ret = mpi_check_small_factors(&Y)) == 0 &&
2996 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2997 == 0 &&
2998 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2999 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08003000 goto cleanup;
David Horstmannceeaeb92023-01-05 15:44:23 +00003001 }
Jethro Beekman66689272018-02-14 19:24:10 -08003002
David Horstmannceeaeb92023-01-05 15:44:23 +00003003 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08003004 goto cleanup;
David Horstmannceeaeb92023-01-05 15:44:23 +00003005 }
Jethro Beekman66689272018-02-14 19:24:10 -08003006
3007 /*
3008 * Next candidates. We want to preserve Y = (X-1) / 2 and
3009 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3010 * so up Y by 6 and X by 12.
3011 */
David Horstmannceeaeb92023-01-05 15:44:23 +00003012 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
3013 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00003014 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003015 }
3016 }
3017
3018cleanup:
3019
David Horstmannceeaeb92023-01-05 15:44:23 +00003020 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00003021
David Horstmannceeaeb92023-01-05 15:44:23 +00003022 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00003023}
3024
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003025#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003027#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003028
Paul Bakker23986e52011-04-24 08:57:21 +00003029#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003030
3031static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3032{
3033 { 693, 609, 21 },
3034 { 1764, 868, 28 },
3035 { 768454923, 542167814, 1 }
3036};
3037
Paul Bakker5121ce52009-01-03 21:22:43 +00003038/*
3039 * Checkup routine
3040 */
David Horstmannceeaeb92023-01-05 15:44:23 +00003041int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00003042{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003043 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003044 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003045
David Horstmannceeaeb92023-01-05 15:44:23 +00003046 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
3047 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003048
David Horstmannceeaeb92023-01-05 15:44:23 +00003049 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
3050 "EFE021C2645FD1DC586E69184AF4A31E" \
3051 "D5F53E93B5F123FA41680867BA110131" \
3052 "944FE7952E2517337780CB0DB80E61AA" \
3053 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003054
David Horstmannceeaeb92023-01-05 15:44:23 +00003055 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
3056 "B2E7EFD37075B9F03FF989C7C5051C20" \
3057 "34D2A323810251127E7BF8625A4F49A5" \
3058 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3059 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003060
David Horstmannceeaeb92023-01-05 15:44:23 +00003061 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
3062 "0066A198186C18C10B2F5ED9B522752A" \
3063 "9830B69916E535C8F047518A889A43A5" \
3064 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003065
David Horstmannceeaeb92023-01-05 15:44:23 +00003066 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003067
David Horstmannceeaeb92023-01-05 15:44:23 +00003068 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3069 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3070 "9E857EA95A03512E2BAE7391688D264A" \
3071 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3072 "8001B72E848A38CAE1C65F78E56ABDEF" \
3073 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3074 "ECF677152EF804370C1A305CAF3B5BF1" \
3075 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003076
David Horstmannceeaeb92023-01-05 15:44:23 +00003077 if (verbose != 0) {
3078 mbedtls_printf(" MPI test #1 (mul_mpi): ");
3079 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003080
David Horstmannceeaeb92023-01-05 15:44:23 +00003081 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3082 if (verbose != 0) {
3083 mbedtls_printf("failed\n");
3084 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003085
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003086 ret = 1;
3087 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003088 }
3089
David Horstmannceeaeb92023-01-05 15:44:23 +00003090 if (verbose != 0) {
3091 mbedtls_printf("passed\n");
3092 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003093
David Horstmannceeaeb92023-01-05 15:44:23 +00003094 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003095
David Horstmannceeaeb92023-01-05 15:44:23 +00003096 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3097 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003098
David Horstmannceeaeb92023-01-05 15:44:23 +00003099 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
3100 "6613F26162223DF488E9CD48CC132C7A" \
3101 "0AC93C701B001B092E4E5B9F73BCD27B" \
3102 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003103
David Horstmannceeaeb92023-01-05 15:44:23 +00003104 if (verbose != 0) {
3105 mbedtls_printf(" MPI test #2 (div_mpi): ");
3106 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003107
David Horstmannceeaeb92023-01-05 15:44:23 +00003108 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
3109 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
3110 if (verbose != 0) {
3111 mbedtls_printf("failed\n");
3112 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003113
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003114 ret = 1;
3115 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003116 }
3117
David Horstmannceeaeb92023-01-05 15:44:23 +00003118 if (verbose != 0) {
3119 mbedtls_printf("passed\n");
3120 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003121
David Horstmannceeaeb92023-01-05 15:44:23 +00003122 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00003123
David Horstmannceeaeb92023-01-05 15:44:23 +00003124 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3125 "36E139AEA55215609D2816998ED020BB" \
3126 "BD96C37890F65171D948E9BC7CBAA4D9" \
3127 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003128
David Horstmannceeaeb92023-01-05 15:44:23 +00003129 if (verbose != 0) {
3130 mbedtls_printf(" MPI test #3 (exp_mod): ");
3131 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003132
David Horstmannceeaeb92023-01-05 15:44:23 +00003133 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3134 if (verbose != 0) {
3135 mbedtls_printf("failed\n");
3136 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003137
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003138 ret = 1;
3139 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003140 }
3141
David Horstmannceeaeb92023-01-05 15:44:23 +00003142 if (verbose != 0) {
3143 mbedtls_printf("passed\n");
3144 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003145
David Horstmannceeaeb92023-01-05 15:44:23 +00003146 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003147
David Horstmannceeaeb92023-01-05 15:44:23 +00003148 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3149 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3150 "C3DBA76456363A10869622EAC2DD84EC" \
3151 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003152
David Horstmannceeaeb92023-01-05 15:44:23 +00003153 if (verbose != 0) {
3154 mbedtls_printf(" MPI test #4 (inv_mod): ");
3155 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003156
David Horstmannceeaeb92023-01-05 15:44:23 +00003157 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3158 if (verbose != 0) {
3159 mbedtls_printf("failed\n");
3160 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003161
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003162 ret = 1;
3163 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003164 }
3165
David Horstmannceeaeb92023-01-05 15:44:23 +00003166 if (verbose != 0) {
3167 mbedtls_printf("passed\n");
3168 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003169
David Horstmannceeaeb92023-01-05 15:44:23 +00003170 if (verbose != 0) {
3171 mbedtls_printf(" MPI test #5 (simple gcd): ");
3172 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003173
David Horstmannceeaeb92023-01-05 15:44:23 +00003174 for (i = 0; i < GCD_PAIR_COUNT; i++) {
3175 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
3176 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003177
David Horstmannceeaeb92023-01-05 15:44:23 +00003178 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003179
David Horstmannceeaeb92023-01-05 15:44:23 +00003180 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
3181 if (verbose != 0) {
3182 mbedtls_printf("failed at %d\n", i);
3183 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003184
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003185 ret = 1;
3186 goto cleanup;
3187 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003188 }
3189
David Horstmannceeaeb92023-01-05 15:44:23 +00003190 if (verbose != 0) {
3191 mbedtls_printf("passed\n");
3192 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003193
Paul Bakker5121ce52009-01-03 21:22:43 +00003194cleanup:
3195
David Horstmannceeaeb92023-01-05 15:44:23 +00003196 if (ret != 0 && verbose != 0) {
3197 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
3198 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003199
David Horstmannceeaeb92023-01-05 15:44:23 +00003200 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
3201 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003202
David Horstmannceeaeb92023-01-05 15:44:23 +00003203 if (verbose != 0) {
3204 mbedtls_printf("\n");
3205 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003206
David Horstmannceeaeb92023-01-05 15:44:23 +00003207 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00003208}
3209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003210#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003212#endif /* MBEDTLS_BIGNUM_C */