blob: 3967dbe78f2b944a650639fca94540f7e042f9d9 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
Simon Butcher15b15d12015-11-26 19:35:03 +000019
Paul Bakker5121ce52009-01-03 21:22:43 +000020/*
Simon Butcher15b15d12015-11-26 19:35:03 +000021 * The following sources were referenced in the design of this Multi-precision
22 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000023 *
Simon Butcher15b15d12015-11-26 19:35:03 +000024 * [1] Handbook of Applied Cryptography - 1997
25 * Menezes, van Oorschot and Vanstone
26 *
27 * [2] Multi-Precision Math
28 * Tom St Denis
29 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30 *
31 * [3] GNU Multi-Precision Arithmetic Library
32 * https://gmplib.org/manual/index.html
33 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000034 */
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Gilles Peskinedb09ef62020-06-03 01:43:33 +020036#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/bignum.h"
Chris Jones4c5819c2021-03-03 17:45:34 +000041#include "bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050042#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000043#include "mbedtls/error.h"
gabor-mezei-arm8d1d5fd2021-09-27 12:15:19 +020044#include "constant_time.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Rich Evans00ab4702015-02-06 13:43:58 +000046#include <string.h>
47
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020050#else
Rich Evans00ab4702015-02-06 13:43:58 +000051#include <stdio.h>
52#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020054#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020056#endif
57
Hanno Becker73d7d792018-12-11 10:35:51 +000058#define MPI_VALIDATE_RET( cond ) \
59 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
60#define MPI_VALIDATE( cond ) \
61 MBEDTLS_INTERNAL_VALIDATE( cond )
62
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000064#define biL (ciL << 3) /* bits in limb */
65#define biH (ciL << 2) /* half limb size */
66
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010067#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
68
Paul Bakker5121ce52009-01-03 21:22:43 +000069/*
70 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020071 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000072 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020073#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
74#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000075
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050076/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050077static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
78{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050079 mbedtls_platform_zeroize( v, ciL * n );
80}
81
Paul Bakker5121ce52009-01-03 21:22:43 +000082/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000083 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000086{
Hanno Becker73d7d792018-12-11 10:35:51 +000087 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000088
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 X->s = 1;
90 X->n = 0;
91 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000092}
93
94/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000095 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000096 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000098{
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 if( X == NULL )
100 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000101
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000103 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200104 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 }
107
Paul Bakker6c591fa2011-05-05 11:49:20 +0000108 X->s = 1;
109 X->n = 0;
110 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000111}
112
113/*
114 * Enlarge to the specified number of limbs
115 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000117{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000119 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200122 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000123
Paul Bakker5121ce52009-01-03 21:22:43 +0000124 if( X->n < nblimbs )
125 {
Simon Butcher29176892016-05-20 00:19:09 +0100126 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200127 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000128
Paul Bakker5121ce52009-01-03 21:22:43 +0000129 if( X->p != NULL )
130 {
131 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200132 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 }
135
136 X->n = nblimbs;
137 X->p = p;
138 }
139
140 return( 0 );
141}
142
143/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100144 * Resize down as much as possible,
145 * while keeping at least the specified number of limbs
146 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000151 MPI_VALIDATE_RET( X != NULL );
152
153 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
154 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100156 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100157 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100159 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100160
161 for( i = X->n - 1; i > 0; i-- )
162 if( X->p[i] != 0 )
163 break;
164 i++;
165
166 if( i < nblimbs )
167 i = nblimbs;
168
Simon Butcher29176892016-05-20 00:19:09 +0100169 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200170 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100172 if( X->p != NULL )
173 {
174 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200175 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100177 }
178
179 X->n = i;
180 X->p = p;
181
182 return( 0 );
183}
184
Gilles Peskineed32b572021-06-02 22:17:52 +0200185/* Resize X to have exactly n limbs and set it to 0. */
186static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
187{
188 if( limbs == 0 )
189 {
190 mbedtls_mpi_free( X );
191 return( 0 );
192 }
193 else if( X->n == limbs )
194 {
195 memset( X->p, 0, limbs * ciL );
196 X->s = 1;
197 return( 0 );
198 }
199 else
200 {
201 mbedtls_mpi_free( X );
202 return( mbedtls_mpi_grow( X, limbs ) );
203 }
204}
205
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100206/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200207 * Copy the contents of Y into X.
208 *
209 * This function is not constant-time. Leading zeros in Y may be removed.
210 *
211 * Ensure that X does not shrink. This is not guaranteed by the public API,
212 * but some code in the bignum module relies on this property, for example
213 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000214 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000216{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100217 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000218 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000219 MPI_VALIDATE_RET( X != NULL );
220 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221
222 if( X == Y )
223 return( 0 );
224
Gilles Peskinedb420622020-01-20 21:12:50 +0100225 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200226 {
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200227 if( X->n != 0 )
228 {
229 X->s = 1;
230 memset( X->p, 0, X->n * ciL );
231 }
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200232 return( 0 );
233 }
234
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 for( i = Y->n - 1; i > 0; i-- )
236 if( Y->p[i] != 0 )
237 break;
238 i++;
239
240 X->s = Y->s;
241
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100242 if( X->n < i )
243 {
244 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
245 }
246 else
247 {
248 memset( X->p + i, 0, ( X->n - i ) * ciL );
249 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000250
Paul Bakker5121ce52009-01-03 21:22:43 +0000251 memcpy( X->p, Y->p, i * ciL );
252
253cleanup:
254
255 return( ret );
256}
257
258/*
259 * Swap the contents of X and Y
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000262{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000264 MPI_VALIDATE( X != NULL );
265 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 memcpy( &T, X, sizeof( mbedtls_mpi ) );
268 memcpy( X, Y, sizeof( mbedtls_mpi ) );
269 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000270}
271
272/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100273 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100274 * about whether the assignment was made or not.
275 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100276 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100278{
279 int ret = 0;
280 size_t i;
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200281 mbedtls_mpi_uint limb_mask;
Hanno Becker73d7d792018-12-11 10:35:51 +0000282 MPI_VALIDATE_RET( X != NULL );
283 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100284
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200285 /* MSVC has a warning about unary minus on unsigned integer types,
286 * but this is well-defined and precisely what we want to do here. */
287#if defined(_MSC_VER)
288#pragma warning( push )
289#pragma warning( disable : 4146 )
290#endif
291
Pascal Junodb99183d2015-03-11 16:49:45 +0100292 /* make sure assign is 0 or 1 in a time-constant manner */
Manuel Pégourié-Gonnarda48b16a2021-06-17 13:25:03 +0200293 assign = (assign | (unsigned char)-assign) >> (sizeof( assign ) * 8 - 1);
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200294 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200295 limb_mask = -assign;
296
297#if defined(_MSC_VER)
298#pragma warning( pop )
299#endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100302
gabor-mezei-arm9fa43ce2021-09-28 16:14:47 +0200303 X->s = mbedtls_cf_cond_select_sign( X->s, Y->s, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100304
gabor-mezei-arm9fa43ce2021-09-28 16:14:47 +0200305 mbedtls_cf_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200307 for( i = Y->n; i < X->n; i++ )
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200308 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100309
310cleanup:
311 return( ret );
312}
313
314/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100315 * Conditionally swap X and Y, without leaking information
316 * about whether the swap was made or not.
317 * Here it is not ok to simply swap the pointers, which whould lead to
318 * different memory access patterns when X and Y are used afterwards.
319 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100321{
322 int ret, s;
323 size_t i;
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200324 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200325 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000326 MPI_VALIDATE_RET( X != NULL );
327 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100328
329 if( X == Y )
330 return( 0 );
331
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +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. */
334#if defined(_MSC_VER)
335#pragma warning( push )
336#pragma warning( disable : 4146 )
337#endif
338
Pascal Junodb99183d2015-03-11 16:49:45 +0100339 /* make sure swap is 0 or 1 in a time-constant manner */
Manuel Pégourié-Gonnarda48b16a2021-06-17 13:25:03 +0200340 swap = (swap | (unsigned char)-swap) >> (sizeof( swap ) * 8 - 1);
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200341 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200342 limb_mask = -swap;
343
344#if defined(_MSC_VER)
345#pragma warning( pop )
346#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
349 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100350
351 s = X->s;
gabor-mezei-arm9fa43ce2021-09-28 16:14:47 +0200352 X->s = mbedtls_cf_cond_select_sign( X->s, Y->s, swap );
353 Y->s = mbedtls_cf_cond_select_sign( Y->s, s, swap );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100354
355
356 for( i = 0; i < X->n; i++ )
357 {
358 tmp = X->p[i];
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200359 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
360 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100361 }
362
363cleanup:
364 return( ret );
365}
366
367/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000368 * Set value from integer
369 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000371{
Janos Follath24eed8d2019-11-22 13:21:35 +0000372 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000373 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000376 memset( X->p, 0, X->n * ciL );
377
378 X->p[0] = ( z < 0 ) ? -z : z;
379 X->s = ( z < 0 ) ? -1 : 1;
380
381cleanup:
382
383 return( ret );
384}
385
386/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000387 * Get a specific bit
388 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000390{
Hanno Becker73d7d792018-12-11 10:35:51 +0000391 MPI_VALIDATE_RET( X != NULL );
392
Paul Bakker2f5947e2011-05-18 15:47:11 +0000393 if( X->n * biL <= pos )
394 return( 0 );
395
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200396 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000397}
398
Gilles Peskine11cdb052018-11-20 16:47:47 +0100399/* Get a specific byte, without range checks. */
400#define GET_BYTE( X, i ) \
401 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
402
Paul Bakker2f5947e2011-05-18 15:47:11 +0000403/*
404 * Set a bit to a specific value of 0 or 1
405 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000407{
408 int ret = 0;
409 size_t off = pos / biL;
410 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000411 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000412
413 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200414 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200415
Paul Bakker2f5947e2011-05-18 15:47:11 +0000416 if( X->n * biL <= pos )
417 {
418 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200419 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000420
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000422 }
423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
425 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000426
427cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200428
Paul Bakker2f5947e2011-05-18 15:47:11 +0000429 return( ret );
430}
431
432/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200433 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000436{
Paul Bakker23986e52011-04-24 08:57:21 +0000437 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000438 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
440 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000441 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
443 return( count );
444
445 return( 0 );
446}
447
448/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000449 * Count leading zero bits in a given integer
450 */
451static size_t mbedtls_clz( const mbedtls_mpi_uint x )
452{
453 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100454 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000455
456 for( j = 0; j < biL; j++ )
457 {
458 if( x & mask ) break;
459
460 mask >>= 1;
461 }
462
463 return j;
464}
465
466/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200467 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000468 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200469size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000470{
Paul Bakker23986e52011-04-24 08:57:21 +0000471 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200473 if( X->n == 0 )
474 return( 0 );
475
Paul Bakker5121ce52009-01-03 21:22:43 +0000476 for( i = X->n - 1; i > 0; i-- )
477 if( X->p[i] != 0 )
478 break;
479
Simon Butcher15b15d12015-11-26 19:35:03 +0000480 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
Paul Bakker23986e52011-04-24 08:57:21 +0000482 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483}
484
485/*
486 * Return the total size in bytes
487 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000489{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200490 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000491}
492
493/*
494 * Convert an ASCII character to digit value
495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000497{
498 *d = 255;
499
500 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
501 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
502 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 if( *d >= (mbedtls_mpi_uint) radix )
505 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
507 return( 0 );
508}
509
510/*
511 * Import from an ASCII string
512 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000514{
Janos Follath24eed8d2019-11-22 13:21:35 +0000515 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000516 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200517 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 mbedtls_mpi_uint d;
519 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000520 MPI_VALIDATE_RET( X != NULL );
521 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
523 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000524 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000527
Gilles Peskine7cba8592021-06-08 18:32:34 +0200528 if( s[0] == 0 )
529 {
530 mbedtls_mpi_free( X );
531 return( 0 );
532 }
533
Gilles Peskine80f56732021-04-03 18:26:13 +0200534 if( s[0] == '-' )
535 {
536 ++s;
537 sign = -1;
538 }
539
Paul Bakkerff60ee62010-03-16 21:09:09 +0000540 slen = strlen( s );
541
Paul Bakker5121ce52009-01-03 21:22:43 +0000542 if( radix == 16 )
543 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100544 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200545 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
546
Paul Bakkerff60ee62010-03-16 21:09:09 +0000547 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
550 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
Paul Bakker23986e52011-04-24 08:57:21 +0000552 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000553 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200555 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556 }
557 }
558 else
559 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
Paul Bakkerff60ee62010-03-16 21:09:09 +0000562 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000563 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
565 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200566 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000567 }
568 }
569
Gilles Peskine80f56732021-04-03 18:26:13 +0200570 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
571 X->s = -1;
572
Paul Bakker5121ce52009-01-03 21:22:43 +0000573cleanup:
574
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000576
577 return( ret );
578}
579
580/*
Ron Eldora16fa292018-11-20 14:07:01 +0200581 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000582 */
Ron Eldora16fa292018-11-20 14:07:01 +0200583static int mpi_write_hlp( mbedtls_mpi *X, int radix,
584 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000585{
Janos Follath24eed8d2019-11-22 13:21:35 +0000586 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200588 size_t length = 0;
589 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000590
Ron Eldora16fa292018-11-20 14:07:01 +0200591 do
592 {
593 if( length >= buflen )
594 {
595 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
596 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000597
Ron Eldora16fa292018-11-20 14:07:01 +0200598 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
599 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
600 /*
601 * Write the residue in the current position, as an ASCII character.
602 */
603 if( r < 0xA )
604 *(--p_end) = (char)( '0' + r );
605 else
606 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000607
Ron Eldora16fa292018-11-20 14:07:01 +0200608 length++;
609 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
Ron Eldora16fa292018-11-20 14:07:01 +0200611 memmove( *p, p_end, length );
612 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
614cleanup:
615
616 return( ret );
617}
618
619/*
620 * Export into an ASCII string
621 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100622int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
623 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000624{
Paul Bakker23986e52011-04-24 08:57:21 +0000625 int ret = 0;
626 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000627 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000629 MPI_VALIDATE_RET( X != NULL );
630 MPI_VALIDATE_RET( olen != NULL );
631 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000632
633 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000634 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635
Hanno Becker23cfea02019-02-04 09:45:07 +0000636 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
637 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
638 * `n`. If radix > 4, this might be a strict
639 * overapproximation of the number of
640 * radix-adic digits needed to present `n`. */
641 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
642 * present `n`. */
643
Janos Follath80470622019-03-06 13:43:02 +0000644 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000645 n += 1; /* Compensate for the divisions above, which round down `n`
646 * in case it's not even. */
647 n += 1; /* Potential '-'-sign. */
648 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
649 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100651 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000652 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100653 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000655 }
656
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100657 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
660 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000661 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000662 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000663 buflen--;
664 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
666 if( radix == 16 )
667 {
Paul Bakker23986e52011-04-24 08:57:21 +0000668 int c;
669 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
Paul Bakker23986e52011-04-24 08:57:21 +0000671 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000672 {
Paul Bakker23986e52011-04-24 08:57:21 +0000673 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000674 {
Paul Bakker23986e52011-04-24 08:57:21 +0000675 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
Paul Bakker6c343d72014-07-10 14:36:19 +0200677 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000678 continue;
679
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000680 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000681 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000682 k = 1;
683 }
684 }
685 }
686 else
687 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000689
690 if( T.s == -1 )
691 T.s = 1;
692
Ron Eldora16fa292018-11-20 14:07:01 +0200693 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000694 }
695
696 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100697 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699cleanup:
700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
703 return( ret );
704}
705
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000707/*
708 * Read X from an opened file
709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000713 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000714 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000715 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000716 * Buffer should have space for (short) label and decimal formatted MPI,
717 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
Hanno Becker73d7d792018-12-11 10:35:51 +0000721 MPI_VALIDATE_RET( X != NULL );
722 MPI_VALIDATE_RET( fin != NULL );
723
724 if( radix < 2 || radix > 16 )
725 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
726
Paul Bakker5121ce52009-01-03 21:22:43 +0000727 memset( s, 0, sizeof( s ) );
728 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
731 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000732 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200733 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000734
Hanno Beckerb2034b72017-04-26 11:46:46 +0100735 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
736 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
738 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100739 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000740 if( mpi_get_digit( &d, radix, *p ) != 0 )
741 break;
742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000744}
745
746/*
747 * Write X into an opened file (or stdout if fout == NULL)
748 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000750{
Janos Follath24eed8d2019-11-22 13:21:35 +0000751 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000752 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000753 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000754 * Buffer should have space for (short) label and decimal formatted MPI,
755 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000756 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000758 MPI_VALIDATE_RET( X != NULL );
759
760 if( radix < 2 || radix > 16 )
761 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000762
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100763 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100765 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000766
767 if( p == NULL ) p = "";
768
769 plen = strlen( p );
770 slen = strlen( s );
771 s[slen++] = '\r';
772 s[slen++] = '\n';
773
774 if( fout != NULL )
775 {
776 if( fwrite( p, 1, plen, fout ) != plen ||
777 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000779 }
780 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
783cleanup:
784
785 return( ret );
786}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000788
Hanno Beckerda1655a2017-10-18 14:21:44 +0100789
790/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
791 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000792
793static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
794{
795 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100796 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000797 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100798
799 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
800 {
801 tmp <<= CHAR_BIT;
802 tmp |= (mbedtls_mpi_uint) *x_ptr;
803 }
804
Hanno Beckerf8720072018-11-08 11:53:49 +0000805 return( tmp );
806}
807
808static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
809{
810#if defined(__BYTE_ORDER__)
811
812/* Nothing to do on bigendian systems. */
813#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
814 return( x );
815#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
816
817#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
818
819/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000820#if defined(__GNUC__) && defined(__GNUC_PREREQ)
821#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000822#define have_bswap
823#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000824#endif
825
826#if defined(__clang__) && defined(__has_builtin)
827#if __has_builtin(__builtin_bswap32) && \
828 __has_builtin(__builtin_bswap64)
829#define have_bswap
830#endif
831#endif
832
Hanno Beckerf8720072018-11-08 11:53:49 +0000833#if defined(have_bswap)
834 /* The compiler is hopefully able to statically evaluate this! */
835 switch( sizeof(mbedtls_mpi_uint) )
836 {
837 case 4:
838 return( __builtin_bswap32(x) );
839 case 8:
840 return( __builtin_bswap64(x) );
841 }
842#endif
843#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
844#endif /* __BYTE_ORDER__ */
845
846 /* Fall back to C-based reordering if we don't know the byte order
847 * or we couldn't use a compiler-specific builtin. */
848 return( mpi_uint_bigendian_to_host_c( x ) );
849}
850
Hanno Becker2be8a552018-10-25 12:40:09 +0100851static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100852{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100853 mbedtls_mpi_uint *cur_limb_left;
854 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100855 if( limbs == 0 )
856 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100857
858 /*
859 * Traverse limbs and
860 * - adapt byte-order in each limb
861 * - swap the limbs themselves.
862 * For that, simultaneously traverse the limbs from left to right
863 * and from right to left, as long as the left index is not bigger
864 * than the right index (it's not a problem if limbs is odd and the
865 * indices coincide in the last iteration).
866 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100867 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
868 cur_limb_left <= cur_limb_right;
869 cur_limb_left++, cur_limb_right-- )
870 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000871 mbedtls_mpi_uint tmp;
872 /* Note that if cur_limb_left == cur_limb_right,
873 * this code effectively swaps the bytes only once. */
874 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
875 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
876 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100877 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100878}
879
Paul Bakker5121ce52009-01-03 21:22:43 +0000880/*
Janos Follatha778a942019-02-13 10:28:28 +0000881 * Import X from unsigned binary data, little endian
882 */
883int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
884 const unsigned char *buf, size_t buflen )
885{
Janos Follath24eed8d2019-11-22 13:21:35 +0000886 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000887 size_t i;
888 size_t const limbs = CHARS_TO_LIMBS( buflen );
889
890 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +0200891 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000892
893 for( i = 0; i < buflen; i++ )
894 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
895
896cleanup:
897
Janos Follath171a7ef2019-02-15 16:17:45 +0000898 /*
899 * This function is also used to import keys. However, wiping the buffers
900 * upon failure is not necessary because failure only can happen before any
901 * input is copied.
902 */
Janos Follatha778a942019-02-13 10:28:28 +0000903 return( ret );
904}
905
906/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000907 * Import X from unsigned binary data, big endian
908 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200909int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000910{
Janos Follath24eed8d2019-11-22 13:21:35 +0000911 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100912 size_t const limbs = CHARS_TO_LIMBS( buflen );
913 size_t const overhead = ( limbs * ciL ) - buflen;
914 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000915
Hanno Becker8ce11a32018-12-19 16:18:52 +0000916 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000917 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
918
Hanno Becker073c1992017-10-17 15:17:27 +0100919 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +0200920 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000921
Gilles Peskineed32b572021-06-02 22:17:52 +0200922 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000923 * even if buflen is 0. */
Gilles Peskineed32b572021-06-02 22:17:52 +0200924 if( buflen != 0 )
Hanno Becker0e810b92019-01-03 17:13:11 +0000925 {
926 Xp = (unsigned char*) X->p;
927 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100928
Hanno Becker0e810b92019-01-03 17:13:11 +0000929 mpi_bigendian_to_host( X->p, limbs );
930 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000931
932cleanup:
933
Janos Follath171a7ef2019-02-15 16:17:45 +0000934 /*
935 * This function is also used to import keys. However, wiping the buffers
936 * upon failure is not necessary because failure only can happen before any
937 * input is copied.
938 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 return( ret );
940}
941
942/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000943 * Export X into unsigned binary data, little endian
944 */
945int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
946 unsigned char *buf, size_t buflen )
947{
948 size_t stored_bytes = X->n * ciL;
949 size_t bytes_to_copy;
950 size_t i;
951
952 if( stored_bytes < buflen )
953 {
954 bytes_to_copy = stored_bytes;
955 }
956 else
957 {
958 bytes_to_copy = buflen;
959
960 /* The output buffer is smaller than the allocated size of X.
961 * However X may fit if its leading bytes are zero. */
962 for( i = bytes_to_copy; i < stored_bytes; i++ )
963 {
964 if( GET_BYTE( X, i ) != 0 )
965 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
966 }
967 }
968
969 for( i = 0; i < bytes_to_copy; i++ )
970 buf[i] = GET_BYTE( X, i );
971
972 if( stored_bytes < buflen )
973 {
974 /* Write trailing 0 bytes */
975 memset( buf + stored_bytes, 0, buflen - stored_bytes );
976 }
977
978 return( 0 );
979}
980
981/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000982 * Export X into unsigned binary data, big endian
983 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100984int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
985 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000986{
Hanno Becker73d7d792018-12-11 10:35:51 +0000987 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100988 size_t bytes_to_copy;
989 unsigned char *p;
990 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000991
Hanno Becker73d7d792018-12-11 10:35:51 +0000992 MPI_VALIDATE_RET( X != NULL );
993 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
994
995 stored_bytes = X->n * ciL;
996
Gilles Peskine11cdb052018-11-20 16:47:47 +0100997 if( stored_bytes < buflen )
998 {
999 /* There is enough space in the output buffer. Write initial
1000 * null bytes and record the position at which to start
1001 * writing the significant bytes. In this case, the execution
1002 * trace of this function does not depend on the value of the
1003 * number. */
1004 bytes_to_copy = stored_bytes;
1005 p = buf + buflen - stored_bytes;
1006 memset( buf, 0, buflen - stored_bytes );
1007 }
1008 else
1009 {
1010 /* The output buffer is smaller than the allocated size of X.
1011 * However X may fit if its leading bytes are zero. */
1012 bytes_to_copy = buflen;
1013 p = buf;
1014 for( i = bytes_to_copy; i < stored_bytes; i++ )
1015 {
1016 if( GET_BYTE( X, i ) != 0 )
1017 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1018 }
1019 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001020
Gilles Peskine11cdb052018-11-20 16:47:47 +01001021 for( i = 0; i < bytes_to_copy; i++ )
1022 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023
1024 return( 0 );
1025}
1026
1027/*
1028 * Left-shift: X <<= count
1029 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031{
Janos Follath24eed8d2019-11-22 13:21:35 +00001032 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001033 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001035 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001036
1037 v0 = count / (biL );
1038 t1 = count & (biL - 1);
1039
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001040 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001041
Paul Bakkerf9688572011-05-05 10:00:45 +00001042 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001043 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001044
1045 ret = 0;
1046
1047 /*
1048 * shift by count / limb_size
1049 */
1050 if( v0 > 0 )
1051 {
Paul Bakker23986e52011-04-24 08:57:21 +00001052 for( i = X->n; i > v0; i-- )
1053 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
Paul Bakker23986e52011-04-24 08:57:21 +00001055 for( ; i > 0; i-- )
1056 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 }
1058
1059 /*
1060 * shift by count % limb_size
1061 */
1062 if( t1 > 0 )
1063 {
1064 for( i = v0; i < X->n; i++ )
1065 {
1066 r1 = X->p[i] >> (biL - t1);
1067 X->p[i] <<= t1;
1068 X->p[i] |= r0;
1069 r0 = r1;
1070 }
1071 }
1072
1073cleanup:
1074
1075 return( ret );
1076}
1077
1078/*
1079 * Right-shift: X >>= count
1080 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082{
Paul Bakker23986e52011-04-24 08:57:21 +00001083 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001084 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001085 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001086
1087 v0 = count / biL;
1088 v1 = count & (biL - 1);
1089
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001090 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001092
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 /*
1094 * shift by count / limb_size
1095 */
1096 if( v0 > 0 )
1097 {
1098 for( i = 0; i < X->n - v0; i++ )
1099 X->p[i] = X->p[i + v0];
1100
1101 for( ; i < X->n; i++ )
1102 X->p[i] = 0;
1103 }
1104
1105 /*
1106 * shift by count % limb_size
1107 */
1108 if( v1 > 0 )
1109 {
Paul Bakker23986e52011-04-24 08:57:21 +00001110 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001111 {
Paul Bakker23986e52011-04-24 08:57:21 +00001112 r1 = X->p[i - 1] << (biL - v1);
1113 X->p[i - 1] >>= v1;
1114 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001115 r0 = r1;
1116 }
1117 }
1118
1119 return( 0 );
1120}
1121
1122/*
1123 * Compare unsigned values
1124 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001126{
Paul Bakker23986e52011-04-24 08:57:21 +00001127 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001128 MPI_VALIDATE_RET( X != NULL );
1129 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001130
Paul Bakker23986e52011-04-24 08:57:21 +00001131 for( i = X->n; i > 0; i-- )
1132 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 break;
1134
Paul Bakker23986e52011-04-24 08:57:21 +00001135 for( j = Y->n; j > 0; j-- )
1136 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001137 break;
1138
Paul Bakker23986e52011-04-24 08:57:21 +00001139 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 return( 0 );
1141
1142 if( i > j ) return( 1 );
1143 if( j > i ) return( -1 );
1144
Paul Bakker23986e52011-04-24 08:57:21 +00001145 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001146 {
Paul Bakker23986e52011-04-24 08:57:21 +00001147 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1148 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001149 }
1150
1151 return( 0 );
1152}
1153
1154/*
1155 * Compare signed values
1156 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001157int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001158{
Paul Bakker23986e52011-04-24 08:57:21 +00001159 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001160 MPI_VALIDATE_RET( X != NULL );
1161 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001162
Paul Bakker23986e52011-04-24 08:57:21 +00001163 for( i = X->n; i > 0; i-- )
1164 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001165 break;
1166
Paul Bakker23986e52011-04-24 08:57:21 +00001167 for( j = Y->n; j > 0; j-- )
1168 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001169 break;
1170
Paul Bakker23986e52011-04-24 08:57:21 +00001171 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 return( 0 );
1173
1174 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001175 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001176
1177 if( X->s > 0 && Y->s < 0 ) return( 1 );
1178 if( Y->s > 0 && X->s < 0 ) return( -1 );
1179
Paul Bakker23986e52011-04-24 08:57:21 +00001180 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 {
Paul Bakker23986e52011-04-24 08:57:21 +00001182 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1183 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184 }
1185
1186 return( 0 );
1187}
1188
Janos Follathee6abce2019-09-05 14:47:19 +01001189/*
1190 * Compare signed values in constant time
1191 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001192int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1193 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001194{
1195 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001196 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001197 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001198
1199 MPI_VALIDATE_RET( X != NULL );
1200 MPI_VALIDATE_RET( Y != NULL );
1201 MPI_VALIDATE_RET( ret != NULL );
1202
1203 if( X->n != Y->n )
1204 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1205
1206 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001207 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1208 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001209 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001210 X_is_negative = ( X->s & 2 ) >> 1;
1211 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001212
1213 /*
1214 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001215 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1216 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001217 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001218 cond = ( X_is_negative ^ Y_is_negative );
1219 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001220
1221 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001222 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001223 * need to go through the loop. Record if we have the result already.
1224 */
Janos Follathee6abce2019-09-05 14:47:19 +01001225 done = cond;
1226
1227 for( i = X->n; i > 0; i-- )
1228 {
1229 /*
Janos Follath30702422019-11-05 12:24:52 +00001230 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1231 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001232 *
1233 * Again even if we can make a decision, we just mark the result and
1234 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001235 */
gabor-mezei-arm9fa43ce2021-09-28 16:14:47 +02001236 cond = mbedtls_cf_mpi_uint_lt( Y->p[i - 1], X->p[i - 1] );
Janos Follath30702422019-11-05 12:24:52 +00001237 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001238 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001239
1240 /*
Janos Follath30702422019-11-05 12:24:52 +00001241 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1242 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001243 *
1244 * Again even if we can make a decision, we just mark the result and
1245 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001246 */
gabor-mezei-arm9fa43ce2021-09-28 16:14:47 +02001247 cond = mbedtls_cf_mpi_uint_lt( X->p[i - 1], Y->p[i - 1] );
Janos Follath30702422019-11-05 12:24:52 +00001248 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001249 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001250 }
1251
1252 return( 0 );
1253}
1254
Paul Bakker5121ce52009-01-03 21:22:43 +00001255/*
1256 * Compare signed values
1257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001259{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 mbedtls_mpi Y;
1261 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001262 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001263
1264 *p = ( z < 0 ) ? -z : z;
1265 Y.s = ( z < 0 ) ? -1 : 1;
1266 Y.n = 1;
1267 Y.p = p;
1268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001269 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001270}
1271
1272/*
1273 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001276{
Janos Follath24eed8d2019-11-22 13:21:35 +00001277 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001278 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001279 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001280 MPI_VALIDATE_RET( X != NULL );
1281 MPI_VALIDATE_RET( A != NULL );
1282 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001283
1284 if( X == B )
1285 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001286 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001287 }
1288
1289 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001291
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001292 /*
1293 * X should always be positive as a result of unsigned additions.
1294 */
1295 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001296
Paul Bakker23986e52011-04-24 08:57:21 +00001297 for( j = B->n; j > 0; j-- )
1298 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001299 break;
1300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001302
1303 o = B->p; p = X->p; c = 0;
1304
Janos Follath6c922682015-10-30 17:43:11 +01001305 /*
1306 * tmp is used because it might happen that p == o
1307 */
Paul Bakker23986e52011-04-24 08:57:21 +00001308 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001309 {
Janos Follath6c922682015-10-30 17:43:11 +01001310 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001311 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001312 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001313 }
1314
1315 while( c != 0 )
1316 {
1317 if( i >= X->n )
1318 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001320 p = X->p + i;
1321 }
1322
Paul Bakker2d319fd2012-09-16 21:34:26 +00001323 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001324 }
1325
1326cleanup:
1327
1328 return( ret );
1329}
1330
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001331/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001332 * Helper for mbedtls_mpi subtraction.
1333 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001334 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001335 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001336 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001337 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001338 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001339 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001340 * \param n Number of limbs of \p d, \p l and \p r.
1341 * \param[out] d The result of the subtraction.
1342 * \param[in] l The left operand.
1343 * \param[in] r The right operand.
1344 *
1345 * \return 1 if `l < r`.
1346 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001347 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001348static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1349 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001350 const mbedtls_mpi_uint *l,
1351 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001352{
Paul Bakker23986e52011-04-24 08:57:21 +00001353 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001354 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001356 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001357 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001358 z = ( l[i] < c ); t = l[i] - c;
1359 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 }
1361
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001362 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001363}
1364
1365/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001366 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001369{
Janos Follath24eed8d2019-11-22 13:21:35 +00001370 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001371 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001372 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001373 MPI_VALIDATE_RET( X != NULL );
1374 MPI_VALIDATE_RET( A != NULL );
1375 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
Paul Bakker23986e52011-04-24 08:57:21 +00001377 for( n = B->n; n > 0; n-- )
1378 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001380 if( n > A->n )
1381 {
1382 /* B >= (2^ciL)^n > A */
1383 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1384 goto cleanup;
1385 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001387 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1388
1389 /* Set the high limbs of X to match A. Don't touch the lower limbs
1390 * because X might be aliased to B, and we must not overwrite the
1391 * significant digits of B. */
1392 if( A->n > n )
1393 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1394 if( X->n > A->n )
1395 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1396
1397 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001398 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001399 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001400 /* Propagate the carry to the first nonzero limb of X. */
1401 for( ; n < X->n && X->p[n] == 0; n++ )
1402 --X->p[n];
1403 /* If we ran out of space for the carry, it means that the result
1404 * is negative. */
1405 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001406 {
1407 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1408 goto cleanup;
1409 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001410 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001411 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001412
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001413 /* X should always be positive as a result of unsigned subtractions. */
1414 X->s = 1;
1415
Paul Bakker5121ce52009-01-03 21:22:43 +00001416cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 return( ret );
1418}
1419
1420/*
1421 * Signed addition: X = A + B
1422 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001424{
Hanno Becker73d7d792018-12-11 10:35:51 +00001425 int ret, s;
1426 MPI_VALIDATE_RET( X != NULL );
1427 MPI_VALIDATE_RET( A != NULL );
1428 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001429
Hanno Becker73d7d792018-12-11 10:35:51 +00001430 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001431 if( A->s * B->s < 0 )
1432 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001433 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 X->s = s;
1437 }
1438 else
1439 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001441 X->s = -s;
1442 }
1443 }
1444 else
1445 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001447 X->s = s;
1448 }
1449
1450cleanup:
1451
1452 return( ret );
1453}
1454
1455/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001456 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001459{
Hanno Becker73d7d792018-12-11 10:35:51 +00001460 int ret, s;
1461 MPI_VALIDATE_RET( X != NULL );
1462 MPI_VALIDATE_RET( A != NULL );
1463 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001464
Hanno Becker73d7d792018-12-11 10:35:51 +00001465 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001466 if( A->s * B->s > 0 )
1467 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001469 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001470 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001471 X->s = s;
1472 }
1473 else
1474 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001476 X->s = -s;
1477 }
1478 }
1479 else
1480 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 X->s = s;
1483 }
1484
1485cleanup:
1486
1487 return( ret );
1488}
1489
1490/*
1491 * Signed addition: X = A + b
1492 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001494{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001495 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001497 MPI_VALIDATE_RET( X != NULL );
1498 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001499
1500 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001501 B.s = ( b < 0 ) ? -1 : 1;
1502 B.n = 1;
1503 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001504
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001505 return( mbedtls_mpi_add_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001506}
1507
1508/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001509 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001512{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001513 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001515 MPI_VALIDATE_RET( X != NULL );
1516 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001517
1518 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001519 B.s = ( b < 0 ) ? -1 : 1;
1520 B.n = 1;
1521 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001522
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001523 return( mbedtls_mpi_sub_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001524}
1525
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001526/** Helper for mbedtls_mpi multiplication.
1527 *
1528 * Add \p b * \p s to \p d.
1529 *
1530 * \param i The number of limbs of \p s.
1531 * \param[in] s A bignum to multiply, of size \p i.
1532 * It may overlap with \p d, but only if
1533 * \p d <= \p s.
1534 * Its leading limb must not be \c 0.
1535 * \param[in,out] d The bignum to add to.
1536 * It must be sufficiently large to store the
1537 * result of the multiplication. This means
1538 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1539 * is not known a priori.
1540 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001541 */
1542static
1543#if defined(__APPLE__) && defined(__arm__)
1544/*
1545 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1546 * appears to need this to prevent bad ARM code generation at -O3.
1547 */
1548__attribute__ ((noinline))
1549#endif
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001550void mpi_mul_hlp( size_t i,
1551 const mbedtls_mpi_uint *s,
1552 mbedtls_mpi_uint *d,
1553 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001554{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001556
1557#if defined(MULADDC_HUIT)
1558 for( ; i >= 8; i -= 8 )
1559 {
1560 MULADDC_INIT
1561 MULADDC_HUIT
1562 MULADDC_STOP
1563 }
1564
1565 for( ; i > 0; i-- )
1566 {
1567 MULADDC_INIT
1568 MULADDC_CORE
1569 MULADDC_STOP
1570 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001571#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001572 for( ; i >= 16; i -= 16 )
1573 {
1574 MULADDC_INIT
1575 MULADDC_CORE MULADDC_CORE
1576 MULADDC_CORE MULADDC_CORE
1577 MULADDC_CORE MULADDC_CORE
1578 MULADDC_CORE MULADDC_CORE
1579
1580 MULADDC_CORE MULADDC_CORE
1581 MULADDC_CORE MULADDC_CORE
1582 MULADDC_CORE MULADDC_CORE
1583 MULADDC_CORE MULADDC_CORE
1584 MULADDC_STOP
1585 }
1586
1587 for( ; i >= 8; i -= 8 )
1588 {
1589 MULADDC_INIT
1590 MULADDC_CORE MULADDC_CORE
1591 MULADDC_CORE MULADDC_CORE
1592
1593 MULADDC_CORE MULADDC_CORE
1594 MULADDC_CORE MULADDC_CORE
1595 MULADDC_STOP
1596 }
1597
1598 for( ; i > 0; i-- )
1599 {
1600 MULADDC_INIT
1601 MULADDC_CORE
1602 MULADDC_STOP
1603 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001604#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001605
1606 t++;
1607
Gilles Peskine8e464c42020-07-24 00:08:38 +02001608 while( c != 0 )
1609 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001610 *d += c; c = ( *d < c ); d++;
1611 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001612}
1613
1614/*
1615 * Baseline multiplication: X = A * B (HAC 14.12)
1616 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001618{
Janos Follath24eed8d2019-11-22 13:21:35 +00001619 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001620 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 mbedtls_mpi TA, TB;
Gilles Peskine997be0a2021-06-15 21:44:32 +02001622 int result_is_zero = 0;
Hanno Becker73d7d792018-12-11 10:35:51 +00001623 MPI_VALIDATE_RET( X != NULL );
1624 MPI_VALIDATE_RET( A != NULL );
1625 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1630 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Paul Bakker23986e52011-04-24 08:57:21 +00001632 for( i = A->n; i > 0; i-- )
1633 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001634 break;
Gilles Peskine4169c322021-06-17 14:35:25 +02001635 if( i == 0 )
Gilles Peskine997be0a2021-06-15 21:44:32 +02001636 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
Paul Bakker23986e52011-04-24 08:57:21 +00001638 for( j = B->n; j > 0; j-- )
1639 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 break;
Gilles Peskine4169c322021-06-17 14:35:25 +02001641 if( j == 0 )
Gilles Peskine997be0a2021-06-15 21:44:32 +02001642 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1645 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001646
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001647 for( ; j > 0; j-- )
1648 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001649
Gilles Peskinef4998b02021-06-10 15:51:54 +02001650 /* If the result is 0, we don't shortcut the operation, which reduces
1651 * but does not eliminate side channels leaking the zero-ness. We do
1652 * need to take care to set the sign bit properly since the library does
1653 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine997be0a2021-06-15 21:44:32 +02001654 if( result_is_zero )
Gilles Peskinef4998b02021-06-10 15:51:54 +02001655 X->s = 1;
Gilles Peskinef4998b02021-06-10 15:51:54 +02001656 else
1657 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001658
1659cleanup:
1660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001662
1663 return( ret );
1664}
1665
1666/*
1667 * Baseline multiplication: X = A * b
1668 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001670{
Hanno Becker73d7d792018-12-11 10:35:51 +00001671 MPI_VALIDATE_RET( X != NULL );
1672 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001674 /* mpi_mul_hlp can't deal with a leading 0. */
1675 size_t n = A->n;
1676 while( n > 0 && A->p[n - 1] == 0 )
1677 --n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001679 /* The general method below doesn't work if n==0 or b==0. By chance
1680 * calculating the result is trivial in those cases. */
1681 if( b == 0 || n == 0 )
1682 {
Paul Elliott986b55a2021-04-20 21:46:29 +01001683 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001684 }
1685
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001686 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001687 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001688 /* In general, A * b requires 1 limb more than b. If
1689 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1690 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001691 * copy() will take care of the growth if needed. However, experimentally,
1692 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001693 * calls to calloc() in ECP code, presumably because it reuses the
1694 * same mpi for a while and this way the mpi is more likely to directly
1695 * grow to its final size. */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001696 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
1697 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1698 mpi_mul_hlp( n, A->p, X->p, b - 1 );
1699
1700cleanup:
1701 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001702}
1703
1704/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001705 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1706 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001707 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001708static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1709 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001710{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001711#if defined(MBEDTLS_HAVE_UDBL)
1712 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001713#else
Simon Butcher9803d072016-01-03 00:24:34 +00001714 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1715 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001716 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1717 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001718 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001719#endif
1720
Simon Butcher15b15d12015-11-26 19:35:03 +00001721 /*
1722 * Check for overflow
1723 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001724 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001725 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001726 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001727
Simon Butcherf5ba0452015-12-27 23:01:55 +00001728 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001729 }
1730
1731#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001732 dividend = (mbedtls_t_udbl) u1 << biL;
1733 dividend |= (mbedtls_t_udbl) u0;
1734 quotient = dividend / d;
1735 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1736 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1737
1738 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001739 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001740
1741 return (mbedtls_mpi_uint) quotient;
1742#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001743
1744 /*
1745 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1746 * Vol. 2 - Seminumerical Algorithms, Knuth
1747 */
1748
1749 /*
1750 * Normalize the divisor, d, and dividend, u0, u1
1751 */
1752 s = mbedtls_clz( d );
1753 d = d << s;
1754
1755 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001756 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001757 u0 = u0 << s;
1758
1759 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001760 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001761
1762 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001763 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001764
1765 /*
1766 * Find the first quotient and remainder
1767 */
1768 q1 = u1 / d1;
1769 r0 = u1 - d1 * q1;
1770
1771 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1772 {
1773 q1 -= 1;
1774 r0 += d1;
1775
1776 if ( r0 >= radix ) break;
1777 }
1778
Simon Butcherf5ba0452015-12-27 23:01:55 +00001779 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001780 q0 = rAX / d1;
1781 r0 = rAX - q0 * d1;
1782
1783 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1784 {
1785 q0 -= 1;
1786 r0 += d1;
1787
1788 if ( r0 >= radix ) break;
1789 }
1790
1791 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001792 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001793
1794 quotient = q1 * radix + q0;
1795
1796 return quotient;
1797#endif
1798}
1799
1800/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001802 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001803int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1804 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001805{
Janos Follath24eed8d2019-11-22 13:21:35 +00001806 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001807 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001809 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001810 MPI_VALIDATE_RET( A != NULL );
1811 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1814 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001817 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001818 /*
1819 * Avoid dynamic memory allocations for constant-size T2.
1820 *
1821 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1822 * so nobody increase the size of the MPI and we're safe to use an on-stack
1823 * buffer.
1824 */
Alexander K35d6d462019-10-31 14:46:45 +03001825 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001826 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1827 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001831 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1832 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 return( 0 );
1834 }
1835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1837 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 X.s = Y.s = 1;
1839
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1841 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001842 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001844 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001845 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 {
1847 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1849 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 }
1851 else k = 0;
1852
1853 n = X.n - 1;
1854 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 {
1859 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001863
1864 for( i = n; i > t ; i-- )
1865 {
1866 if( X.p[i] >= Y.p[t] )
1867 Z.p[i - t - 1] = ~0;
1868 else
1869 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001870 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1871 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 }
1873
Alexander K35d6d462019-10-31 14:46:45 +03001874 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1875 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1876 T2.p[2] = X.p[i];
1877
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 Z.p[i - t - 1]++;
1879 do
1880 {
1881 Z.p[i - t - 1]--;
1882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001884 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1891 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1892 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001895 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1897 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1898 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899 Z.p[i - t - 1]--;
1900 }
1901 }
1902
1903 if( Q != NULL )
1904 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001906 Q->s = A->s * B->s;
1907 }
1908
1909 if( R != NULL )
1910 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001912 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001913 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001916 R->s = 1;
1917 }
1918
1919cleanup:
1920
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001922 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001923 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
1925 return( ret );
1926}
1927
1928/*
1929 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001930 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001931int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1932 const mbedtls_mpi *A,
1933 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001934{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001935 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001936 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001937 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
1939 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001940 B.s = ( b < 0 ) ? -1 : 1;
1941 B.n = 1;
1942 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001944 return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945}
1946
1947/*
1948 * Modulo: R = A mod B
1949 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001951{
Janos Follath24eed8d2019-11-22 13:21:35 +00001952 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001953 MPI_VALIDATE_RET( R != NULL );
1954 MPI_VALIDATE_RET( A != NULL );
1955 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1958 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1963 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1966 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
1968cleanup:
1969
1970 return( ret );
1971}
1972
1973/*
1974 * Modulo: r = A mod b
1975 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001977{
Paul Bakker23986e52011-04-24 08:57:21 +00001978 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001979 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001980 MPI_VALIDATE_RET( r != NULL );
1981 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
1983 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
1986 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001987 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001988
1989 /*
1990 * handle trivial cases
1991 */
1992 if( b == 1 )
1993 {
1994 *r = 0;
1995 return( 0 );
1996 }
1997
1998 if( b == 2 )
1999 {
2000 *r = A->p[0] & 1;
2001 return( 0 );
2002 }
2003
2004 /*
2005 * general case
2006 */
Paul Bakker23986e52011-04-24 08:57:21 +00002007 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00002008 {
Paul Bakker23986e52011-04-24 08:57:21 +00002009 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00002010 y = ( y << biH ) | ( x >> biH );
2011 z = y / b;
2012 y -= z * b;
2013
2014 x <<= biH;
2015 y = ( y << biH ) | ( x >> biH );
2016 z = y / b;
2017 y -= z * b;
2018 }
2019
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002020 /*
2021 * If A is negative, then the current y represents a negative value.
2022 * Flipping it to the positive side.
2023 */
2024 if( A->s < 0 && y != 0 )
2025 y = b - y;
2026
Paul Bakker5121ce52009-01-03 21:22:43 +00002027 *r = y;
2028
2029 return( 0 );
2030}
2031
2032/*
2033 * Fast Montgomery initialization (thanks to Tom St Denis)
2034 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002036{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002038 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
2040 x = m0;
2041 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002042
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002043 for( i = biL; i >= 8; i /= 2 )
2044 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
2046 *mm = ~x + 1;
2047}
2048
Gilles Peskine2a82f722020-06-04 15:00:49 +02002049/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2050 *
2051 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002052 * It must have at least as many limbs as N
2053 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002054 * On successful completion, A contains the result of
2055 * the multiplication A * B * R^-1 mod N where
2056 * R = (2^ciL)^n.
2057 * \param[in] B One of the numbers to multiply.
2058 * It must be nonzero and must not have more limbs than N
2059 * (B->n <= N->n).
2060 * \param[in] N The modulo. N must be odd.
2061 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2062 * This is -N^-1 mod 2^ciL.
2063 * \param[in,out] T A bignum for temporary storage.
2064 * It must be at least twice the limb size of N plus 2
2065 * (T->n >= 2 * (N->n + 1)).
2066 * Its initial content is unused and
2067 * its final content is indeterminate.
2068 * Note that unlike the usual convention in the library
2069 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002070 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002071static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002073{
Paul Bakker23986e52011-04-24 08:57:21 +00002074 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002075 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002076
2077 memset( T->p, 0, T->n * ciL );
2078
2079 d = T->p;
2080 n = N->n;
2081 m = ( B->n < n ) ? B->n : n;
2082
2083 for( i = 0; i < n; i++ )
2084 {
2085 /*
2086 * T = (T + u0*B + u1*N) / 2^biL
2087 */
2088 u0 = A->p[i];
2089 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2090
2091 mpi_mul_hlp( m, B->p, d, u0 );
2092 mpi_mul_hlp( n, N->p, d, u1 );
2093
2094 *d++ = u0; d[n + 1] = 0;
2095 }
2096
Gilles Peskine221626f2020-06-08 22:37:50 +02002097 /* At this point, d is either the desired result or the desired result
2098 * plus N. We now potentially subtract N, avoiding leaking whether the
2099 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002100
Gilles Peskine221626f2020-06-08 22:37:50 +02002101 /* Copy the n least significant limbs of d to A, so that
2102 * A = d if d < N (recall that N has n limbs). */
2103 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002104 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002105 * do the calculation without using conditional tests. */
2106 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002107 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02002108 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02002109 /* If d0 < N then d < (2^biL)^n
2110 * so d[n] == 0 and we want to keep A as it is.
2111 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2112 * so d[n] == 1 and we want to set A to the result of the subtraction
2113 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2114 * This exactly corresponds to a conditional assignment. */
gabor-mezei-arm9fa43ce2021-09-28 16:14:47 +02002115 mbedtls_cf_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002116}
2117
2118/*
2119 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002120 *
2121 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002122 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002123static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2124 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002125{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 mbedtls_mpi_uint z = 1;
2127 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
Paul Bakker8ddb6452013-02-27 14:56:33 +01002129 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002130 U.p = &z;
2131
Gilles Peskine4e91d472020-06-04 20:55:15 +02002132 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002133}
2134
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002135/**
2136 * Select an MPI from a table without leaking the index.
2137 *
2138 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2139 * reads the entire table in order to avoid leaking the value of idx to an
2140 * attacker able to observe memory access patterns.
2141 *
2142 * \param[out] R Where to write the selected MPI.
2143 * \param[in] T The table to read from.
2144 * \param[in] T_size The number of elements in the table.
2145 * \param[in] idx The index of the element to select;
2146 * this must satisfy 0 <= idx < T_size.
2147 *
2148 * \return \c 0 on success, or a negative error code.
2149 */
2150static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2151{
2152 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2153
2154 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002155 {
2156 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
gabor-mezei-arm9fa43ce2021-09-28 16:14:47 +02002157 (unsigned char) mbedtls_cf_size_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002158 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002159
2160cleanup:
2161 return( ret );
2162}
2163
Paul Bakker5121ce52009-01-03 21:22:43 +00002164/*
2165 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2166 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002167int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2168 const mbedtls_mpi *E, const mbedtls_mpi *N,
Yuto Takano538a0cb2021-07-14 10:20:09 +01002169 mbedtls_mpi *prec_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002170{
Janos Follath24eed8d2019-11-22 13:21:35 +00002171 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002172 size_t wbits, wsize, one = 1;
2173 size_t i, j, nblimbs;
2174 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002176 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002177 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
Hanno Becker73d7d792018-12-11 10:35:51 +00002179 MPI_VALIDATE_RET( X != NULL );
2180 MPI_VALIDATE_RET( A != NULL );
2181 MPI_VALIDATE_RET( E != NULL );
2182 MPI_VALIDATE_RET( N != NULL );
2183
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002184 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2188 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002189
Chris Jones9246d042020-11-25 15:12:39 +00002190 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2191 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2192 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2193
Paul Bakkerf6198c12012-05-16 08:02:29 +00002194 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002195 * Init temps and window size
2196 */
2197 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2199 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002200 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002201 memset( W, 0, sizeof( W ) );
2202
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002203 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
2205 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2206 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2207
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002208#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2210 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002211#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002212
Paul Bakker5121ce52009-01-03 21:22:43 +00002213 j = N->n + 1;
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002214 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2215 * and mpi_montred() calls later. Here we ensure that W[1] and X are
2216 * large enough, and later we'll grow other W[i] to the same length.
2217 * They must not be shrunk midway through this function!
2218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2220 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2221 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002222
2223 /*
Paul Bakker50546922012-05-19 08:40:49 +00002224 * Compensate for negative A (and correct at the end)
2225 */
2226 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002227 if( neg )
2228 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002230 Apos.s = 1;
2231 A = &Apos;
2232 }
2233
2234 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002235 * If 1st call, pre-compute R^2 mod N
2236 */
Yuto Takano538a0cb2021-07-14 10:20:09 +01002237 if( prec_RR == NULL || prec_RR->p == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00002238 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2240 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2241 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
Yuto Takano538a0cb2021-07-14 10:20:09 +01002243 if( prec_RR != NULL )
2244 memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 }
2246 else
Yuto Takano538a0cb2021-07-14 10:20:09 +01002247 memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
2249 /*
2250 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2251 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002253 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002255 /* This should be a no-op because W[1] is already that large before
2256 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2257 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine2aa3f162021-06-15 21:22:48 +02002258 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002259 }
Paul Bakkerc2024f42014-01-23 20:38:35 +01002260 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002263 /* Note that this is safe because W[1] always has at least N->n limbs
2264 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002265 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
2267 /*
2268 * X = R^2 * R^-1 mod N = R mod N
2269 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002271 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
2273 if( wsize > 1 )
2274 {
2275 /*
2276 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2277 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002278 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2281 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
2283 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002284 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002285
Paul Bakker5121ce52009-01-03 21:22:43 +00002286 /*
2287 * W[i] = W[i - 1] * W[1]
2288 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002289 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002290 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2292 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002293
Gilles Peskine4e91d472020-06-04 20:55:15 +02002294 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002295 }
2296 }
2297
2298 nblimbs = E->n;
2299 bufsize = 0;
2300 nbits = 0;
2301 wbits = 0;
2302 state = 0;
2303
2304 while( 1 )
2305 {
2306 if( bufsize == 0 )
2307 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002308 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 break;
2310
Paul Bakker0d7702c2013-10-29 16:18:35 +01002311 nblimbs--;
2312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 }
2315
2316 bufsize--;
2317
2318 ei = (E->p[nblimbs] >> bufsize) & 1;
2319
2320 /*
2321 * skip leading 0s
2322 */
2323 if( ei == 0 && state == 0 )
2324 continue;
2325
2326 if( ei == 0 && state == 1 )
2327 {
2328 /*
2329 * out of window, square X
2330 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002331 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 continue;
2333 }
2334
2335 /*
2336 * add ei to current window
2337 */
2338 state = 2;
2339
2340 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002341 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
2343 if( nbits == wsize )
2344 {
2345 /*
2346 * X = X^wsize R^-1 mod N
2347 */
2348 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002349 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
2351 /*
2352 * X = X * W[wbits] R^-1 mod N
2353 */
Manuel Pégourié-Gonnarde22176e2021-06-10 09:34:00 +02002354 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002355 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
2357 state--;
2358 nbits = 0;
2359 wbits = 0;
2360 }
2361 }
2362
2363 /*
2364 * process the remaining bits
2365 */
2366 for( i = 0; i < nbits; i++ )
2367 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002368 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
2370 wbits <<= 1;
2371
Paul Bakker66d5d072014-06-17 16:39:18 +02002372 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002373 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002374 }
2375
2376 /*
2377 * X = A^E * R * R^-1 mod N = A^E mod N
2378 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002379 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002380
Hanno Beckera4af1c42017-04-18 09:07:45 +01002381 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002382 {
2383 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002385 }
2386
Paul Bakker5121ce52009-01-03 21:22:43 +00002387cleanup:
2388
Paul Bakker66d5d072014-06-17 16:39:18 +02002389 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002393 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002394
Yuto Takano538a0cb2021-07-14 10:20:09 +01002395 if( prec_RR == NULL || prec_RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
2398 return( ret );
2399}
2400
Paul Bakker5121ce52009-01-03 21:22:43 +00002401/*
2402 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2403 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002405{
Janos Follath24eed8d2019-11-22 13:21:35 +00002406 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002407 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002408 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002409
Hanno Becker73d7d792018-12-11 10:35:51 +00002410 MPI_VALIDATE_RET( G != NULL );
2411 MPI_VALIDATE_RET( A != NULL );
2412 MPI_VALIDATE_RET( B != NULL );
2413
Alexander Ke8ad49f2019-08-16 16:16:07 +03002414 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2417 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002419 lz = mbedtls_mpi_lsb( &TA );
2420 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002421
Gilles Peskine27253bc2021-06-09 13:26:43 +02002422 /* The loop below gives the correct result when A==0 but not when B==0.
2423 * So have a special case for B==0. Leverage the fact that we just
2424 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2425 * slightly more efficient than cmp_int(). */
2426 if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2427 {
2428 ret = mbedtls_mpi_copy( G, A );
2429 goto cleanup;
2430 }
2431
Paul Bakker66d5d072014-06-17 16:39:18 +02002432 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002433 lz = lzt;
2434
Paul Bakker5121ce52009-01-03 21:22:43 +00002435 TA.s = TB.s = 1;
2436
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002437 /* We mostly follow the procedure described in HAC 14.54, but with some
2438 * minor differences:
2439 * - Sequences of multiplications or divisions by 2 are grouped into a
2440 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002441 * - The procedure in HAC assumes that 0 < TB <= TA.
2442 * - The condition TB <= TA is not actually necessary for correctness.
2443 * TA and TB have symmetric roles except for the loop termination
2444 * condition, and the shifts at the beginning of the loop body
2445 * remove any significance from the ordering of TA vs TB before
2446 * the shifts.
2447 * - If TA = 0, the loop goes through 0 iterations and the result is
2448 * correctly TB.
2449 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002450 *
2451 * For the correctness proof below, decompose the original values of
2452 * A and B as
2453 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2454 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2455 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2456 * and gcd(A',B') is odd or 0.
2457 *
2458 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2459 * The code maintains the following invariant:
2460 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002461 */
2462
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002463 /* Proof that the loop terminates:
2464 * At each iteration, either the right-shift by 1 is made on a nonzero
2465 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2466 * by at least 1, or the right-shift by 1 is made on zero and then
2467 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2468 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2469 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002471 {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002472 /* Divisions by 2 preserve the invariant (I). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2474 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002475
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002476 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2477 * TA-TB is even so the division by 2 has an integer result.
2478 * Invariant (I) is preserved since any odd divisor of both TA and TB
2479 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2480 * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
2481 * divides TA.
2482 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2486 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002487 }
2488 else
2489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2491 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002492 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002493 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002494 }
2495
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002496 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2497 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2498 * - If there was at least one loop iteration, then one of TA or TB is odd,
2499 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2500 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2501 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002502 * 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 +02002503 */
2504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2506 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002507
2508cleanup:
2509
Alexander Ke8ad49f2019-08-16 16:16:07 +03002510 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002511
2512 return( ret );
2513}
2514
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002515/* Fill X with n_bytes random bytes.
2516 * X must already have room for those bytes.
Gilles Peskineafb2bd22021-06-03 11:51:09 +02002517 * The ordering of the bytes returned from the RNG is suitable for
2518 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskineebe9b6a2021-04-13 21:55:35 +02002519 * The size and sign of X are unchanged.
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002520 * n_bytes must not be 0.
2521 */
2522static int mpi_fill_random_internal(
2523 mbedtls_mpi *X, size_t n_bytes,
2524 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2525{
2526 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2527 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2528 const size_t overhead = ( limbs * ciL ) - n_bytes;
2529
2530 if( X->n < limbs )
2531 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002532
Gilles Peskineebe9b6a2021-04-13 21:55:35 +02002533 memset( X->p, 0, overhead );
2534 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002535 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2536 mpi_bigendian_to_host( X->p, limbs );
2537
2538cleanup:
2539 return( ret );
2540}
2541
Paul Bakker33dc46b2014-04-30 16:11:39 +02002542/*
2543 * Fill X with size bytes of random.
2544 *
2545 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002546 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002547 * deterministic, eg for tests).
2548 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002549int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002550 int (*f_rng)(void *, unsigned char *, size_t),
2551 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002552{
Janos Follath24eed8d2019-11-22 13:21:35 +00002553 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002554 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002555
Hanno Becker8ce11a32018-12-19 16:18:52 +00002556 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002557 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002558
Hanno Beckerda1655a2017-10-18 14:21:44 +01002559 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +02002560 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002561 if( size == 0 )
2562 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002563
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002564 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002565
2566cleanup:
2567 return( ret );
2568}
2569
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002570int mbedtls_mpi_random( mbedtls_mpi *X,
2571 mbedtls_mpi_sint min,
2572 const mbedtls_mpi *N,
2573 int (*f_rng)(void *, unsigned char *, size_t),
2574 void *p_rng )
2575{
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002576 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee5381682021-04-13 21:23:25 +02002577 int count;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002578 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002579 size_t n_bits = mbedtls_mpi_bitlen( N );
2580 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002581 mbedtls_mpi lower_bound;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002582
Gilles Peskine1e918f42021-03-29 22:14:51 +02002583 if( min < 0 )
2584 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2585 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2586 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2587
Gilles Peskinee5381682021-04-13 21:23:25 +02002588 /*
2589 * When min == 0, each try has at worst a probability 1/2 of failing
2590 * (the msb has a probability 1/2 of being 0, and then the result will
2591 * be < N), so after 30 tries failure probability is a most 2**(-30).
2592 *
2593 * When N is just below a power of 2, as is the case when generating
Gilles Peskinee842e582021-04-15 11:45:19 +02002594 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee5381682021-04-13 21:23:25 +02002595 * overwhelming probability. When N is just above a power of 2,
Gilles Peskinee842e582021-04-15 11:45:19 +02002596 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee5381682021-04-13 21:23:25 +02002597 * a probability of failing that is almost 1/2.
2598 *
2599 * The probabilities are almost the same if min is nonzero but negligible
2600 * compared to N. This is always the case when N is crypto-sized, but
2601 * it's convenient to support small N for testing purposes. When N
2602 * is small, use a higher repeat count, otherwise the probability of
2603 * failure is macroscopic.
2604 */
Gilles Peskine87823d72021-06-02 21:18:59 +02002605 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee5381682021-04-13 21:23:25 +02002606
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002607 mbedtls_mpi_init( &lower_bound );
2608
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002609 /* Ensure that target MPI has exactly the same number of limbs
2610 * as the upper bound, even if the upper bound has leading zeros.
2611 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskineed32b572021-06-02 22:17:52 +02002612 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002613 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2614 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002615
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002616 /*
2617 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2618 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2619 * - use the same byte ordering;
2620 * - keep the leftmost n_bits bits of the generated octet string;
2621 * - try until result is in the desired range.
2622 * This also avoids any bias, which is especially important for ECDSA.
2623 */
2624 do
2625 {
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002626 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002627 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2628
Gilles Peskinee5381682021-04-13 21:23:25 +02002629 if( --count == 0 )
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002630 {
2631 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2632 goto cleanup;
2633 }
2634
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002635 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2636 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002637 }
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002638 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002639
2640cleanup:
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002641 mbedtls_mpi_free( &lower_bound );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002642 return( ret );
2643}
2644
Paul Bakker5121ce52009-01-03 21:22:43 +00002645/*
2646 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2647 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002648int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002649{
Janos Follath24eed8d2019-11-22 13:21:35 +00002650 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002651 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002652 MPI_VALIDATE_RET( X != NULL );
2653 MPI_VALIDATE_RET( A != NULL );
2654 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Hanno Becker4bcb4912017-04-18 15:49:39 +01002656 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002658
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002659 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2660 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2661 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002662
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002663 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002666 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002668 goto cleanup;
2669 }
2670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2672 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2673 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2674 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002676 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2677 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2678 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2679 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002680
2681 do
2682 {
2683 while( ( TU.p[0] & 1 ) == 0 )
2684 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002685 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002686
2687 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2688 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2690 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002691 }
2692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002693 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2694 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002695 }
2696
2697 while( ( TV.p[0] & 1 ) == 0 )
2698 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002699 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002700
2701 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2702 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002703 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2704 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002705 }
2706
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002707 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2708 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002709 }
2710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002712 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002713 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2714 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2715 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002716 }
2717 else
2718 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002719 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2720 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2721 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 }
2723 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002724 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002725
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002726 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2727 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002728
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002729 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2730 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002732 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002733
2734cleanup:
2735
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002736 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2737 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2738 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002739
2740 return( ret );
2741}
2742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002743#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002744
Paul Bakker5121ce52009-01-03 21:22:43 +00002745static const int small_prime[] =
2746{
2747 3, 5, 7, 11, 13, 17, 19, 23,
2748 29, 31, 37, 41, 43, 47, 53, 59,
2749 61, 67, 71, 73, 79, 83, 89, 97,
2750 101, 103, 107, 109, 113, 127, 131, 137,
2751 139, 149, 151, 157, 163, 167, 173, 179,
2752 181, 191, 193, 197, 199, 211, 223, 227,
2753 229, 233, 239, 241, 251, 257, 263, 269,
2754 271, 277, 281, 283, 293, 307, 311, 313,
2755 317, 331, 337, 347, 349, 353, 359, 367,
2756 373, 379, 383, 389, 397, 401, 409, 419,
2757 421, 431, 433, 439, 443, 449, 457, 461,
2758 463, 467, 479, 487, 491, 499, 503, 509,
2759 521, 523, 541, 547, 557, 563, 569, 571,
2760 577, 587, 593, 599, 601, 607, 613, 617,
2761 619, 631, 641, 643, 647, 653, 659, 661,
2762 673, 677, 683, 691, 701, 709, 719, 727,
2763 733, 739, 743, 751, 757, 761, 769, 773,
2764 787, 797, 809, 811, 821, 823, 827, 829,
2765 839, 853, 857, 859, 863, 877, 881, 883,
2766 887, 907, 911, 919, 929, 937, 941, 947,
2767 953, 967, 971, 977, 983, 991, 997, -103
2768};
2769
2770/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002771 * Small divisors test (X must be positive)
2772 *
2773 * Return values:
2774 * 0: no small factor (possible prime, more tests needed)
2775 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002776 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002777 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002778 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002779static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002780{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002781 int ret = 0;
2782 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002784
Paul Bakker5121ce52009-01-03 21:22:43 +00002785 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002786 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002787
2788 for( i = 0; small_prime[i] > 0; i++ )
2789 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002790 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002791 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002792
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002793 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002794
2795 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002796 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002797 }
2798
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002799cleanup:
2800 return( ret );
2801}
2802
2803/*
2804 * Miller-Rabin pseudo-primality test (HAC 4.24)
2805 */
Janos Follathda31fa12018-09-03 14:45:23 +01002806static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002807 int (*f_rng)(void *, unsigned char *, size_t),
2808 void *p_rng )
2809{
Pascal Junodb99183d2015-03-11 16:49:45 +01002810 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002811 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002812 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002813
Hanno Becker8ce11a32018-12-19 16:18:52 +00002814 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002815 MPI_VALIDATE_RET( f_rng != NULL );
2816
2817 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2818 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002819 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002820
Paul Bakker5121ce52009-01-03 21:22:43 +00002821 /*
2822 * W = |X| - 1
2823 * R = W >> lsb( W )
2824 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2826 s = mbedtls_mpi_lsb( &W );
2827 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2828 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002829
Janos Follathda31fa12018-09-03 14:45:23 +01002830 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002831 {
2832 /*
2833 * pick a random A, 1 < A < |X| - 1
2834 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002835 count = 0;
2836 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002837 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002838
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002839 j = mbedtls_mpi_bitlen( &A );
2840 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002841 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002842 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002843 }
2844
2845 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002846 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2847 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002848 }
2849
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002850 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2851 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002852
2853 /*
2854 * A = A^R mod |X|
2855 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002856 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002858 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2859 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002860 continue;
2861
2862 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002863 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002864 {
2865 /*
2866 * A = A * A mod |X|
2867 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002868 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2869 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002871 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002872 break;
2873
2874 j++;
2875 }
2876
2877 /*
2878 * not prime if A != |X| - 1 or A == 1
2879 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002880 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2881 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002882 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002883 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002884 break;
2885 }
2886 }
2887
2888cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002889 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2890 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002891 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002892
2893 return( ret );
2894}
2895
2896/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002897 * Pseudo-primality test: small factors, then Miller-Rabin
2898 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002899int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2900 int (*f_rng)(void *, unsigned char *, size_t),
2901 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002902{
Janos Follath24eed8d2019-11-22 13:21:35 +00002903 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002904 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002905 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002906 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002907
2908 XX.s = 1;
2909 XX.n = X->n;
2910 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002912 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2913 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2914 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002916 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002917 return( 0 );
2918
2919 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2920 {
2921 if( ret == 1 )
2922 return( 0 );
2923
2924 return( ret );
2925 }
2926
Janos Follathda31fa12018-09-03 14:45:23 +01002927 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002928}
2929
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002930/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002931 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002932 *
Janos Follathf301d232018-08-14 13:34:01 +01002933 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2934 * be either 1024 bits or 1536 bits long, and flags must contain
2935 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002936 */
Janos Follath7c025a92018-08-14 11:08:41 +01002937int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002938 int (*f_rng)(void *, unsigned char *, size_t),
2939 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002940{
Jethro Beekman66689272018-02-14 19:24:10 -08002941#ifdef MBEDTLS_HAVE_INT64
2942// ceil(2^63.5)
2943#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2944#else
2945// ceil(2^31.5)
2946#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2947#endif
2948 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002949 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002950 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002951 mbedtls_mpi_uint r;
2952 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002953
Hanno Becker8ce11a32018-12-19 16:18:52 +00002954 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002955 MPI_VALIDATE_RET( f_rng != NULL );
2956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002957 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2958 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002960 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002961
2962 n = BITS_TO_LIMBS( nbits );
2963
Janos Follathda31fa12018-09-03 14:45:23 +01002964 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2965 {
2966 /*
2967 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2968 */
2969 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2970 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2971 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2972 }
2973 else
2974 {
2975 /*
2976 * 2^-100 error probability, number of rounds computed based on HAC,
2977 * fact 4.48
2978 */
2979 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2980 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2981 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2982 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2983 }
2984
Jethro Beekman66689272018-02-14 19:24:10 -08002985 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002986 {
Jethro Beekman66689272018-02-14 19:24:10 -08002987 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2988 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2989 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2990
2991 k = n * biL;
2992 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2993 X->p[0] |= 1;
2994
Janos Follath7c025a92018-08-14 11:08:41 +01002995 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002996 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002997 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002999 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00003000 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003001 }
Jethro Beekman66689272018-02-14 19:24:10 -08003002 else
Paul Bakker5121ce52009-01-03 21:22:43 +00003003 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003004 /*
Jethro Beekman66689272018-02-14 19:24:10 -08003005 * An necessary condition for Y and X = 2Y + 1 to be prime
3006 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
3007 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003008 */
Jethro Beekman66689272018-02-14 19:24:10 -08003009
3010 X->p[0] |= 2;
3011
3012 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
3013 if( r == 0 )
3014 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
3015 else if( r == 1 )
3016 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
3017
3018 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
3019 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
3020 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
3021
3022 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003023 {
Jethro Beekman66689272018-02-14 19:24:10 -08003024 /*
3025 * First, check small factors for X and Y
3026 * before doing Miller-Rabin on any of them
3027 */
3028 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
3029 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003030 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003031 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003032 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003033 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08003034 goto cleanup;
3035
3036 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
3037 goto cleanup;
3038
3039 /*
3040 * Next candidates. We want to preserve Y = (X-1) / 2 and
3041 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3042 * so up Y by 6 and X by 12.
3043 */
3044 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
3045 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003046 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003047 }
3048 }
3049
3050cleanup:
3051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003052 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00003053
3054 return( ret );
3055}
3056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003057#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003059#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003060
Paul Bakker23986e52011-04-24 08:57:21 +00003061#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003062
3063static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3064{
3065 { 693, 609, 21 },
3066 { 1764, 868, 28 },
3067 { 768454923, 542167814, 1 }
3068};
3069
Paul Bakker5121ce52009-01-03 21:22:43 +00003070/*
3071 * Checkup routine
3072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003073int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00003074{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003075 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003076 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003078 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
3079 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003081 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003082 "EFE021C2645FD1DC586E69184AF4A31E" \
3083 "D5F53E93B5F123FA41680867BA110131" \
3084 "944FE7952E2517337780CB0DB80E61AA" \
3085 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003087 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003088 "B2E7EFD37075B9F03FF989C7C5051C20" \
3089 "34D2A323810251127E7BF8625A4F49A5" \
3090 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3091 "5B5C25763222FEFCCFC38B832366C29E" ) );
3092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003093 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003094 "0066A198186C18C10B2F5ED9B522752A" \
3095 "9830B69916E535C8F047518A889A43A5" \
3096 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3097
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003098 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003100 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003101 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3102 "9E857EA95A03512E2BAE7391688D264A" \
3103 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3104 "8001B72E848A38CAE1C65F78E56ABDEF" \
3105 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3106 "ECF677152EF804370C1A305CAF3B5BF1" \
3107 "30879B56C61DE584A0F53A2447A51E" ) );
3108
3109 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003110 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003112 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003113 {
3114 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003115 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003116
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003117 ret = 1;
3118 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003119 }
3120
3121 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003122 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003124 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003126 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003127 "256567336059E52CAE22925474705F39A94" ) );
3128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003129 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003130 "6613F26162223DF488E9CD48CC132C7A" \
3131 "0AC93C701B001B092E4E5B9F73BCD27B" \
3132 "9EE50D0657C77F374E903CDFA4C642" ) );
3133
3134 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003135 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003136
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003137 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3138 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003139 {
3140 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003141 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003142
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003143 ret = 1;
3144 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003145 }
3146
3147 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003148 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003150 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003152 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003153 "36E139AEA55215609D2816998ED020BB" \
3154 "BD96C37890F65171D948E9BC7CBAA4D9" \
3155 "325D24D6A3C12710F10A09FA08AB87" ) );
3156
3157 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003158 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003160 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003161 {
3162 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003163 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003164
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003165 ret = 1;
3166 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003167 }
3168
3169 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003170 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003172 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003174 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003175 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3176 "C3DBA76456363A10869622EAC2DD84EC" \
3177 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3178
3179 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003180 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003182 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003183 {
3184 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003185 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003186
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003187 ret = 1;
3188 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003189 }
3190
3191 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003192 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003193
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003194 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003195 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003196
Paul Bakker66d5d072014-06-17 16:39:18 +02003197 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003198 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003199 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3200 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003202 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003204 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003205 {
3206 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003207 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003208
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003209 ret = 1;
3210 goto cleanup;
3211 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003212 }
3213
3214 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003215 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003216
Paul Bakker5121ce52009-01-03 21:22:43 +00003217cleanup:
3218
3219 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003220 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003222 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3223 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003224
3225 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003226 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003227
3228 return( ret );
3229}
3230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003231#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003233#endif /* MBEDTLS_BIGNUM_C */