blob: 154bbed8b60f4e890ac631b2fd84de448c327ae9 [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
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020040# include "mbedtls/bignum.h"
41# include "bn_mul.h"
42# include "mbedtls/platform_util.h"
43# include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000044
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020045# include <string.h>
Rich Evans00ab4702015-02-06 13:43:58 +000046
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020047# if defined(MBEDTLS_PLATFORM_C)
48# include "mbedtls/platform.h"
49# else
50# include <stdio.h>
51# include <stdlib.h>
52# define mbedtls_printf printf
53# define mbedtls_calloc calloc
54# define mbedtls_free free
55# endif
Paul Bakker6e339b52013-07-03 13:37:05 +020056
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020057# define MPI_VALIDATE_RET(cond) \
58 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
59# define MPI_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker73d7d792018-12-11 10:35:51 +000060
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020061# define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
62# define biL (ciL << 3) /* bits in limb */
63# define biH (ciL << 2) /* half limb size */
Paul Bakker5121ce52009-01-03 21:22:43 +000064
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020065# define MPI_SIZE_T_MAX ((size_t)-1) /* SIZE_T_MAX is not standard */
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010066
Paul Bakker5121ce52009-01-03 21:22:43 +000067/*
68 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020069 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000070 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020071# define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0))
72# define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0))
Paul Bakker5121ce52009-01-03 21:22:43 +000073
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050074/* Implementation that should never be optimized out by the compiler */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020075static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050076{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020077 mbedtls_platform_zeroize(v, ciL * n);
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050078}
79
Paul Bakker5121ce52009-01-03 21:22:43 +000080/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000082 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020083void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000084{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020085 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +000086
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 X->s = 1;
88 X->n = 0;
89 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000090}
91
92/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000094 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020095void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000096{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020097 if (X == NULL)
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000099
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200100 if (X->p != NULL) {
101 mbedtls_mpi_zeroize(X->p, X->n);
102 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000103 }
104
Paul Bakker6c591fa2011-05-05 11:49:20 +0000105 X->s = 1;
106 X->n = 0;
107 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000108}
109
110/*
111 * Enlarge to the specified number of limbs
112 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200113int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +0000114{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115 mbedtls_mpi_uint *p;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200116 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000117
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200118 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS)
119 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Paul Bakkerf9688572011-05-05 10:00:45 +0000120
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200121 if (X->n < nblimbs) {
122 if ((p = (mbedtls_mpi_uint *)mbedtls_calloc(nblimbs, ciL)) == NULL)
123 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200125 if (X->p != NULL) {
126 memcpy(p, X->p, X->n * ciL);
127 mbedtls_mpi_zeroize(X->p, X->n);
128 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000129 }
130
131 X->n = nblimbs;
132 X->p = p;
133 }
134
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200135 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000136}
137
138/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100139 * Resize down as much as possible,
140 * while keeping at least the specified number of limbs
141 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200142int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100145 size_t i;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200146 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000147
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200148 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS)
149 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100151 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200152 if (X->n <= nblimbs)
153 return mbedtls_mpi_grow(X, nblimbs);
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
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200156 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;
159 i++;
160
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200161 if (i < nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100162 i = nblimbs;
163
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200164 if ((p = (mbedtls_mpi_uint *)mbedtls_calloc(i, ciL)) == NULL)
165 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100166
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200167 if (X->p != NULL) {
168 memcpy(p, X->p, i * ciL);
169 mbedtls_mpi_zeroize(X->p, X->n);
170 mbedtls_free(X->p);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171 }
172
173 X->n = i;
174 X->p = p;
175
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200176 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100177}
178
Gilles Peskineed32b572021-06-02 22:17:52 +0200179/* Resize X to have exactly n limbs and set it to 0. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200180static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200181{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200182 if (limbs == 0) {
183 mbedtls_mpi_free(X);
184 return 0;
185 } else if (X->n == limbs) {
186 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200187 X->s = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200188 return 0;
189 } else {
190 mbedtls_mpi_free(X);
191 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200192 }
193}
194
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100195/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200196 * Copy the contents of Y into X.
197 *
198 * This function is not constant-time. Leading zeros in Y may be removed.
199 *
200 * Ensure that X does not shrink. This is not guaranteed by the public API,
201 * but some code in the bignum module relies on this property, for example
202 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000203 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200204int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000205{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100206 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000207 size_t i;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200208 MPI_VALIDATE_RET(X != NULL);
209 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000210
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200211 if (X == Y)
212 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000213
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200214 if (Y->n == 0) {
215 if (X->n != 0) {
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200216 X->s = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200217 memset(X->p, 0, X->n * ciL);
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200218 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200219 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200220 }
221
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200222 for (i = Y->n - 1; i > 0; i--)
223 if (Y->p[i] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 break;
225 i++;
226
227 X->s = Y->s;
228
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200229 if (X->n < i) {
230 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
231 } else {
232 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100233 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000234
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200235 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000236
237cleanup:
238
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200239 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000240}
241
242/*
243 * Swap the contents of X and Y
244 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200245void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000246{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 mbedtls_mpi T;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200248 MPI_VALIDATE(X != NULL);
249 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000250
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200251 memcpy(&T, X, sizeof(mbedtls_mpi));
252 memcpy(X, Y, sizeof(mbedtls_mpi));
253 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000254}
255
Manuel Pégourié-Gonnard3ae4ae42021-06-07 09:51:00 +0200256/**
257 * Select between two sign values in constant-time.
258 *
259 * This is functionally equivalent to second ? a : b but uses only bit
260 * operations in order to avoid branches.
261 *
262 * \param[in] a The first sign; must be either +1 or -1.
263 * \param[in] b The second sign; must be either +1 or -1.
264 * \param[in] second Must be either 1 (return b) or 0 (return a).
265 *
266 * \return The selected sign value.
267 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200268static int mpi_safe_cond_select_sign(int a, int b, unsigned char second)
Manuel Pégourié-Gonnard3ae4ae42021-06-07 09:51:00 +0200269{
270 /* In order to avoid questions about what we can reasonnably assume about
271 * the representations of signed integers, move everything to unsigned
272 * by taking advantage of the fact that a and b are either +1 or -1. */
273 unsigned ua = a + 1;
274 unsigned ub = b + 1;
275
Manuel Pégourié-Gonnard31ec1d72021-06-10 09:36:41 +0200276 /* second was 0 or 1, mask is 0 or 2 as are ua and ub */
277 const unsigned mask = second << 1;
Manuel Pégourié-Gonnard3ae4ae42021-06-07 09:51:00 +0200278
279 /* select ua or ub */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200280 unsigned ur = (ua & ~mask) | (ub & mask);
Manuel Pégourié-Gonnard3ae4ae42021-06-07 09:51:00 +0200281
282 /* ur is now 0 or 2, convert back to -1 or +1 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200283 return (int)ur - 1;
Manuel Pégourié-Gonnard3ae4ae42021-06-07 09:51:00 +0200284}
285
Paul Bakker5121ce52009-01-03 21:22:43 +0000286/*
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200287 * Conditionally assign dest = src, without leaking information
288 * about whether the assignment was made or not.
289 * dest and src must be arrays of limbs of size n.
290 * assign must be 0 or 1.
291 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200292static void mpi_safe_cond_assign(size_t n,
293 mbedtls_mpi_uint *dest,
294 const mbedtls_mpi_uint *src,
295 unsigned char assign)
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200296{
297 size_t i;
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200298
299 /* MSVC has a warning about unary minus on unsigned integer types,
300 * but this is well-defined and precisely what we want to do here. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200301# if defined(_MSC_VER)
302# pragma warning(push)
303# pragma warning(disable : 4146)
304# endif
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200305
306 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
307 const mbedtls_mpi_uint mask = -assign;
308
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200309# if defined(_MSC_VER)
310# pragma warning(pop)
311# endif
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200312
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200313 for (i = 0; i < n; i++)
314 dest[i] = (src[i] & mask) | (dest[i] & ~mask);
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200315}
316
317/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100318 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100319 * about whether the assignment was made or not.
320 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100321 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200322int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
323 const mbedtls_mpi *Y,
324 unsigned char assign)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100325{
326 int ret = 0;
327 size_t i;
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200328 mbedtls_mpi_uint limb_mask;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200329 MPI_VALIDATE_RET(X != NULL);
330 MPI_VALIDATE_RET(Y != NULL);
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100331
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200332 /* MSVC has a warning about unary minus on unsigned integer types,
333 * but this is well-defined and precisely what we want to do here. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200334# if defined(_MSC_VER)
335# pragma warning(push)
336# pragma warning(disable : 4146)
337# endif
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200338
Pascal Junodb99183d2015-03-11 16:49:45 +0100339 /* make sure assign is 0 or 1 in a time-constant manner */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200340 assign = (assign | (unsigned char)-assign) >> (sizeof(assign) * 8 - 1);
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200341 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200342 limb_mask = -assign;
343
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200344# if defined(_MSC_VER)
345# pragma warning(pop)
346# endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100347
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200348 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100349
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200350 X->s = mpi_safe_cond_select_sign(X->s, Y->s, assign);
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100351
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200352 mpi_safe_cond_assign(Y->n, X->p, Y->p, assign);
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100353
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200354 for (i = Y->n; i < X->n; i++)
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200355 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100356
357cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200358 return ret;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100359}
360
361/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100362 * Conditionally swap X and Y, without leaking information
363 * about whether the swap was made or not.
364 * Here it is not ok to simply swap the pointers, which whould lead to
365 * different memory access patterns when X and Y are used afterwards.
366 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200367int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
368 mbedtls_mpi *Y,
369 unsigned char swap)
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100370{
371 int ret, s;
372 size_t i;
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200373 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 mbedtls_mpi_uint tmp;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200375 MPI_VALIDATE_RET(X != NULL);
376 MPI_VALIDATE_RET(Y != NULL);
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100377
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200378 if (X == Y)
379 return 0;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100380
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200381 /* MSVC has a warning about unary minus on unsigned integer types,
382 * but this is well-defined and precisely what we want to do here. */
383# if defined(_MSC_VER)
384# pragma warning(push)
385# pragma warning(disable : 4146)
386# endif
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200387
Pascal Junodb99183d2015-03-11 16:49:45 +0100388 /* make sure swap is 0 or 1 in a time-constant manner */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200389 swap = (swap | (unsigned char)-swap) >> (sizeof(swap) * 8 - 1);
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200390 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200391 limb_mask = -swap;
392
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200393# if defined(_MSC_VER)
394# pragma warning(pop)
395# endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100396
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200397 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
398 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100399
400 s = X->s;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200401 X->s = mpi_safe_cond_select_sign(X->s, Y->s, swap);
402 Y->s = mpi_safe_cond_select_sign(Y->s, s, swap);
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100403
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200404 for (i = 0; i < X->n; i++) {
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100405 tmp = X->p[i];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200406 X->p[i] = (X->p[i] & ~limb_mask) | (Y->p[i] & limb_mask);
407 Y->p[i] = (Y->p[i] & ~limb_mask) | (tmp & limb_mask);
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100408 }
409
410cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200411 return ret;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100412}
413
414/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000415 * Set value from integer
416 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200417int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000418{
Janos Follath24eed8d2019-11-22 13:21:35 +0000419 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200420 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000421
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200422 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
423 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000424
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200425 X->p[0] = (z < 0) ? -z : z;
426 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
428cleanup:
429
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200430 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000431}
432
433/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000434 * Get a specific bit
435 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200436int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000437{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200438 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000439
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200440 if (X->n * biL <= pos)
441 return 0;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000442
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200443 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000444}
445
Gilles Peskine11cdb052018-11-20 16:47:47 +0100446/* Get a specific byte, without range checks. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200447# define GET_BYTE(X, i) (((X)->p[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)
Gilles Peskine11cdb052018-11-20 16:47:47 +0100448
Paul Bakker2f5947e2011-05-18 15:47:11 +0000449/*
450 * Set a bit to a specific value of 0 or 1
451 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200452int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000453{
454 int ret = 0;
455 size_t off = pos / biL;
456 size_t idx = pos % biL;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200457 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000458
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200459 if (val != 0 && val != 1)
460 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker9af723c2014-05-01 13:03:14 +0200461
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200462 if (X->n * biL <= pos) {
463 if (val == 0)
464 return 0;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000465
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200466 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
Paul Bakker2f5947e2011-05-18 15:47:11 +0000467 }
468
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200469 X->p[off] &= ~((mbedtls_mpi_uint)0x01 << idx);
470 X->p[off] |= (mbedtls_mpi_uint)val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000471
472cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200473
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200474 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000475}
476
477/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200478 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000479 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200480size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000481{
Paul Bakker23986e52011-04-24 08:57:21 +0000482 size_t i, j, count = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200483 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200485 for (i = 0; i < X->n; i++)
486 for (j = 0; j < biL; j++, count++)
487 if (((X->p[i] >> j) & 1) != 0)
488 return count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200490 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000491}
492
493/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000494 * Count leading zero bits in a given integer
495 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200496static size_t mbedtls_clz(const mbedtls_mpi_uint x)
Simon Butcher15b15d12015-11-26 19:35:03 +0000497{
498 size_t j;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200499 mbedtls_mpi_uint mask = (mbedtls_mpi_uint)1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000500
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200501 for (j = 0; j < biL; j++) {
502 if (x & mask)
503 break;
Simon Butcher15b15d12015-11-26 19:35:03 +0000504
505 mask >>= 1;
506 }
507
508 return j;
509}
510
511/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200512 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000513 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200514size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000515{
Paul Bakker23986e52011-04-24 08:57:21 +0000516 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000517
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200518 if (X->n == 0)
519 return 0;
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200520
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200521 for (i = X->n - 1; i > 0; i--)
522 if (X->p[i] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000523 break;
524
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200525 j = biL - mbedtls_clz(X->p[i]);
Paul Bakker5121ce52009-01-03 21:22:43 +0000526
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200527 return (i * biL) + j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528}
529
530/*
531 * Return the total size in bytes
532 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200533size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000534{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200535 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536}
537
538/*
539 * Convert an ASCII character to digit value
540 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200541static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000542{
543 *d = 255;
544
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200545 if (c >= 0x30 && c <= 0x39)
546 *d = c - 0x30;
547 if (c >= 0x41 && c <= 0x46)
548 *d = c - 0x37;
549 if (c >= 0x61 && c <= 0x66)
550 *d = c - 0x57;
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200552 if (*d >= (mbedtls_mpi_uint)radix)
553 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
Paul Bakker5121ce52009-01-03 21:22:43 +0000554
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200555 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000556}
557
558/*
559 * Import from an ASCII string
560 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200561int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000562{
Janos Follath24eed8d2019-11-22 13:21:35 +0000563 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000564 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200565 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 mbedtls_mpi_uint d;
567 mbedtls_mpi T;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200568 MPI_VALIDATE_RET(X != NULL);
569 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200571 if (radix < 2 || radix > 16)
572 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200574 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000575
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200576 if (s[0] == 0) {
577 mbedtls_mpi_free(X);
578 return 0;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200579 }
580
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200581 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200582 ++s;
583 sign = -1;
584 }
585
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200586 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000587
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200588 if (radix == 16) {
589 if (slen > MPI_SIZE_T_MAX >> 2)
590 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200591
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200592 n = BITS_TO_LIMBS(slen << 2);
Paul Bakker5121ce52009-01-03 21:22:43 +0000593
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200594 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
595 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +0000596
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200597 for (i = slen, j = 0; i > 0; i--, j++) {
598 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
599 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
Paul Bakker5121ce52009-01-03 21:22:43 +0000600 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200601 } else {
602 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +0000603
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200604 for (i = 0; i < slen; i++) {
605 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
606 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
607 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000608 }
609 }
610
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200611 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0)
Gilles Peskine80f56732021-04-03 18:26:13 +0200612 X->s = -1;
613
Paul Bakker5121ce52009-01-03 21:22:43 +0000614cleanup:
615
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200616 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200618 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000619}
620
621/*
Ron Eldora16fa292018-11-20 14:07:01 +0200622 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200624static int
625mpi_write_hlp(mbedtls_mpi *X, int radix, char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000626{
Janos Follath24eed8d2019-11-22 13:21:35 +0000627 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200629 size_t length = 0;
630 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200632 do {
633 if (length >= buflen) {
634 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200635 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000636
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200637 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
638 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200639 /*
640 * Write the residue in the current position, as an ASCII character.
641 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200642 if (r < 0xA)
643 *(--p_end) = (char)('0' + r);
Ron Eldora16fa292018-11-20 14:07:01 +0200644 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200645 *(--p_end) = (char)('A' + (r - 0xA));
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
Ron Eldora16fa292018-11-20 14:07:01 +0200647 length++;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200648 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200650 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200651 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
653cleanup:
654
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200655 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000656}
657
658/*
659 * Export into an ASCII string
660 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200661int mbedtls_mpi_write_string(const mbedtls_mpi *X,
662 int radix,
663 char *buf,
664 size_t buflen,
665 size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000666{
Paul Bakker23986e52011-04-24 08:57:21 +0000667 int ret = 0;
668 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 mbedtls_mpi T;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200671 MPI_VALIDATE_RET(X != NULL);
672 MPI_VALIDATE_RET(olen != NULL);
673 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000674
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200675 if (radix < 2 || radix > 16)
676 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200678 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
679 if (radix >= 4)
680 n >>= 1; /* Number of 4-adic digits necessary to present
681 * `n`. If radix > 4, this might be a strict
682 * overapproximation of the number of
683 * radix-adic digits needed to present `n`. */
684 if (radix >= 16)
685 n >>= 1; /* Number of hexadecimal digits necessary to
686 * present `n`. */
Hanno Becker23cfea02019-02-04 09:45:07 +0000687
Janos Follath80470622019-03-06 13:43:02 +0000688 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000689 n += 1; /* Compensate for the divisions above, which round down `n`
690 * in case it's not even. */
691 n += 1; /* Potential '-'-sign. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200692 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
693 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200695 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100696 *olen = n;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200697 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000698 }
699
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100700 p = buf;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200701 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200703 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000704 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000705 buflen--;
706 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200708 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000709 int c;
710 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200712 for (i = X->n, k = 0; i > 0; i--) {
713 for (j = ciL; j > 0; j--) {
714 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200716 if (c == 0 && k == 0 && (i + j) != 2)
Paul Bakker5121ce52009-01-03 21:22:43 +0000717 continue;
718
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200719 *(p++) = "0123456789ABCDEF"[c / 16];
720 *(p++) = "0123456789ABCDEF"[c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000721 k = 1;
722 }
723 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200724 } else {
725 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000726
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200727 if (T.s == -1)
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000728 T.s = 1;
729
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200730 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000731 }
732
733 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100734 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
736cleanup:
737
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200738 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200740 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000741}
742
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200743# if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000744/*
745 * Read X from an opened file
746 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200747int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000748{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000750 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000751 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000752 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000753 * Buffer should have space for (short) label and decimal formatted MPI,
754 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000755 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200756 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200758 MPI_VALIDATE_RET(X != NULL);
759 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000760
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200761 if (radix < 2 || radix > 16)
762 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Hanno Becker73d7d792018-12-11 10:35:51 +0000763
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200764 memset(s, 0, sizeof(s));
765 if (fgets(s, sizeof(s) - 1, fin) == NULL)
766 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
Paul Bakker5121ce52009-01-03 21:22:43 +0000767
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200768 slen = strlen(s);
769 if (slen == sizeof(s) - 2)
770 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakkercb37aa52011-11-30 16:00:20 +0000771
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200772 if (slen > 0 && s[slen - 1] == '\n') {
773 slen--;
774 s[slen] = '\0';
775 }
776 if (slen > 0 && s[slen - 1] == '\r') {
777 slen--;
778 s[slen] = '\0';
779 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
781 p = s + slen;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200782 while (p-- > s)
783 if (mpi_get_digit(&d, radix, *p) != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000784 break;
785
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200786 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000787}
788
789/*
790 * Write X into an opened file (or stdout if fout == NULL)
791 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200792int mbedtls_mpi_write_file(const char *p,
793 const mbedtls_mpi *X,
794 int radix,
795 FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000796{
Janos Follath24eed8d2019-11-22 13:21:35 +0000797 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000798 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000799 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000800 * Buffer should have space for (short) label and decimal formatted MPI,
801 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000802 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200803 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
804 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000805
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200806 if (radix < 2 || radix > 16)
807 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000808
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200809 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000810
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200811 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000812
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200813 if (p == NULL)
814 p = "";
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200816 plen = strlen(p);
817 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 s[slen++] = '\r';
819 s[slen++] = '\n';
820
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200821 if (fout != NULL) {
822 if (fwrite(p, 1, plen, fout) != plen ||
823 fwrite(s, 1, slen, fout) != slen)
824 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
825 } else
826 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000827
828cleanup:
829
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200830 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000831}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200832# endif /* MBEDTLS_FS_IO */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100833
834/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
835 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000836
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200837static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000838{
839 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100840 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000841 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100842
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200843 for (i = 0, x_ptr = (unsigned char *)&x; i < ciL; i++, x_ptr++) {
Hanno Becker031d6332019-05-01 17:09:11 +0100844 tmp <<= CHAR_BIT;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200845 tmp |= (mbedtls_mpi_uint)*x_ptr;
Hanno Becker031d6332019-05-01 17:09:11 +0100846 }
847
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200848 return tmp;
Hanno Beckerf8720072018-11-08 11:53:49 +0000849}
850
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200851static mbedtls_mpi_uint mpi_uint_bigendian_to_host(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000852{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200853# if defined(__BYTE_ORDER__)
Hanno Beckerf8720072018-11-08 11:53:49 +0000854
855/* Nothing to do on bigendian systems. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200856# if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
857 return x;
858# endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
Hanno Beckerf8720072018-11-08 11:53:49 +0000859
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200860# if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
Hanno Beckerf8720072018-11-08 11:53:49 +0000861
862/* For GCC and Clang, have builtins for byte swapping. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200863# if defined(__GNUC__) && defined(__GNUC_PREREQ)
864# if __GNUC_PREREQ(4, 3)
865# define have_bswap
866# endif
867# endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000868
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200869# if defined(__clang__) && defined(__has_builtin)
870# if __has_builtin(__builtin_bswap32) && \
871 __has_builtin(__builtin_bswap64)
872# define have_bswap
873# endif
874# endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000875
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200876# if defined(have_bswap)
Hanno Beckerf8720072018-11-08 11:53:49 +0000877 /* The compiler is hopefully able to statically evaluate this! */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200878 switch (sizeof(mbedtls_mpi_uint)) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000879 case 4:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200880 return __builtin_bswap32(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000881 case 8:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200882 return __builtin_bswap64(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000883 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200884# endif
885# endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
886# endif /* __BYTE_ORDER__ */
Hanno Beckerf8720072018-11-08 11:53:49 +0000887
888 /* Fall back to C-based reordering if we don't know the byte order
889 * or we couldn't use a compiler-specific builtin. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200890 return mpi_uint_bigendian_to_host_c(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000891}
892
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200893static void mpi_bigendian_to_host(mbedtls_mpi_uint *const p, size_t limbs)
Hanno Beckerda1655a2017-10-18 14:21:44 +0100894{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100895 mbedtls_mpi_uint *cur_limb_left;
896 mbedtls_mpi_uint *cur_limb_right;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200897 if (limbs == 0)
Hanno Becker2be8a552018-10-25 12:40:09 +0100898 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100899
900 /*
901 * Traverse limbs and
902 * - adapt byte-order in each limb
903 * - swap the limbs themselves.
904 * For that, simultaneously traverse the limbs from left to right
905 * and from right to left, as long as the left index is not bigger
906 * than the right index (it's not a problem if limbs is odd and the
907 * indices coincide in the last iteration).
908 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200909 for (cur_limb_left = p, cur_limb_right = p + (limbs - 1);
910 cur_limb_left <= cur_limb_right; cur_limb_left++, cur_limb_right--) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000911 mbedtls_mpi_uint tmp;
912 /* Note that if cur_limb_left == cur_limb_right,
913 * this code effectively swaps the bytes only once. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200914 tmp = mpi_uint_bigendian_to_host(*cur_limb_left);
915 *cur_limb_left = mpi_uint_bigendian_to_host(*cur_limb_right);
Hanno Beckerf8720072018-11-08 11:53:49 +0000916 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100917 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100918}
919
Paul Bakker5121ce52009-01-03 21:22:43 +0000920/*
Janos Follatha778a942019-02-13 10:28:28 +0000921 * Import X from unsigned binary data, little endian
922 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200923int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
924 const unsigned char *buf,
925 size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000926{
Janos Follath24eed8d2019-11-22 13:21:35 +0000927 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000928 size_t i;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200929 size_t const limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000930
931 /* Ensure that target MPI has exactly the necessary number of limbs */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200932 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000933
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200934 for (i = 0; i < buflen; i++)
935 X->p[i / ciL] |= ((mbedtls_mpi_uint)buf[i]) << ((i % ciL) << 3);
Janos Follatha778a942019-02-13 10:28:28 +0000936
937cleanup:
938
Janos Follath171a7ef2019-02-15 16:17:45 +0000939 /*
940 * This function is also used to import keys. However, wiping the buffers
941 * upon failure is not necessary because failure only can happen before any
942 * input is copied.
943 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200944 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000945}
946
947/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000948 * Import X from unsigned binary data, big endian
949 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200950int mbedtls_mpi_read_binary(mbedtls_mpi *X,
951 const unsigned char *buf,
952 size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000953{
Janos Follath24eed8d2019-11-22 13:21:35 +0000954 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200955 size_t const limbs = CHARS_TO_LIMBS(buflen);
956 size_t const overhead = (limbs * ciL) - buflen;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100957 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000958
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200959 MPI_VALIDATE_RET(X != NULL);
960 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000961
Hanno Becker073c1992017-10-17 15:17:27 +0100962 /* Ensure that target MPI has exactly the necessary number of limbs */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200963 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000964
Gilles Peskineed32b572021-06-02 22:17:52 +0200965 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000966 * even if buflen is 0. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200967 if (buflen != 0) {
968 Xp = (unsigned char *)X->p;
969 memcpy(Xp + overhead, buf, buflen);
Hanno Beckerda1655a2017-10-18 14:21:44 +0100970
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200971 mpi_bigendian_to_host(X->p, limbs);
Hanno Becker0e810b92019-01-03 17:13:11 +0000972 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000973
974cleanup:
975
Janos Follath171a7ef2019-02-15 16:17:45 +0000976 /*
977 * This function is also used to import keys. However, wiping the buffers
978 * upon failure is not necessary because failure only can happen before any
979 * input is copied.
980 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200981 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000982}
983
984/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000985 * Export X into unsigned binary data, little endian
986 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200987int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
988 unsigned char *buf,
989 size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000990{
991 size_t stored_bytes = X->n * ciL;
992 size_t bytes_to_copy;
993 size_t i;
994
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200995 if (stored_bytes < buflen) {
Janos Follathe344d0f2019-02-19 16:17:40 +0000996 bytes_to_copy = stored_bytes;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200997 } else {
Janos Follathe344d0f2019-02-19 16:17:40 +0000998 bytes_to_copy = buflen;
999
1000 /* The output buffer is smaller than the allocated size of X.
1001 * However X may fit if its leading bytes are zero. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001002 for (i = bytes_to_copy; i < stored_bytes; i++) {
1003 if (GET_BYTE(X, i) != 0)
1004 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Janos Follathe344d0f2019-02-19 16:17:40 +00001005 }
1006 }
1007
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001008 for (i = 0; i < bytes_to_copy; i++)
1009 buf[i] = GET_BYTE(X, i);
Janos Follathe344d0f2019-02-19 16:17:40 +00001010
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001011 if (stored_bytes < buflen) {
Janos Follathe344d0f2019-02-19 16:17:40 +00001012 /* Write trailing 0 bytes */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001013 memset(buf + stored_bytes, 0, buflen - stored_bytes);
Janos Follathe344d0f2019-02-19 16:17:40 +00001014 }
1015
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001016 return 0;
Janos Follathe344d0f2019-02-19 16:17:40 +00001017}
1018
1019/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 * Export X into unsigned binary data, big endian
1021 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001022int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
1023 unsigned char *buf,
1024 size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +00001025{
Hanno Becker73d7d792018-12-11 10:35:51 +00001026 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +01001027 size_t bytes_to_copy;
1028 unsigned char *p;
1029 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001030
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001031 MPI_VALIDATE_RET(X != NULL);
1032 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001033
1034 stored_bytes = X->n * ciL;
1035
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001036 if (stored_bytes < buflen) {
Gilles Peskine11cdb052018-11-20 16:47:47 +01001037 /* There is enough space in the output buffer. Write initial
1038 * null bytes and record the position at which to start
1039 * writing the significant bytes. In this case, the execution
1040 * trace of this function does not depend on the value of the
1041 * number. */
1042 bytes_to_copy = stored_bytes;
1043 p = buf + buflen - stored_bytes;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001044 memset(buf, 0, buflen - stored_bytes);
1045 } else {
Gilles Peskine11cdb052018-11-20 16:47:47 +01001046 /* The output buffer is smaller than the allocated size of X.
1047 * However X may fit if its leading bytes are zero. */
1048 bytes_to_copy = buflen;
1049 p = buf;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001050 for (i = bytes_to_copy; i < stored_bytes; i++) {
1051 if (GET_BYTE(X, i) != 0)
1052 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Gilles Peskine11cdb052018-11-20 16:47:47 +01001053 }
1054 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001055
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001056 for (i = 0; i < bytes_to_copy; i++)
1057 p[bytes_to_copy - i - 1] = GET_BYTE(X, i);
Paul Bakker5121ce52009-01-03 21:22:43 +00001058
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001059 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001060}
1061
1062/*
1063 * Left-shift: X <<= count
1064 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001065int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +00001066{
Janos Follath24eed8d2019-11-22 13:21:35 +00001067 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001068 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069 mbedtls_mpi_uint r0 = 0, r1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001070 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001071
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001072 v0 = count / (biL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 t1 = count & (biL - 1);
1074
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001075 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001076
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001077 if (X->n * biL < i)
1078 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001079
1080 ret = 0;
1081
1082 /*
1083 * shift by count / limb_size
1084 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001085 if (v0 > 0) {
1086 for (i = X->n; i > v0; i--)
Paul Bakker23986e52011-04-24 08:57:21 +00001087 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001088
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001089 for (; i > 0; i--)
Paul Bakker23986e52011-04-24 08:57:21 +00001090 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 }
1092
1093 /*
1094 * shift by count % limb_size
1095 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001096 if (t1 > 0) {
1097 for (i = v0; i < X->n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 r1 = X->p[i] >> (biL - t1);
1099 X->p[i] <<= t1;
1100 X->p[i] |= r0;
1101 r0 = r1;
1102 }
1103 }
1104
1105cleanup:
1106
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001107 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001108}
1109
1110/*
1111 * Right-shift: X >>= count
1112 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001113int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +00001114{
Paul Bakker23986e52011-04-24 08:57:21 +00001115 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 mbedtls_mpi_uint r0 = 0, r1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001117 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001118
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001119 v0 = count / biL;
Paul Bakker5121ce52009-01-03 21:22:43 +00001120 v1 = count & (biL - 1);
1121
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001122 if (v0 > X->n || (v0 == X->n && v1 > 0))
1123 return mbedtls_mpi_lset(X, 0);
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001124
Paul Bakker5121ce52009-01-03 21:22:43 +00001125 /*
1126 * shift by count / limb_size
1127 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001128 if (v0 > 0) {
1129 for (i = 0; i < X->n - v0; i++)
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 X->p[i] = X->p[i + v0];
1131
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001132 for (; i < X->n; i++)
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 X->p[i] = 0;
1134 }
1135
1136 /*
1137 * shift by count % limb_size
1138 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001139 if (v1 > 0) {
1140 for (i = X->n; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001141 r1 = X->p[i - 1] << (biL - v1);
1142 X->p[i - 1] >>= v1;
1143 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 r0 = r1;
1145 }
1146 }
1147
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001148 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001149}
1150
1151/*
1152 * Compare unsigned values
1153 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001154int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001155{
Paul Bakker23986e52011-04-24 08:57:21 +00001156 size_t i, j;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001157 MPI_VALIDATE_RET(X != NULL);
1158 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001159
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001160 for (i = X->n; i > 0; i--)
1161 if (X->p[i - 1] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00001162 break;
1163
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001164 for (j = Y->n; j > 0; j--)
1165 if (Y->p[j - 1] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00001166 break;
1167
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001168 if (i == 0 && j == 0)
1169 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001170
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001171 if (i > j)
1172 return 1;
1173 if (j > i)
1174 return -1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001175
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001176 for (; i > 0; i--) {
1177 if (X->p[i - 1] > Y->p[i - 1])
1178 return 1;
1179 if (X->p[i - 1] < Y->p[i - 1])
1180 return -1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 }
1182
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001183 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001184}
1185
1186/*
1187 * Compare signed values
1188 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001189int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001190{
Paul Bakker23986e52011-04-24 08:57:21 +00001191 size_t i, j;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001192 MPI_VALIDATE_RET(X != NULL);
1193 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001195 for (i = X->n; i > 0; i--)
1196 if (X->p[i - 1] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 break;
1198
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001199 for (j = Y->n; j > 0; j--)
1200 if (Y->p[j - 1] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 break;
1202
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001203 if (i == 0 && j == 0)
1204 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001206 if (i > j)
1207 return X->s;
1208 if (j > i)
1209 return -Y->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001210
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001211 if (X->s > 0 && Y->s < 0)
1212 return 1;
1213 if (Y->s > 0 && X->s < 0)
1214 return -1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001216 for (; i > 0; i--) {
1217 if (X->p[i - 1] > Y->p[i - 1])
1218 return X->s;
1219 if (X->p[i - 1] < Y->p[i - 1])
1220 return -X->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001221 }
1222
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001223 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001224}
1225
Janos Follath3f6f0e42019-10-14 09:09:32 +01001226/** Decide if an integer is less than the other, without branches.
1227 *
1228 * \param x First integer.
1229 * \param y Second integer.
1230 *
1231 * \return 1 if \p x is less than \p y, 0 otherwise
1232 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001233static unsigned ct_lt_mpi_uint(const mbedtls_mpi_uint x,
1234 const mbedtls_mpi_uint y)
Janos Follathee6abce2019-09-05 14:47:19 +01001235{
1236 mbedtls_mpi_uint ret;
1237 mbedtls_mpi_uint cond;
1238
1239 /*
1240 * Check if the most significant bits (MSB) of the operands are different.
1241 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001242 cond = (x ^ y);
Janos Follathee6abce2019-09-05 14:47:19 +01001243 /*
1244 * If the MSB are the same then the difference x-y will be negative (and
1245 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1246 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001247 ret = (x - y) & ~cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001248 /*
1249 * If the MSB are different, then the operand with the MSB of 1 is the
1250 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1251 * the MSB of y is 0.)
1252 */
1253 ret |= y & cond;
1254
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001255 ret = ret >> (biL - 1);
Janos Follathee6abce2019-09-05 14:47:19 +01001256
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001257 return (unsigned)ret;
Janos Follathee6abce2019-09-05 14:47:19 +01001258}
1259
1260/*
1261 * Compare signed values in constant time
1262 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001263int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
1264 const mbedtls_mpi *Y,
1265 unsigned *ret)
Janos Follathee6abce2019-09-05 14:47:19 +01001266{
1267 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001268 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001269 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001270
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001271 MPI_VALIDATE_RET(X != NULL);
1272 MPI_VALIDATE_RET(Y != NULL);
1273 MPI_VALIDATE_RET(ret != NULL);
Janos Follathee6abce2019-09-05 14:47:19 +01001274
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001275 if (X->n != Y->n)
Janos Follathee6abce2019-09-05 14:47:19 +01001276 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1277
1278 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001279 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1280 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001281 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001282 X_is_negative = (X->s & 2) >> 1;
1283 Y_is_negative = (Y->s & 2) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001284
1285 /*
1286 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001287 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1288 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001289 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001290 cond = (X_is_negative ^ Y_is_negative);
Janos Follath5e614ce2019-10-28 12:31:34 +00001291 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001292
1293 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001294 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001295 * need to go through the loop. Record if we have the result already.
1296 */
Janos Follathee6abce2019-09-05 14:47:19 +01001297 done = cond;
1298
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001299 for (i = X->n; i > 0; i--) {
Janos Follathee6abce2019-09-05 14:47:19 +01001300 /*
Janos Follath30702422019-11-05 12:24:52 +00001301 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1302 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001303 *
1304 * Again even if we can make a decision, we just mark the result and
1305 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001306 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001307 cond = ct_lt_mpi_uint(Y->p[i - 1], X->p[i - 1]);
1308 *ret |= cond & (1 - done) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001309 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001310
1311 /*
Janos Follath30702422019-11-05 12:24:52 +00001312 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1313 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001314 *
1315 * Again even if we can make a decision, we just mark the result and
1316 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001317 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001318 cond = ct_lt_mpi_uint(X->p[i - 1], Y->p[i - 1]);
1319 *ret |= cond & (1 - done) & (1 - X_is_negative);
Janos Follathc50e6d52019-10-28 12:37:21 +00001320 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001321 }
1322
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001323 return 0;
Janos Follathee6abce2019-09-05 14:47:19 +01001324}
1325
Paul Bakker5121ce52009-01-03 21:22:43 +00001326/*
1327 * Compare signed values
1328 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001329int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +00001330{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 mbedtls_mpi Y;
1332 mbedtls_mpi_uint p[1];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001333 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001335 *p = (z < 0) ? -z : z;
1336 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 Y.n = 1;
1338 Y.p = p;
1339
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001340 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00001341}
1342
1343/*
1344 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1345 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001346int mbedtls_mpi_add_abs(mbedtls_mpi *X,
1347 const mbedtls_mpi *A,
1348 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001349{
Janos Follath24eed8d2019-11-22 13:21:35 +00001350 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001351 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001352 mbedtls_mpi_uint *o, *p, c, tmp;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001353 MPI_VALIDATE_RET(X != NULL);
1354 MPI_VALIDATE_RET(A != NULL);
1355 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001356
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001357 if (X == B) {
1358 const mbedtls_mpi *T = A;
1359 A = X;
1360 B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001361 }
1362
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001363 if (X != A)
1364 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
Paul Bakker9af723c2014-05-01 13:03:14 +02001365
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001366 /*
1367 * X should always be positive as a result of unsigned additions.
1368 */
1369 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001370
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001371 for (j = B->n; j > 0; j--)
1372 if (B->p[j - 1] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 break;
1374
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001375 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001377 o = B->p;
1378 p = X->p;
1379 c = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
Janos Follath6c922682015-10-30 17:43:11 +01001381 /*
1382 * tmp is used because it might happen that p == o
1383 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001384 for (i = 0; i < j; i++, o++, p++) {
1385 tmp = *o;
1386 *p += c;
1387 c = (*p < c);
1388 *p += tmp;
1389 c += (*p < tmp);
Paul Bakker5121ce52009-01-03 21:22:43 +00001390 }
1391
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001392 while (c != 0) {
1393 if (i >= X->n) {
1394 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001395 p = X->p + i;
1396 }
1397
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001398 *p += c;
1399 c = (*p < c);
1400 i++;
1401 p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 }
1403
1404cleanup:
1405
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001406 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001407}
1408
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001409/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001410 * Helper for mbedtls_mpi subtraction.
1411 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001412 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001413 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001414 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001415 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001416 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001417 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001418 * \param n Number of limbs of \p d, \p l and \p r.
1419 * \param[out] d The result of the subtraction.
1420 * \param[in] l The left operand.
1421 * \param[in] r The right operand.
1422 *
1423 * \return 1 if `l < r`.
1424 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001426static mbedtls_mpi_uint mpi_sub_hlp(size_t n,
1427 mbedtls_mpi_uint *d,
1428 const mbedtls_mpi_uint *l,
1429 const mbedtls_mpi_uint *r)
Paul Bakker5121ce52009-01-03 21:22:43 +00001430{
Paul Bakker23986e52011-04-24 08:57:21 +00001431 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001432 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001433
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001434 for (i = 0; i < n; i++) {
1435 z = (l[i] < c);
1436 t = l[i] - c;
1437 c = (t < r[i]) + z;
1438 d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 }
1440
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001441 return c;
Paul Bakker5121ce52009-01-03 21:22:43 +00001442}
1443
1444/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001445 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001446 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001447int mbedtls_mpi_sub_abs(mbedtls_mpi *X,
1448 const mbedtls_mpi *A,
1449 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001450{
Janos Follath24eed8d2019-11-22 13:21:35 +00001451 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001452 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001453 mbedtls_mpi_uint carry;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001454 MPI_VALIDATE_RET(X != NULL);
1455 MPI_VALIDATE_RET(A != NULL);
1456 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001457
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001458 for (n = B->n; n > 0; n--)
1459 if (B->p[n - 1] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00001460 break;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001461 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001462 /* B >= (2^ciL)^n > A */
1463 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1464 goto cleanup;
1465 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001466
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001467 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001468
1469 /* Set the high limbs of X to match A. Don't touch the lower limbs
1470 * because X might be aliased to B, and we must not overwrite the
1471 * significant digits of B. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001472 if (A->n > n)
1473 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1474 if (X->n > A->n)
1475 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001476
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001477 carry = mpi_sub_hlp(n, X->p, A->p, B->p);
1478 if (carry != 0) {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001479 /* Propagate the carry to the first nonzero limb of X. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001480 for (; n < X->n && X->p[n] == 0; n++)
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001481 --X->p[n];
1482 /* If we ran out of space for the carry, it means that the result
1483 * is negative. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001484 if (n == X->n) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001485 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1486 goto cleanup;
1487 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001488 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001489 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001491 /* X should always be positive as a result of unsigned subtractions. */
1492 X->s = 1;
1493
Paul Bakker5121ce52009-01-03 21:22:43 +00001494cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001495 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001496}
1497
1498/*
1499 * Signed addition: X = A + B
1500 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001501int mbedtls_mpi_add_mpi(mbedtls_mpi *X,
1502 const mbedtls_mpi *A,
1503 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001504{
Hanno Becker73d7d792018-12-11 10:35:51 +00001505 int ret, s;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001506 MPI_VALIDATE_RET(X != NULL);
1507 MPI_VALIDATE_RET(A != NULL);
1508 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001509
Hanno Becker73d7d792018-12-11 10:35:51 +00001510 s = A->s;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001511 if (A->s * B->s < 0) {
1512 if (mbedtls_mpi_cmp_abs(A, B) >= 0) {
1513 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
1514 X->s = s;
1515 } else {
1516 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 X->s = -s;
1518 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001519 } else {
1520 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 X->s = s;
1522 }
1523
1524cleanup:
1525
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001526 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001527}
1528
1529/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001530 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001531 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001532int mbedtls_mpi_sub_mpi(mbedtls_mpi *X,
1533 const mbedtls_mpi *A,
1534 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001535{
Hanno Becker73d7d792018-12-11 10:35:51 +00001536 int ret, s;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001537 MPI_VALIDATE_RET(X != NULL);
1538 MPI_VALIDATE_RET(A != NULL);
1539 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001540
Hanno Becker73d7d792018-12-11 10:35:51 +00001541 s = A->s;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001542 if (A->s * B->s > 0) {
1543 if (mbedtls_mpi_cmp_abs(A, B) >= 0) {
1544 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
1545 X->s = s;
1546 } else {
1547 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Paul Bakker5121ce52009-01-03 21:22:43 +00001548 X->s = -s;
1549 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001550 } else {
1551 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001552 X->s = s;
1553 }
1554
1555cleanup:
1556
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001557 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001558}
1559
1560/*
1561 * Signed addition: X = A + b
1562 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001563int mbedtls_mpi_add_int(mbedtls_mpi *X,
1564 const mbedtls_mpi *A,
1565 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001566{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001567 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 mbedtls_mpi_uint p[1];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001569 MPI_VALIDATE_RET(X != NULL);
1570 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001572 p[0] = (b < 0) ? -b : b;
1573 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001574 B.n = 1;
1575 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001576
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001577 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001578}
1579
1580/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001581 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001582 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001583int mbedtls_mpi_sub_int(mbedtls_mpi *X,
1584 const mbedtls_mpi *A,
1585 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001586{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001587 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 mbedtls_mpi_uint p[1];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001589 MPI_VALIDATE_RET(X != NULL);
1590 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001591
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001592 p[0] = (b < 0) ? -b : b;
1593 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001594 B.n = 1;
1595 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001596
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001597 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001598}
1599
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001600/** Helper for mbedtls_mpi multiplication.
1601 *
1602 * Add \p b * \p s to \p d.
1603 *
1604 * \param i The number of limbs of \p s.
1605 * \param[in] s A bignum to multiply, of size \p i.
1606 * It may overlap with \p d, but only if
1607 * \p d <= \p s.
1608 * Its leading limb must not be \c 0.
1609 * \param[in,out] d The bignum to add to.
1610 * It must be sufficiently large to store the
1611 * result of the multiplication. This means
1612 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1613 * is not known a priori.
1614 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001615 */
1616static
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001617# if defined(__APPLE__) && defined(__arm__)
1618 /*
1619 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1620 * appears to need this to prevent bad ARM code generation at -O3.
1621 */
1622 __attribute__((noinline))
1623# endif
1624 void
1625 mpi_mul_hlp(size_t i,
1626 const mbedtls_mpi_uint *s,
1627 mbedtls_mpi_uint *d,
1628 mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001629{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001632# if defined(MULADDC_HUIT)
1633 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001634 MULADDC_INIT
1635 MULADDC_HUIT
1636 MULADDC_STOP
1637 }
1638
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001639 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 MULADDC_INIT
1641 MULADDC_CORE
1642 MULADDC_STOP
1643 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001644# else /* MULADDC_HUIT */
1645 for (; i >= 16; i -= 16) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001646 MULADDC_INIT
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001647 MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE
1648 MULADDC_CORE MULADDC_CORE MULADDC_CORE
Paul Bakker5121ce52009-01-03 21:22:43 +00001649
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001650 MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE
1651 MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001652 }
1653
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001654 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001655 MULADDC_INIT
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001656 MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE
Paul Bakker5121ce52009-01-03 21:22:43 +00001657
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001658 MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_CORE MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001659 }
1660
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001661 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001662 MULADDC_INIT
1663 MULADDC_CORE
1664 MULADDC_STOP
1665 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001666# endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
1668 t++;
1669
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001670 while (c != 0) {
1671 *d += c;
1672 c = (*d < c);
1673 d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001674 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001675}
1676
1677/*
1678 * Baseline multiplication: X = A * B (HAC 14.12)
1679 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001680int mbedtls_mpi_mul_mpi(mbedtls_mpi *X,
1681 const mbedtls_mpi *A,
1682 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001683{
Janos Follath24eed8d2019-11-22 13:21:35 +00001684 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001685 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 mbedtls_mpi TA, TB;
Gilles Peskine997be0a2021-06-15 21:44:32 +02001687 int result_is_zero = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001688 MPI_VALIDATE_RET(X != NULL);
1689 MPI_VALIDATE_RET(A != NULL);
1690 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001692 mbedtls_mpi_init(&TA);
1693 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001695 if (X == A) {
1696 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1697 A = &TA;
1698 }
1699 if (X == B) {
1700 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
1701 B = &TB;
1702 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001704 for (i = A->n; i > 0; i--)
1705 if (A->p[i - 1] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00001706 break;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001707 if (i == 0)
Gilles Peskine997be0a2021-06-15 21:44:32 +02001708 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001709
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001710 for (j = B->n; j > 0; j--)
1711 if (B->p[j - 1] != 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 break;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001713 if (j == 0)
Gilles Peskine997be0a2021-06-15 21:44:32 +02001714 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001715
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001716 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1717 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001718
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001719 for (; j > 0; j--)
1720 mpi_mul_hlp(i, A->p, X->p + j - 1, B->p[j - 1]);
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
Gilles Peskinef4998b02021-06-10 15:51:54 +02001722 /* If the result is 0, we don't shortcut the operation, which reduces
1723 * but does not eliminate side channels leaking the zero-ness. We do
1724 * need to take care to set the sign bit properly since the library does
1725 * not fully support an MPI object with a value of 0 and s == -1. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001726 if (result_is_zero)
Gilles Peskinef4998b02021-06-10 15:51:54 +02001727 X->s = 1;
Gilles Peskinef4998b02021-06-10 15:51:54 +02001728 else
1729 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001730
1731cleanup:
1732
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001733 mbedtls_mpi_free(&TB);
1734 mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001735
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001736 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001737}
1738
1739/*
1740 * Baseline multiplication: X = A * b
1741 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001742int mbedtls_mpi_mul_int(mbedtls_mpi *X,
1743 const mbedtls_mpi *A,
1744 mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001745{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001746 MPI_VALIDATE_RET(X != NULL);
1747 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001749 /* mpi_mul_hlp can't deal with a leading 0. */
1750 size_t n = A->n;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001751 while (n > 0 && A->p[n - 1] == 0)
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001752 --n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001754 /* The general method below doesn't work if n==0 or b==0. By chance
1755 * calculating the result is trivial in those cases. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001756 if (b == 0 || n == 0) {
1757 return mbedtls_mpi_lset(X, 0);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001758 }
1759
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001760 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001761 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001762 /* In general, A * b requires 1 limb more than b. If
1763 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1764 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001765 * copy() will take care of the growth if needed. However, experimentally,
1766 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001767 * calls to calloc() in ECP code, presumably because it reuses the
1768 * same mpi for a while and this way the mpi is more likely to directly
1769 * grow to its final size. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001770 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1771 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1772 mpi_mul_hlp(n, A->p, X->p, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001773
1774cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001775 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001776}
1777
1778/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001779 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1780 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001781 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001782static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1783 mbedtls_mpi_uint u0,
1784 mbedtls_mpi_uint d,
1785 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001786{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001787# if defined(MBEDTLS_HAVE_UDBL)
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001788 mbedtls_t_udbl dividend, quotient;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001789# else
1790 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint)1 << biH;
1791 const mbedtls_mpi_uint uint_halfword_mask =
1792 ((mbedtls_mpi_uint)1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001793 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1794 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001795 size_t s;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001796# endif
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001797
Simon Butcher15b15d12015-11-26 19:35:03 +00001798 /*
1799 * Check for overflow
1800 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001801 if (0 == d || u1 >= d) {
1802 if (r != NULL)
1803 *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001804
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001805 return ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001806 }
1807
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001808# if defined(MBEDTLS_HAVE_UDBL)
1809 dividend = (mbedtls_t_udbl)u1 << biL;
1810 dividend |= (mbedtls_t_udbl)u0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001811 quotient = dividend / d;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001812 if (quotient > ((mbedtls_t_udbl)1 << biL) - 1)
1813 quotient = ((mbedtls_t_udbl)1 << biL) - 1;
Simon Butcher15b15d12015-11-26 19:35:03 +00001814
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001815 if (r != NULL)
1816 *r = (mbedtls_mpi_uint)(dividend - (quotient * d));
Simon Butcher15b15d12015-11-26 19:35:03 +00001817
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001818 return (mbedtls_mpi_uint)quotient;
1819# else
Simon Butcher15b15d12015-11-26 19:35:03 +00001820
1821 /*
1822 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1823 * Vol. 2 - Seminumerical Algorithms, Knuth
1824 */
1825
1826 /*
1827 * Normalize the divisor, d, and dividend, u0, u1
1828 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001829 s = mbedtls_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001830 d = d << s;
1831
1832 u1 = u1 << s;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001833 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint)s >> (biL - 1));
1834 u0 = u0 << s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001835
1836 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001837 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001838
1839 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001840 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001841
1842 /*
1843 * Find the first quotient and remainder
1844 */
1845 q1 = u1 / d1;
1846 r0 = u1 - d1 * q1;
1847
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001848 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001849 q1 -= 1;
1850 r0 += d1;
1851
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001852 if (r0 >= radix)
1853 break;
Simon Butcher15b15d12015-11-26 19:35:03 +00001854 }
1855
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001856 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001857 q0 = rAX / d1;
1858 r0 = rAX - q0 * d1;
1859
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001860 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001861 q0 -= 1;
1862 r0 += d1;
1863
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001864 if (r0 >= radix)
1865 break;
Simon Butcher15b15d12015-11-26 19:35:03 +00001866 }
1867
1868 if (r != NULL)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001869 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001870
1871 quotient = q1 * radix + q0;
1872
1873 return quotient;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001874# endif
Simon Butcher15b15d12015-11-26 19:35:03 +00001875}
1876
1877/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001879 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001880int mbedtls_mpi_div_mpi(mbedtls_mpi *Q,
1881 mbedtls_mpi *R,
1882 const mbedtls_mpi *A,
1883 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001884{
Janos Follath24eed8d2019-11-22 13:21:35 +00001885 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001886 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001888 mbedtls_mpi_uint TP2[3];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001889 MPI_VALIDATE_RET(A != NULL);
1890 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001892 if (mbedtls_mpi_cmp_int(B, 0) == 0)
1893 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
Paul Bakker5121ce52009-01-03 21:22:43 +00001894
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001895 mbedtls_mpi_init(&X);
1896 mbedtls_mpi_init(&Y);
1897 mbedtls_mpi_init(&Z);
1898 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001899 /*
1900 * Avoid dynamic memory allocations for constant-size T2.
1901 *
1902 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1903 * so nobody increase the size of the MPI and we're safe to use an on-stack
1904 * buffer.
1905 */
Alexander K35d6d462019-10-31 14:46:45 +03001906 T2.s = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001907 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001908 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001909
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001910 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1911 if (Q != NULL)
1912 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1913 if (R != NULL)
1914 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1915 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001916 }
1917
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001918 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1919 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 X.s = Y.s = 1;
1921
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001922 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1923 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1924 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001925
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001926 k = mbedtls_mpi_bitlen(&Y) % biL;
1927 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 k = biL - 1 - k;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001929 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1930 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1931 } else
1932 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
1934 n = X.n - 1;
1935 t = Y.n - 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001936 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001938 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 Z.p[n - t]++;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001940 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001941 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001942 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001944 for (i = n; i > t; i--) {
1945 if (X.p[i] >= Y.p[t])
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 Z.p[i - t - 1] = ~0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001947 else {
1948 Z.p[i - t - 1] =
1949 mbedtls_int_div_int(X.p[i], X.p[i - 1], Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001950 }
1951
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001952 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1953 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001954 T2.p[2] = X.p[i];
1955
Paul Bakker5121ce52009-01-03 21:22:43 +00001956 Z.p[i - t - 1]++;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001957 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001958 Z.p[i - t - 1]--;
1959
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001960 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1961 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 T1.p[1] = Y.p[t];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001963 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1964 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001965
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001966 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1967 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1968 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001970 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1971 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1972 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1973 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 Z.p[i - t - 1]--;
1975 }
1976 }
1977
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001978 if (Q != NULL) {
1979 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 Q->s = A->s * B->s;
1981 }
1982
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001983 if (R != NULL) {
1984 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001985 X.s = A->s;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001986 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001988 if (mbedtls_mpi_cmp_int(R, 0) == 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00001989 R->s = 1;
1990 }
1991
1992cleanup:
1993
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001994 mbedtls_mpi_free(&X);
1995 mbedtls_mpi_free(&Y);
1996 mbedtls_mpi_free(&Z);
1997 mbedtls_mpi_free(&T1);
1998 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001999
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002000 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002001}
2002
2003/*
2004 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002006int mbedtls_mpi_div_int(mbedtls_mpi *Q,
2007 mbedtls_mpi *R,
2008 const mbedtls_mpi *A,
2009 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00002010{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01002011 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002012 mbedtls_mpi_uint p[1];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002013 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002015 p[0] = (b < 0) ? -b : b;
2016 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01002017 B.n = 1;
2018 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002020 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00002021}
2022
2023/*
2024 * Modulo: R = A mod B
2025 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002026int mbedtls_mpi_mod_mpi(mbedtls_mpi *R,
2027 const mbedtls_mpi *A,
2028 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002029{
Janos Follath24eed8d2019-11-22 13:21:35 +00002030 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002031 MPI_VALIDATE_RET(R != NULL);
2032 MPI_VALIDATE_RET(A != NULL);
2033 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002035 if (mbedtls_mpi_cmp_int(B, 0) < 0)
2036 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002037
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002038 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002040 while (mbedtls_mpi_cmp_int(R, 0) < 0)
2041 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002042
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002043 while (mbedtls_mpi_cmp_mpi(R, B) >= 0)
2044 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
2046cleanup:
2047
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002048 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002049}
2050
2051/*
2052 * Modulo: r = A mod b
2053 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002054int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r,
2055 const mbedtls_mpi *A,
2056 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00002057{
Paul Bakker23986e52011-04-24 08:57:21 +00002058 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 mbedtls_mpi_uint x, y, z;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002060 MPI_VALIDATE_RET(r != NULL);
2061 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002063 if (b == 0)
2064 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
Paul Bakker5121ce52009-01-03 21:22:43 +00002065
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002066 if (b < 0)
2067 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002068
2069 /*
2070 * handle trivial cases
2071 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002072 if (b == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002073 *r = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002074 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002075 }
2076
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002077 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002078 *r = A->p[0] & 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002079 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002080 }
2081
2082 /*
2083 * general case
2084 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002085 for (i = A->n, y = 0; i > 0; i--) {
2086 x = A->p[i - 1];
2087 y = (y << biH) | (x >> biH);
2088 z = y / b;
Paul Bakker5121ce52009-01-03 21:22:43 +00002089 y -= z * b;
2090
2091 x <<= biH;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002092 y = (y << biH) | (x >> biH);
2093 z = y / b;
Paul Bakker5121ce52009-01-03 21:22:43 +00002094 y -= z * b;
2095 }
2096
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002097 /*
2098 * If A is negative, then the current y represents a negative value.
2099 * Flipping it to the positive side.
2100 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002101 if (A->s < 0 && y != 0)
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002102 y = b - y;
2103
Paul Bakker5121ce52009-01-03 21:22:43 +00002104 *r = y;
2105
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002106 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002107}
2108
2109/*
2110 * Fast Montgomery initialization (thanks to Tom St Denis)
2111 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002112static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002113{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002115 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002116
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002117 x = m0;
2118 x += ((m0 + 2) & 4) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002120 for (i = biL; i >= 8; i /= 2)
2121 x *= (2 - (m0 * x));
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
2123 *mm = ~x + 1;
2124}
2125
Gilles Peskine2a82f722020-06-04 15:00:49 +02002126/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2127 *
2128 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002129 * It must have at least as many limbs as N
2130 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002131 * On successful completion, A contains the result of
2132 * the multiplication A * B * R^-1 mod N where
2133 * R = (2^ciL)^n.
2134 * \param[in] B One of the numbers to multiply.
2135 * It must be nonzero and must not have more limbs than N
2136 * (B->n <= N->n).
2137 * \param[in] N The modulo. N must be odd.
2138 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2139 * This is -N^-1 mod 2^ciL.
2140 * \param[in,out] T A bignum for temporary storage.
2141 * It must be at least twice the limb size of N plus 2
2142 * (T->n >= 2 * (N->n + 1)).
2143 * Its initial content is unused and
2144 * its final content is indeterminate.
2145 * Note that unlike the usual convention in the library
2146 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002147 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002148static void mpi_montmul(mbedtls_mpi *A,
2149 const mbedtls_mpi *B,
2150 const mbedtls_mpi *N,
2151 mbedtls_mpi_uint mm,
2152 const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00002153{
Paul Bakker23986e52011-04-24 08:57:21 +00002154 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002156
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002157 memset(T->p, 0, T->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002158
2159 d = T->p;
2160 n = N->n;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002161 m = (B->n < n) ? B->n : n;
Paul Bakker5121ce52009-01-03 21:22:43 +00002162
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002163 for (i = 0; i < n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002164 /*
2165 * T = (T + u0*B + u1*N) / 2^biL
2166 */
2167 u0 = A->p[i];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002168 u1 = (d[0] + u0 * B->p[0]) * mm;
Paul Bakker5121ce52009-01-03 21:22:43 +00002169
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002170 mpi_mul_hlp(m, B->p, d, u0);
2171 mpi_mul_hlp(n, N->p, d, u1);
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002173 *d++ = u0;
2174 d[n + 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002175 }
2176
Gilles Peskine221626f2020-06-08 22:37:50 +02002177 /* At this point, d is either the desired result or the desired result
2178 * plus N. We now potentially subtract N, avoiding leaking whether the
2179 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
Gilles Peskine221626f2020-06-08 22:37:50 +02002181 /* Copy the n least significant limbs of d to A, so that
2182 * A = d if d < N (recall that N has n limbs). */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002183 memcpy(A->p, d, n * ciL);
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002184 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002185 * do the calculation without using conditional tests. */
2186 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002187 d[n] += 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002188 d[n] -= mpi_sub_hlp(n, d, d, N->p);
Gilles Peskine221626f2020-06-08 22:37:50 +02002189 /* If d0 < N then d < (2^biL)^n
2190 * so d[n] == 0 and we want to keep A as it is.
2191 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2192 * so d[n] == 1 and we want to set A to the result of the subtraction
2193 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2194 * This exactly corresponds to a conditional assignment. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002195 mpi_safe_cond_assign(n, A->p, d, (unsigned char)d[n]);
Paul Bakker5121ce52009-01-03 21:22:43 +00002196}
2197
2198/*
2199 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002200 *
2201 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002202 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002203static void mpi_montred(mbedtls_mpi *A,
2204 const mbedtls_mpi *N,
2205 mbedtls_mpi_uint mm,
2206 const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00002207{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 mbedtls_mpi_uint z = 1;
2209 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002211 U.n = U.s = (int)z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 U.p = &z;
2213
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002214 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002215}
2216
2217/*
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002218 * Constant-flow boolean "equal" comparison:
2219 * return x == y
2220 *
2221 * This function can be used to write constant-time code by replacing branches
2222 * with bit operations - it can be used in conjunction with
2223 * mbedtls_ssl_cf_mask_from_bit().
2224 *
2225 * This function is implemented without using comparison operators, as those
2226 * might be translated to branches by some compilers on some platforms.
2227 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002228static size_t mbedtls_mpi_cf_bool_eq(size_t x, size_t y)
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002229{
2230 /* diff = 0 if x == y, non-zero otherwise */
2231 const size_t diff = x ^ y;
2232
2233 /* MSVC has a warning about unary minus on unsigned integer types,
2234 * but this is well-defined and precisely what we want to do here. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002235# if defined(_MSC_VER)
2236# pragma warning(push)
2237# pragma warning(disable : 4146)
2238# endif
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002239
2240 /* diff_msb's most significant bit is equal to x != y */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002241 const size_t diff_msb = (diff | (size_t)-diff);
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002242
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002243# if defined(_MSC_VER)
2244# pragma warning(pop)
2245# endif
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002246
2247 /* diff1 = (x != y) ? 1 : 0 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002248 const size_t diff1 = diff_msb >> (sizeof(diff_msb) * 8 - 1);
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002249
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002250 return 1 ^ diff1;
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002251}
2252
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002253/**
2254 * Select an MPI from a table without leaking the index.
2255 *
2256 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2257 * reads the entire table in order to avoid leaking the value of idx to an
2258 * attacker able to observe memory access patterns.
2259 *
2260 * \param[out] R Where to write the selected MPI.
2261 * \param[in] T The table to read from.
2262 * \param[in] T_size The number of elements in the table.
2263 * \param[in] idx The index of the element to select;
2264 * this must satisfy 0 <= idx < T_size.
2265 *
2266 * \return \c 0 on success, or a negative error code.
2267 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002268static int
2269mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002270{
2271 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2272
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002273 for (size_t i = 0; i < T_size; i++) {
2274 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(
2275 R, &T[i], (unsigned char)mbedtls_mpi_cf_bool_eq(i, idx)));
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002276 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002277
2278cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002279 return ret;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002280}
2281
Paul Bakker5121ce52009-01-03 21:22:43 +00002282/*
2283 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2284 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002285int mbedtls_mpi_exp_mod(mbedtls_mpi *X,
2286 const mbedtls_mpi *A,
2287 const mbedtls_mpi *E,
2288 const mbedtls_mpi *N,
2289 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00002290{
Janos Follath24eed8d2019-11-22 13:21:35 +00002291 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002292 size_t wbits, wsize, one = 1;
2293 size_t i, j, nblimbs;
2294 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 mbedtls_mpi_uint ei, mm, state;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002296 mbedtls_mpi RR, T, W[1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002297 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002299 MPI_VALIDATE_RET(X != NULL);
2300 MPI_VALIDATE_RET(A != NULL);
2301 MPI_VALIDATE_RET(E != NULL);
2302 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002303
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002304 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0)
2305 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002307 if (mbedtls_mpi_cmp_int(E, 0) < 0)
2308 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002309
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002310 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
2311 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS)
2312 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Chris Jones9246d042020-11-25 15:12:39 +00002313
Paul Bakkerf6198c12012-05-16 08:02:29 +00002314 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 * Init temps and window size
2316 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002317 mpi_montg_init(&mm, N);
2318 mbedtls_mpi_init(&RR);
2319 mbedtls_mpi_init(&T);
2320 mbedtls_mpi_init(&Apos);
2321 mbedtls_mpi_init(&WW);
2322 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00002323
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002324 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002326 wsize = (i > 671) ? 6 : (i > 239) ? 5 : (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002327
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002328# if (MBEDTLS_MPI_WINDOW_SIZE < 6)
2329 if (wsize > MBEDTLS_MPI_WINDOW_SIZE)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002331# endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002332
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 j = N->n + 1;
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002334 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2335 * and mpi_montred() calls later. Here we ensure that W[1] and X are
2336 * large enough, and later we'll grow other W[i] to the same length.
2337 * They must not be shrunk midway through this function!
2338 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002339 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
2340 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
2341 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
2343 /*
Paul Bakker50546922012-05-19 08:40:49 +00002344 * Compensate for negative A (and correct at the end)
2345 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002346 neg = (A->s == -1);
2347 if (neg) {
2348 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00002349 Apos.s = 1;
2350 A = &Apos;
2351 }
2352
2353 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002354 * If 1st call, pre-compute R^2 mod N
2355 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002356 if (prec_RR == NULL || prec_RR->p == NULL) {
2357 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
2358 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
2359 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002361 if (prec_RR != NULL)
2362 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
2363 } else
2364 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00002365
2366 /*
2367 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2368 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002369 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
2370 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002371 /* This should be a no-op because W[1] is already that large before
2372 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2373 * in mpi_montmul() below, so let's make sure. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002374 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
2375 } else
2376 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002378 /* Note that this is safe because W[1] always has at least N->n limbs
2379 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002380 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002381
2382 /*
2383 * X = R^2 * R^-1 mod N = R mod N
2384 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002385 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &RR));
2386 mpi_montred(X, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002388 if (wsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002389 /*
2390 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2391 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002392 j = one << (wsize - 1);
Paul Bakker5121ce52009-01-03 21:22:43 +00002393
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002394 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
2395 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002396
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002397 for (i = 0; i < wsize - 1; i++)
2398 mpi_montmul(&W[j], &W[j], N, mm, &T);
Paul Bakker0d7702c2013-10-29 16:18:35 +01002399
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 /*
2401 * W[i] = W[i - 1] * W[1]
2402 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002403 for (i = j + 1; i < (one << wsize); i++) {
2404 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
2405 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002406
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002407 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 }
2409 }
2410
2411 nblimbs = E->n;
2412 bufsize = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002413 nbits = 0;
2414 wbits = 0;
2415 state = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002416
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002417 while (1) {
2418 if (bufsize == 0) {
2419 if (nblimbs == 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00002420 break;
2421
Paul Bakker0d7702c2013-10-29 16:18:35 +01002422 nblimbs--;
2423
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002424 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002425 }
2426
2427 bufsize--;
2428
2429 ei = (E->p[nblimbs] >> bufsize) & 1;
2430
2431 /*
2432 * skip leading 0s
2433 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002434 if (ei == 0 && state == 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00002435 continue;
2436
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002437 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002438 /*
2439 * out of window, square X
2440 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002441 mpi_montmul(X, X, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002442 continue;
2443 }
2444
2445 /*
2446 * add ei to current window
2447 */
2448 state = 2;
2449
2450 nbits++;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002451 wbits |= (ei << (wsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00002452
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002453 if (nbits == wsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002454 /*
2455 * X = X^wsize R^-1 mod N
2456 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002457 for (i = 0; i < wsize; i++)
2458 mpi_montmul(X, X, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002459
2460 /*
2461 * X = X * W[wbits] R^-1 mod N
2462 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002463 MBEDTLS_MPI_CHK(mpi_select(&WW, W, (size_t)1 << wsize, wbits));
2464 mpi_montmul(X, &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002465
2466 state--;
2467 nbits = 0;
2468 wbits = 0;
2469 }
2470 }
2471
2472 /*
2473 * process the remaining bits
2474 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002475 for (i = 0; i < nbits; i++) {
2476 mpi_montmul(X, X, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002477
2478 wbits <<= 1;
2479
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002480 if ((wbits & (one << wsize)) != 0)
2481 mpi_montmul(X, &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002482 }
2483
2484 /*
2485 * X = A^E * R * R^-1 mod N = A^E mod N
2486 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002487 mpi_montred(X, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002488
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002489 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Paul Bakkerf6198c12012-05-16 08:02:29 +00002490 X->s = -1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002491 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
Paul Bakkerf6198c12012-05-16 08:02:29 +00002492 }
2493
Paul Bakker5121ce52009-01-03 21:22:43 +00002494cleanup:
2495
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002496 for (i = (one << (wsize - 1)); i < (one << wsize); i++)
2497 mbedtls_mpi_free(&W[i]);
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002499 mbedtls_mpi_free(&W[1]);
2500 mbedtls_mpi_free(&T);
2501 mbedtls_mpi_free(&Apos);
2502 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00002503
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002504 if (prec_RR == NULL || prec_RR->p == NULL)
2505 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002506
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002507 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002508}
2509
Paul Bakker5121ce52009-01-03 21:22:43 +00002510/*
2511 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2512 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002513int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002514{
Janos Follath24eed8d2019-11-22 13:21:35 +00002515 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002516 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002517 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002518
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002519 MPI_VALIDATE_RET(G != NULL);
2520 MPI_VALIDATE_RET(A != NULL);
2521 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002522
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002523 mbedtls_mpi_init(&TA);
2524 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002525
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002526 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2527 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002528
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002529 lz = mbedtls_mpi_lsb(&TA);
2530 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002531
Gilles Peskine27253bc2021-06-09 13:26:43 +02002532 /* The loop below gives the correct result when A==0 but not when B==0.
2533 * So have a special case for B==0. Leverage the fact that we just
2534 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2535 * slightly more efficient than cmp_int(). */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002536 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
2537 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02002538 goto cleanup;
2539 }
2540
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002541 if (lzt < lz)
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002542 lz = lzt;
2543
Paul Bakker5121ce52009-01-03 21:22:43 +00002544 TA.s = TB.s = 1;
2545
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002546 /* We mostly follow the procedure described in HAC 14.54, but with some
2547 * minor differences:
2548 * - Sequences of multiplications or divisions by 2 are grouped into a
2549 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002550 * - The procedure in HAC assumes that 0 < TB <= TA.
2551 * - The condition TB <= TA is not actually necessary for correctness.
2552 * TA and TB have symmetric roles except for the loop termination
2553 * condition, and the shifts at the beginning of the loop body
2554 * remove any significance from the ordering of TA vs TB before
2555 * the shifts.
2556 * - If TA = 0, the loop goes through 0 iterations and the result is
2557 * correctly TB.
2558 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002559 *
2560 * For the correctness proof below, decompose the original values of
2561 * A and B as
2562 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2563 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2564 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2565 * and gcd(A',B') is odd or 0.
2566 *
2567 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2568 * The code maintains the following invariant:
2569 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002570 */
2571
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002572 /* Proof that the loop terminates:
2573 * At each iteration, either the right-shift by 1 is made on a nonzero
2574 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2575 * by at least 1, or the right-shift by 1 is made on zero and then
2576 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2577 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2578 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002579 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002580 /* Divisions by 2 preserve the invariant (I). */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002581 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2582 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002583
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002584 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2585 * TA-TB is even so the division by 2 has an integer result.
2586 * Invariant (I) is preserved since any odd divisor of both TA and TB
2587 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2588 * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
2589 * divides TA.
2590 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002591 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2592 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2593 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2594 } else {
2595 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2596 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002598 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002599 }
2600
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002601 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2602 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2603 * - If there was at least one loop iteration, then one of TA or TB is odd,
2604 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2605 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2606 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002607 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002608 */
2609
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002610 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2611 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002612
2613cleanup:
2614
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002615 mbedtls_mpi_free(&TA);
2616 mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002617
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002618 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002619}
2620
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002621/* Fill X with n_bytes random bytes.
2622 * X must already have room for those bytes.
Gilles Peskineafb2bd22021-06-03 11:51:09 +02002623 * The ordering of the bytes returned from the RNG is suitable for
2624 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskineebe9b6a2021-04-13 21:55:35 +02002625 * The size and sign of X are unchanged.
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002626 * n_bytes must not be 0.
2627 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002628static int
2629mpi_fill_random_internal(mbedtls_mpi *X,
2630 size_t n_bytes,
2631 int (*f_rng)(void *, unsigned char *, size_t),
2632 void *p_rng)
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002633{
2634 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002635 const size_t limbs = CHARS_TO_LIMBS(n_bytes);
2636 const size_t overhead = (limbs * ciL) - n_bytes;
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002637
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002638 if (X->n < limbs)
2639 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002640
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002641 memset(X->p, 0, overhead);
2642 memset((unsigned char *)X->p + limbs * ciL, 0, (X->n - limbs) * ciL);
2643 MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *)X->p + overhead, n_bytes));
2644 mpi_bigendian_to_host(X->p, limbs);
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002645
2646cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002647 return ret;
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002648}
2649
Paul Bakker33dc46b2014-04-30 16:11:39 +02002650/*
2651 * Fill X with size bytes of random.
2652 *
2653 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002654 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002655 * deterministic, eg for tests).
2656 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002657int mbedtls_mpi_fill_random(mbedtls_mpi *X,
2658 size_t size,
2659 int (*f_rng)(void *, unsigned char *, size_t),
2660 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002661{
Janos Follath24eed8d2019-11-22 13:21:35 +00002662 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002663 size_t const limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002664
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002665 MPI_VALIDATE_RET(X != NULL);
2666 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002667
Hanno Beckerda1655a2017-10-18 14:21:44 +01002668 /* Ensure that target MPI has exactly the necessary number of limbs */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002669 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2670 if (size == 0)
2671 return 0;
Paul Bakker287781a2011-03-26 13:18:49 +00002672
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002673 ret = mpi_fill_random_internal(X, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002674
2675cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002676 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002677}
2678
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002679int mbedtls_mpi_random(mbedtls_mpi *X,
2680 mbedtls_mpi_sint min,
2681 const mbedtls_mpi *N,
2682 int (*f_rng)(void *, unsigned char *, size_t),
2683 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002684{
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002685 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee5381682021-04-13 21:23:25 +02002686 int count;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002687 unsigned lt_lower = 1, lt_upper = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002688 size_t n_bits = mbedtls_mpi_bitlen(N);
2689 size_t n_bytes = (n_bits + 7) / 8;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002690 mbedtls_mpi lower_bound;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002691
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002692 if (min < 0)
2693 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2694 if (mbedtls_mpi_cmp_int(N, min) <= 0)
2695 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine1e918f42021-03-29 22:14:51 +02002696
Gilles Peskinee5381682021-04-13 21:23:25 +02002697 /*
2698 * When min == 0, each try has at worst a probability 1/2 of failing
2699 * (the msb has a probability 1/2 of being 0, and then the result will
2700 * be < N), so after 30 tries failure probability is a most 2**(-30).
2701 *
2702 * When N is just below a power of 2, as is the case when generating
Gilles Peskinee842e582021-04-15 11:45:19 +02002703 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee5381682021-04-13 21:23:25 +02002704 * overwhelming probability. When N is just above a power of 2,
Gilles Peskinee842e582021-04-15 11:45:19 +02002705 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee5381682021-04-13 21:23:25 +02002706 * a probability of failing that is almost 1/2.
2707 *
2708 * The probabilities are almost the same if min is nonzero but negligible
2709 * compared to N. This is always the case when N is crypto-sized, but
2710 * it's convenient to support small N for testing purposes. When N
2711 * is small, use a higher repeat count, otherwise the probability of
2712 * failure is macroscopic.
2713 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002714 count = (n_bytes > 4 ? 30 : 250);
Gilles Peskinee5381682021-04-13 21:23:25 +02002715
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002716 mbedtls_mpi_init(&lower_bound);
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002717
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002718 /* Ensure that target MPI has exactly the same number of limbs
2719 * as the upper bound, even if the upper bound has leading zeros.
2720 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002721 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, N->n));
2722 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&lower_bound, N->n));
2723 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&lower_bound, min));
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002724
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002725 /*
2726 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2727 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2728 * - use the same byte ordering;
2729 * - keep the leftmost n_bits bits of the generated octet string;
2730 * - try until result is in the desired range.
2731 * This also avoids any bias, which is especially important for ECDSA.
2732 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002733 do {
2734 MBEDTLS_MPI_CHK(mpi_fill_random_internal(X, n_bytes, f_rng, p_rng));
2735 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, 8 * n_bytes - n_bits));
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002736
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002737 if (--count == 0) {
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002738 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2739 goto cleanup;
2740 }
2741
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002742 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, &lower_bound, &lt_lower));
2743 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, N, &lt_upper));
2744 } while (lt_lower != 0 || lt_upper == 0);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002745
2746cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002747 mbedtls_mpi_free(&lower_bound);
2748 return ret;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002749}
2750
Paul Bakker5121ce52009-01-03 21:22:43 +00002751/*
2752 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2753 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002754int mbedtls_mpi_inv_mod(mbedtls_mpi *X,
2755 const mbedtls_mpi *A,
2756 const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002757{
Janos Follath24eed8d2019-11-22 13:21:35 +00002758 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002760 MPI_VALIDATE_RET(X != NULL);
2761 MPI_VALIDATE_RET(A != NULL);
2762 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002763
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002764 if (mbedtls_mpi_cmp_int(N, 1) <= 0)
2765 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +00002766
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002767 mbedtls_mpi_init(&TA);
2768 mbedtls_mpi_init(&TU);
2769 mbedtls_mpi_init(&U1);
2770 mbedtls_mpi_init(&U2);
2771 mbedtls_mpi_init(&G);
2772 mbedtls_mpi_init(&TB);
2773 mbedtls_mpi_init(&TV);
2774 mbedtls_mpi_init(&V1);
2775 mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002776
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002777 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002778
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002779 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002781 goto cleanup;
2782 }
2783
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002784 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2785 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2786 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2787 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002788
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002789 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2790 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2791 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2792 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002793
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002794 do {
2795 while ((TU.p[0] & 1) == 0) {
2796 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002797
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002798 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2799 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2800 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002801 }
2802
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002803 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2804 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002805 }
2806
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002807 while ((TV.p[0] & 1) == 0) {
2808 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002809
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002810 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2811 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2812 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002813 }
2814
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002815 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2816 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002817 }
2818
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002819 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2820 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2821 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2822 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2823 } else {
2824 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2825 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2826 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002827 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002828 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002829
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002830 while (mbedtls_mpi_cmp_int(&V1, 0) < 0)
2831 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002832
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002833 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0)
2834 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002835
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002836 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002837
2838cleanup:
2839
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002840 mbedtls_mpi_free(&TA);
2841 mbedtls_mpi_free(&TU);
2842 mbedtls_mpi_free(&U1);
2843 mbedtls_mpi_free(&U2);
2844 mbedtls_mpi_free(&G);
2845 mbedtls_mpi_free(&TB);
2846 mbedtls_mpi_free(&TV);
2847 mbedtls_mpi_free(&V1);
2848 mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002849
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002850 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002851}
2852
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002853# if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002854
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002855static const int small_prime[] = {
2856 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
2857 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109,
2858 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191,
2859 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269,
2860 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
2861 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439,
2862 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
2863 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617,
2864 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709,
2865 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
2866 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907,
2867 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002868};
2869
2870/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002871 * Small divisors test (X must be positive)
2872 *
2873 * Return values:
2874 * 0: no small factor (possible prime, more tests needed)
2875 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002876 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002877 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002878 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002879static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002880{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002881 int ret = 0;
2882 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002883 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002884
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002885 if ((X->p[0] & 1) == 0)
2886 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002887
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002888 for (i = 0; small_prime[i] > 0; i++) {
2889 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0)
2890 return 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002891
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002892 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002893
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002894 if (r == 0)
2895 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002896 }
2897
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002898cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002899 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002900}
2901
2902/*
2903 * Miller-Rabin pseudo-primality test (HAC 4.24)
2904 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002905static int mpi_miller_rabin(const mbedtls_mpi *X,
2906 size_t rounds,
2907 int (*f_rng)(void *, unsigned char *, size_t),
2908 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002909{
Pascal Junodb99183d2015-03-11 16:49:45 +01002910 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002911 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002912 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002913
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002914 MPI_VALIDATE_RET(X != NULL);
2915 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002916
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002917 mbedtls_mpi_init(&W);
2918 mbedtls_mpi_init(&R);
2919 mbedtls_mpi_init(&T);
2920 mbedtls_mpi_init(&A);
2921 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002922
Paul Bakker5121ce52009-01-03 21:22:43 +00002923 /*
2924 * W = |X| - 1
2925 * R = W >> lsb( W )
2926 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002927 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2928 s = mbedtls_mpi_lsb(&W);
2929 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2930 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002931
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002932 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002933 /*
2934 * pick a random A, 1 < A < |X| - 1
2935 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002936 count = 0;
2937 do {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002938 MBEDTLS_MPI_CHK(
2939 mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002940
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002941 j = mbedtls_mpi_bitlen(&A);
2942 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002943 if (j > k) {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002944 A.p[A.n - 1] &=
2945 ((mbedtls_mpi_uint)1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002946 }
2947
2948 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002949 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2950 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002951 }
2952
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002953 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2954 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002955
2956 /*
2957 * A = A^R mod |X|
2958 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002959 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002960
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002961 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 || mbedtls_mpi_cmp_int(&A, 1) == 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00002962 continue;
2963
2964 j = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002965 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002966 /*
2967 * A = A * A mod |X|
2968 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002969 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2970 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002971
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002972 if (mbedtls_mpi_cmp_int(&A, 1) == 0)
Paul Bakker5121ce52009-01-03 21:22:43 +00002973 break;
2974
2975 j++;
2976 }
2977
2978 /*
2979 * not prime if A != |X| - 1 or A == 1
2980 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002981 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2982 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002983 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002984 break;
2985 }
2986 }
2987
2988cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002989 mbedtls_mpi_free(&W);
2990 mbedtls_mpi_free(&R);
2991 mbedtls_mpi_free(&T);
2992 mbedtls_mpi_free(&A);
2993 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002994
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02002995 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002996}
2997
2998/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002999 * Pseudo-primality test: small factors, then Miller-Rabin
3000 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003001int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X,
3002 int rounds,
3003 int (*f_rng)(void *, unsigned char *, size_t),
3004 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01003005{
Janos Follath24eed8d2019-11-22 13:21:35 +00003006 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003007 mbedtls_mpi XX;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003008 MPI_VALIDATE_RET(X != NULL);
3009 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02003010
3011 XX.s = 1;
3012 XX.n = X->n;
3013 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01003014
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003015 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 || mbedtls_mpi_cmp_int(&XX, 1) == 0)
3016 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01003017
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003018 if (mbedtls_mpi_cmp_int(&XX, 2) == 0)
3019 return 0;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01003020
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003021 if ((ret = mpi_check_small_factors(&XX)) != 0) {
3022 if (ret == 1)
3023 return 0;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01003024
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003025 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01003026 }
3027
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003028 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01003029}
3030
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01003031/*
Paul Bakker5121ce52009-01-03 21:22:43 +00003032 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08003033 *
Janos Follathf301d232018-08-14 13:34:01 +01003034 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
3035 * be either 1024 bits or 1536 bits long, and flags must contain
3036 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00003037 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003038int mbedtls_mpi_gen_prime(mbedtls_mpi *X,
3039 size_t nbits,
3040 int flags,
3041 int (*f_rng)(void *, unsigned char *, size_t),
3042 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00003043{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003044# ifdef MBEDTLS_HAVE_INT64
Jethro Beekman66689272018-02-14 19:24:10 -08003045// ceil(2^63.5)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003046# define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
3047# else
Jethro Beekman66689272018-02-14 19:24:10 -08003048// ceil(2^31.5)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003049# define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
3050# endif
Jethro Beekman66689272018-02-14 19:24:10 -08003051 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00003052 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01003053 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003054 mbedtls_mpi_uint r;
3055 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00003056
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003057 MPI_VALIDATE_RET(X != NULL);
3058 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00003059
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003060 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS)
3061 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +00003062
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003063 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00003064
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003065 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00003066
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003067 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01003068 /*
3069 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
3070 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003071 rounds = ((nbits >= 1300) ? 2 :
3072 (nbits >= 850) ? 3 :
3073 (nbits >= 650) ? 4 :
3074 (nbits >= 350) ? 8 :
3075 (nbits >= 250) ? 12 :
3076 (nbits >= 150) ? 18 :
3077 27);
3078 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01003079 /*
3080 * 2^-100 error probability, number of rounds computed based on HAC,
3081 * fact 4.48
3082 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003083 rounds = ((nbits >= 1450) ? 4 :
3084 (nbits >= 1150) ? 5 :
3085 (nbits >= 1000) ? 6 :
3086 (nbits >= 850) ? 7 :
3087 (nbits >= 750) ? 8 :
3088 (nbits >= 500) ? 13 :
3089 (nbits >= 250) ? 28 :
3090 (nbits >= 150) ? 40 :
3091 51);
Janos Follathda31fa12018-09-03 14:45:23 +01003092 }
3093
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003094 while (1) {
3095 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
3096 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4
3097 * §B.3.3 steps 4.4, 5.5) */
3098 if (X->p[n - 1] < CEIL_MAXUINT_DIV_SQRT2)
3099 continue;
Jethro Beekman66689272018-02-14 19:24:10 -08003100
3101 k = n * biL;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003102 if (k > nbits)
3103 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
Jethro Beekman66689272018-02-14 19:24:10 -08003104 X->p[0] |= 1;
3105
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003106 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
3107 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08003108
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003109 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE)
Paul Bakker5121ce52009-01-03 21:22:43 +00003110 goto cleanup;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003111 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003112 /*
Jethro Beekman66689272018-02-14 19:24:10 -08003113 * An necessary condition for Y and X = 2Y + 1 to be prime
3114 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
3115 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003116 */
Jethro Beekman66689272018-02-14 19:24:10 -08003117
3118 X->p[0] |= 2;
3119
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003120 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
3121 if (r == 0)
3122 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
3123 else if (r == 1)
3124 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
Jethro Beekman66689272018-02-14 19:24:10 -08003125
3126 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003127 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
3128 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08003129
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003130 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08003131 /*
3132 * First, check small factors for X and Y
3133 * before doing Miller-Rabin on any of them
3134 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003135 if ((ret = mpi_check_small_factors(X)) == 0 &&
3136 (ret = mpi_check_small_factors(&Y)) == 0 &&
3137 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng)) == 0 &&
3138 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng)) == 0)
Jethro Beekman66689272018-02-14 19:24:10 -08003139 goto cleanup;
3140
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003141 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE)
Jethro Beekman66689272018-02-14 19:24:10 -08003142 goto cleanup;
3143
3144 /*
3145 * Next candidates. We want to preserve Y = (X-1) / 2 and
3146 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3147 * so up Y by 6 and X by 12.
3148 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003149 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
3150 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00003151 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003152 }
3153 }
3154
3155cleanup:
3156
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003157 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00003158
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003159 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00003160}
3161
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003162# endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003163
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003164# if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003165
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003166# define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003167
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003168static const int gcd_pairs[GCD_PAIR_COUNT][3] = { { 693, 609, 21 },
3169 { 1764, 868, 28 },
3170 { 768454923, 542167814, 1 } };
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003171
Paul Bakker5121ce52009-01-03 21:22:43 +00003172/*
3173 * Checkup routine
3174 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003175int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00003176{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003177 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003178 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003179
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003180 mbedtls_mpi_init(&A);
3181 mbedtls_mpi_init(&E);
3182 mbedtls_mpi_init(&N);
3183 mbedtls_mpi_init(&X);
3184 mbedtls_mpi_init(&Y);
3185 mbedtls_mpi_init(&U);
3186 mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003187
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003188 MBEDTLS_MPI_CHK(
3189 mbedtls_mpi_read_string(&A, 16,
3190 "EFE021C2645FD1DC586E69184AF4A31E"
3191 "D5F53E93B5F123FA41680867BA110131"
3192 "944FE7952E2517337780CB0DB80E61AA"
3193 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003194
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003195 MBEDTLS_MPI_CHK(
3196 mbedtls_mpi_read_string(&E, 16,
3197 "B2E7EFD37075B9F03FF989C7C5051C20"
3198 "34D2A323810251127E7BF8625A4F49A5"
3199 "F3E27F4DA8BD59C47D6DAABA4C8127BD"
3200 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003201
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003202 MBEDTLS_MPI_CHK(
3203 mbedtls_mpi_read_string(&N, 16,
3204 "0066A198186C18C10B2F5ED9B522752A"
3205 "9830B69916E535C8F047518A889A43A5"
3206 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003207
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003208 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003209
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003210 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3211 "602AB7ECA597A3D6B56FF9829A5E8B85"
3212 "9E857EA95A03512E2BAE7391688D264A"
3213 "A5663B0341DB9CCFD2C4C5F421FEC814"
3214 "8001B72E848A38CAE1C65F78E56ABDEF"
3215 "E12D3C039B8A02D6BE593F0BBBDA56F1"
3216 "ECF677152EF804370C1A305CAF3B5BF1"
3217 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003218
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003219 if (verbose != 0)
3220 mbedtls_printf(" MPI test #1 (mul_mpi): ");
Paul Bakker5121ce52009-01-03 21:22:43 +00003221
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003222 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3223 if (verbose != 0)
3224 mbedtls_printf("failed\n");
Paul Bakker5121ce52009-01-03 21:22:43 +00003225
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003226 ret = 1;
3227 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003228 }
3229
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003230 if (verbose != 0)
3231 mbedtls_printf("passed\n");
Paul Bakker5121ce52009-01-03 21:22:43 +00003232
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003233 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003234
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003235 MBEDTLS_MPI_CHK(
3236 mbedtls_mpi_read_string(&U, 16, "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003237
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003238 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
3239 "6613F26162223DF488E9CD48CC132C7A"
3240 "0AC93C701B001B092E4E5B9F73BCD27B"
3241 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003242
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003243 if (verbose != 0)
3244 mbedtls_printf(" MPI test #2 (div_mpi): ");
Paul Bakker5121ce52009-01-03 21:22:43 +00003245
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003246 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 || mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
3247 if (verbose != 0)
3248 mbedtls_printf("failed\n");
Paul Bakker5121ce52009-01-03 21:22:43 +00003249
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003250 ret = 1;
3251 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003252 }
3253
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003254 if (verbose != 0)
3255 mbedtls_printf("passed\n");
Paul Bakker5121ce52009-01-03 21:22:43 +00003256
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003257 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00003258
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003259 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3260 "36E139AEA55215609D2816998ED020BB"
3261 "BD96C37890F65171D948E9BC7CBAA4D9"
3262 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003263
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003264 if (verbose != 0)
3265 mbedtls_printf(" MPI test #3 (exp_mod): ");
Paul Bakker5121ce52009-01-03 21:22:43 +00003266
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003267 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3268 if (verbose != 0)
3269 mbedtls_printf("failed\n");
Paul Bakker5121ce52009-01-03 21:22:43 +00003270
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003271 ret = 1;
3272 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003273 }
3274
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003275 if (verbose != 0)
3276 mbedtls_printf("passed\n");
Paul Bakker5121ce52009-01-03 21:22:43 +00003277
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003278 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003279
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003280 MBEDTLS_MPI_CHK(
3281 mbedtls_mpi_read_string(&U, 16,
3282 "003A0AAEDD7E784FC07D8F9EC6E3BFD5"
3283 "C3DBA76456363A10869622EAC2DD84EC"
3284 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003285
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003286 if (verbose != 0)
3287 mbedtls_printf(" MPI test #4 (inv_mod): ");
Paul Bakker5121ce52009-01-03 21:22:43 +00003288
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003289 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3290 if (verbose != 0)
3291 mbedtls_printf("failed\n");
Paul Bakker5121ce52009-01-03 21:22:43 +00003292
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003293 ret = 1;
3294 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003295 }
3296
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003297 if (verbose != 0)
3298 mbedtls_printf("passed\n");
Paul Bakker5121ce52009-01-03 21:22:43 +00003299
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003300 if (verbose != 0)
3301 mbedtls_printf(" MPI test #5 (simple gcd): ");
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003302
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003303 for (i = 0; i < GCD_PAIR_COUNT; i++) {
3304 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
3305 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003306
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003307 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003308
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003309 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
3310 if (verbose != 0)
3311 mbedtls_printf("failed at %d\n", i);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003312
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003313 ret = 1;
3314 goto cleanup;
3315 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003316 }
3317
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003318 if (verbose != 0)
3319 mbedtls_printf("passed\n");
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003320
Paul Bakker5121ce52009-01-03 21:22:43 +00003321cleanup:
3322
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003323 if (ret != 0 && verbose != 0)
3324 mbedtls_printf("Unexpected error, return code = %08X\n",
3325 (unsigned int)ret);
Paul Bakker5121ce52009-01-03 21:22:43 +00003326
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003327 mbedtls_mpi_free(&A);
3328 mbedtls_mpi_free(&E);
3329 mbedtls_mpi_free(&N);
3330 mbedtls_mpi_free(&X);
3331 mbedtls_mpi_free(&Y);
3332 mbedtls_mpi_free(&U);
3333 mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003334
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003335 if (verbose != 0)
3336 mbedtls_printf("\n");
Paul Bakker5121ce52009-01-03 21:22:43 +00003337
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003338 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00003339}
3340
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02003341# endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003343#endif /* MBEDTLS_BIGNUM_C */