blob: 7caace77656a3d518225e302ab4d8693292376fa [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
Simon Butcher15b15d12015-11-26 19:35:03 +000019
Paul Bakker5121ce52009-01-03 21:22:43 +000020/*
Simon Butcher15b15d12015-11-26 19:35:03 +000021 * The following sources were referenced in the design of this Multi-precision
22 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000023 *
Simon Butcher15b15d12015-11-26 19:35:03 +000024 * [1] Handbook of Applied Cryptography - 1997
25 * Menezes, van Oorschot and Vanstone
26 *
27 * [2] Multi-Precision Math
28 * Tom St Denis
29 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30 *
31 * [3] GNU Multi-Precision Arithmetic Library
32 * https://gmplib.org/manual/index.html
33 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000034 */
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Gilles Peskinedb09ef62020-06-03 01:43:33 +020036#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/bignum.h"
41#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050042#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000043#include "mbedtls/error.h"
gabor-mezei-arm96584dd2021-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 Peskine3130ce22021-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 Peskinef643e8e2021-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 Peskinef643e8e2021-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/*
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200273 * Conditionally assign dest = src, without leaking information
274 * about whether the assignment was made or not.
275 * dest and src must be arrays of limbs of size n.
276 * assign must be 0 or 1.
277 */
gabor-mezei-arme41e3e82021-09-28 16:14:47 +0200278void mbedtls_cf_mpi_uint_cond_assign( size_t n,
279 mbedtls_mpi_uint *dest,
280 const mbedtls_mpi_uint *src,
281 unsigned char assign )
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200282{
283 size_t i;
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200284
285 /* 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
292 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
293 const mbedtls_mpi_uint mask = -assign;
294
295#if defined(_MSC_VER)
296#pragma warning( pop )
297#endif
298
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200299 for( i = 0; i < n; i++ )
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200300 dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200301}
302
303/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100304 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100305 * about whether the assignment was made or not.
306 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100309{
310 int ret = 0;
311 size_t i;
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200312 mbedtls_mpi_uint limb_mask;
Hanno Becker73d7d792018-12-11 10:35:51 +0000313 MPI_VALIDATE_RET( X != NULL );
314 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100315
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200316 /* MSVC has a warning about unary minus on unsigned integer types,
317 * but this is well-defined and precisely what we want to do here. */
318#if defined(_MSC_VER)
319#pragma warning( push )
320#pragma warning( disable : 4146 )
321#endif
322
Pascal Junodb99183d2015-03-11 16:49:45 +0100323 /* make sure assign is 0 or 1 in a time-constant manner */
Manuel Pégourié-Gonnardc94b6b02021-06-17 13:25:03 +0200324 assign = (assign | (unsigned char)-assign) >> (sizeof( assign ) * 8 - 1);
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200325 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200326 limb_mask = -assign;
327
328#if defined(_MSC_VER)
329#pragma warning( pop )
330#endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100333
gabor-mezei-arme41e3e82021-09-28 16:14:47 +0200334 X->s = mbedtls_cf_cond_select_sign( X->s, Y->s, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100335
gabor-mezei-arme41e3e82021-09-28 16:14:47 +0200336 mbedtls_cf_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100337
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200338 for( i = Y->n; i < X->n; i++ )
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200339 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100340
341cleanup:
342 return( ret );
343}
344
345/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100346 * Conditionally swap X and Y, without leaking information
347 * about whether the swap was made or not.
348 * Here it is not ok to simply swap the pointers, which whould lead to
349 * different memory access patterns when X and Y are used afterwards.
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100352{
353 int ret, s;
354 size_t i;
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200355 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000357 MPI_VALIDATE_RET( X != NULL );
358 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100359
360 if( X == Y )
361 return( 0 );
362
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200363 /* MSVC has a warning about unary minus on unsigned integer types,
364 * but this is well-defined and precisely what we want to do here. */
365#if defined(_MSC_VER)
366#pragma warning( push )
367#pragma warning( disable : 4146 )
368#endif
369
Pascal Junodb99183d2015-03-11 16:49:45 +0100370 /* make sure swap is 0 or 1 in a time-constant manner */
Manuel Pégourié-Gonnardc94b6b02021-06-17 13:25:03 +0200371 swap = (swap | (unsigned char)-swap) >> (sizeof( swap ) * 8 - 1);
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200372 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200373 limb_mask = -swap;
374
375#if defined(_MSC_VER)
376#pragma warning( pop )
377#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
380 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100381
382 s = X->s;
gabor-mezei-arme41e3e82021-09-28 16:14:47 +0200383 X->s = mbedtls_cf_cond_select_sign( X->s, Y->s, swap );
384 Y->s = mbedtls_cf_cond_select_sign( Y->s, s, swap );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100385
386
387 for( i = 0; i < X->n; i++ )
388 {
389 tmp = X->p[i];
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200390 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
391 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100392 }
393
394cleanup:
395 return( ret );
396}
397
398/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000399 * Set value from integer
400 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000402{
Janos Follath24eed8d2019-11-22 13:21:35 +0000403 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000404 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407 memset( X->p, 0, X->n * ciL );
408
409 X->p[0] = ( z < 0 ) ? -z : z;
410 X->s = ( z < 0 ) ? -1 : 1;
411
412cleanup:
413
414 return( ret );
415}
416
417/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000418 * Get a specific bit
419 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000421{
Hanno Becker73d7d792018-12-11 10:35:51 +0000422 MPI_VALIDATE_RET( X != NULL );
423
Paul Bakker2f5947e2011-05-18 15:47:11 +0000424 if( X->n * biL <= pos )
425 return( 0 );
426
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200427 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000428}
429
Gilles Peskine11cdb052018-11-20 16:47:47 +0100430/* Get a specific byte, without range checks. */
431#define GET_BYTE( X, i ) \
432 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
433
Paul Bakker2f5947e2011-05-18 15:47:11 +0000434/*
435 * Set a bit to a specific value of 0 or 1
436 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000438{
439 int ret = 0;
440 size_t off = pos / biL;
441 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000442 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000443
444 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200446
Paul Bakker2f5947e2011-05-18 15:47:11 +0000447 if( X->n * biL <= pos )
448 {
449 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200450 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000453 }
454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
456 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000457
458cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200459
Paul Bakker2f5947e2011-05-18 15:47:11 +0000460 return( ret );
461}
462
463/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200464 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000467{
Paul Bakker23986e52011-04-24 08:57:21 +0000468 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000469 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470
471 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000472 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000473 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
474 return( count );
475
476 return( 0 );
477}
478
479/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000480 * Count leading zero bits in a given integer
481 */
482static size_t mbedtls_clz( const mbedtls_mpi_uint x )
483{
484 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100485 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000486
487 for( j = 0; j < biL; j++ )
488 {
489 if( x & mask ) break;
490
491 mask >>= 1;
492 }
493
494 return j;
495}
496
497/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200498 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000499 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200500size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501{
Paul Bakker23986e52011-04-24 08:57:21 +0000502 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200504 if( X->n == 0 )
505 return( 0 );
506
Paul Bakker5121ce52009-01-03 21:22:43 +0000507 for( i = X->n - 1; i > 0; i-- )
508 if( X->p[i] != 0 )
509 break;
510
Simon Butcher15b15d12015-11-26 19:35:03 +0000511 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000512
Paul Bakker23986e52011-04-24 08:57:21 +0000513 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514}
515
516/*
517 * Return the total size in bytes
518 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000520{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200521 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000522}
523
524/*
525 * Convert an ASCII character to digit value
526 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000528{
529 *d = 255;
530
531 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
532 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
533 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 if( *d >= (mbedtls_mpi_uint) radix )
536 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000537
538 return( 0 );
539}
540
541/*
542 * Import from an ASCII string
543 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000545{
Janos Follath24eed8d2019-11-22 13:21:35 +0000546 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000547 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200548 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 mbedtls_mpi_uint d;
550 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000551 MPI_VALIDATE_RET( X != NULL );
552 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000553
554 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000555 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000558
Gilles Peskined4876132021-06-08 18:32:34 +0200559 if( s[0] == 0 )
560 {
561 mbedtls_mpi_free( X );
562 return( 0 );
563 }
564
Gilles Peskine80f56732021-04-03 18:26:13 +0200565 if( s[0] == '-' )
566 {
567 ++s;
568 sign = -1;
569 }
570
Paul Bakkerff60ee62010-03-16 21:09:09 +0000571 slen = strlen( s );
572
Paul Bakker5121ce52009-01-03 21:22:43 +0000573 if( radix == 16 )
574 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100575 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200576 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
577
Paul Bakkerff60ee62010-03-16 21:09:09 +0000578 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
581 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
Paul Bakker23986e52011-04-24 08:57:21 +0000583 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200586 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 }
588 }
589 else
590 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
Paul Bakkerff60ee62010-03-16 21:09:09 +0000593 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000594 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
596 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200597 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000598 }
599 }
600
Gilles Peskine80f56732021-04-03 18:26:13 +0200601 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
602 X->s = -1;
603
Paul Bakker5121ce52009-01-03 21:22:43 +0000604cleanup:
605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000607
608 return( ret );
609}
610
611/*
Ron Eldora16fa292018-11-20 14:07:01 +0200612 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 */
Ron Eldora16fa292018-11-20 14:07:01 +0200614static int mpi_write_hlp( mbedtls_mpi *X, int radix,
615 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000616{
Janos Follath24eed8d2019-11-22 13:21:35 +0000617 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200619 size_t length = 0;
620 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
Ron Eldora16fa292018-11-20 14:07:01 +0200622 do
623 {
624 if( length >= buflen )
625 {
626 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
627 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000628
Ron Eldora16fa292018-11-20 14:07:01 +0200629 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
630 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
631 /*
632 * Write the residue in the current position, as an ASCII character.
633 */
634 if( r < 0xA )
635 *(--p_end) = (char)( '0' + r );
636 else
637 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
Ron Eldora16fa292018-11-20 14:07:01 +0200639 length++;
640 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
Ron Eldora16fa292018-11-20 14:07:01 +0200642 memmove( *p, p_end, length );
643 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
645cleanup:
646
647 return( ret );
648}
649
650/*
651 * Export into an ASCII string
652 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100653int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
654 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000655{
Paul Bakker23986e52011-04-24 08:57:21 +0000656 int ret = 0;
657 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000658 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000660 MPI_VALIDATE_RET( X != NULL );
661 MPI_VALIDATE_RET( olen != NULL );
662 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000665 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
Hanno Becker23cfea02019-02-04 09:45:07 +0000667 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
668 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
669 * `n`. If radix > 4, this might be a strict
670 * overapproximation of the number of
671 * radix-adic digits needed to present `n`. */
672 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
673 * present `n`. */
674
Janos Follath80470622019-03-06 13:43:02 +0000675 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000676 n += 1; /* Compensate for the divisions above, which round down `n`
677 * in case it's not even. */
678 n += 1; /* Potential '-'-sign. */
679 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
680 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100682 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000683 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100684 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000686 }
687
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100688 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000692 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000693 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000694 buflen--;
695 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000696
697 if( radix == 16 )
698 {
Paul Bakker23986e52011-04-24 08:57:21 +0000699 int c;
700 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000701
Paul Bakker23986e52011-04-24 08:57:21 +0000702 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000703 {
Paul Bakker23986e52011-04-24 08:57:21 +0000704 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000705 {
Paul Bakker23986e52011-04-24 08:57:21 +0000706 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
Paul Bakker6c343d72014-07-10 14:36:19 +0200708 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000709 continue;
710
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000711 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000712 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000713 k = 1;
714 }
715 }
716 }
717 else
718 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000720
721 if( T.s == -1 )
722 T.s = 1;
723
Ron Eldora16fa292018-11-20 14:07:01 +0200724 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000725 }
726
727 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100728 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
730cleanup:
731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
734 return( ret );
735}
736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000738/*
739 * Read X from an opened file
740 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000742{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000744 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000746 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000747 * Buffer should have space for (short) label and decimal formatted MPI,
748 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000749 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000751
Hanno Becker73d7d792018-12-11 10:35:51 +0000752 MPI_VALIDATE_RET( X != NULL );
753 MPI_VALIDATE_RET( fin != NULL );
754
755 if( radix < 2 || radix > 16 )
756 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
757
Paul Bakker5121ce52009-01-03 21:22:43 +0000758 memset( s, 0, sizeof( s ) );
759 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000761
762 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000763 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000765
Hanno Beckerb2034b72017-04-26 11:46:46 +0100766 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
767 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000768
769 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100770 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000771 if( mpi_get_digit( &d, radix, *p ) != 0 )
772 break;
773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000775}
776
777/*
778 * Write X into an opened file (or stdout if fout == NULL)
779 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200780int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000781{
Janos Follath24eed8d2019-11-22 13:21:35 +0000782 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000783 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000784 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000785 * Buffer should have space for (short) label and decimal formatted MPI,
786 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000787 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000789 MPI_VALIDATE_RET( X != NULL );
790
791 if( radix < 2 || radix > 16 )
792 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000793
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100794 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000795
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100796 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000797
798 if( p == NULL ) p = "";
799
800 plen = strlen( p );
801 slen = strlen( s );
802 s[slen++] = '\r';
803 s[slen++] = '\n';
804
805 if( fout != NULL )
806 {
807 if( fwrite( p, 1, plen, fout ) != plen ||
808 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200809 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000810 }
811 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200812 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000813
814cleanup:
815
816 return( ret );
817}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200818#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000819
Hanno Beckerda1655a2017-10-18 14:21:44 +0100820
821/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
822 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000823
824static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
825{
826 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100827 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000828 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100829
830 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
831 {
832 tmp <<= CHAR_BIT;
833 tmp |= (mbedtls_mpi_uint) *x_ptr;
834 }
835
Hanno Beckerf8720072018-11-08 11:53:49 +0000836 return( tmp );
837}
838
839static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
840{
841#if defined(__BYTE_ORDER__)
842
843/* Nothing to do on bigendian systems. */
844#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
845 return( x );
846#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
847
848#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
849
850/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000851#if defined(__GNUC__) && defined(__GNUC_PREREQ)
852#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000853#define have_bswap
854#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000855#endif
856
857#if defined(__clang__) && defined(__has_builtin)
858#if __has_builtin(__builtin_bswap32) && \
859 __has_builtin(__builtin_bswap64)
860#define have_bswap
861#endif
862#endif
863
Hanno Beckerf8720072018-11-08 11:53:49 +0000864#if defined(have_bswap)
865 /* The compiler is hopefully able to statically evaluate this! */
866 switch( sizeof(mbedtls_mpi_uint) )
867 {
868 case 4:
869 return( __builtin_bswap32(x) );
870 case 8:
871 return( __builtin_bswap64(x) );
872 }
873#endif
874#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
875#endif /* __BYTE_ORDER__ */
876
877 /* Fall back to C-based reordering if we don't know the byte order
878 * or we couldn't use a compiler-specific builtin. */
879 return( mpi_uint_bigendian_to_host_c( x ) );
880}
881
Hanno Becker2be8a552018-10-25 12:40:09 +0100882static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100883{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100884 mbedtls_mpi_uint *cur_limb_left;
885 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100886 if( limbs == 0 )
887 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100888
889 /*
890 * Traverse limbs and
891 * - adapt byte-order in each limb
892 * - swap the limbs themselves.
893 * For that, simultaneously traverse the limbs from left to right
894 * and from right to left, as long as the left index is not bigger
895 * than the right index (it's not a problem if limbs is odd and the
896 * indices coincide in the last iteration).
897 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100898 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
899 cur_limb_left <= cur_limb_right;
900 cur_limb_left++, cur_limb_right-- )
901 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000902 mbedtls_mpi_uint tmp;
903 /* Note that if cur_limb_left == cur_limb_right,
904 * this code effectively swaps the bytes only once. */
905 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
906 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
907 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100908 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100909}
910
Paul Bakker5121ce52009-01-03 21:22:43 +0000911/*
Janos Follatha778a942019-02-13 10:28:28 +0000912 * Import X from unsigned binary data, little endian
913 */
914int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
915 const unsigned char *buf, size_t buflen )
916{
Janos Follath24eed8d2019-11-22 13:21:35 +0000917 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000918 size_t i;
919 size_t const limbs = CHARS_TO_LIMBS( buflen );
920
921 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200922 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000923
924 for( i = 0; i < buflen; i++ )
925 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
926
927cleanup:
928
Janos Follath171a7ef2019-02-15 16:17:45 +0000929 /*
930 * This function is also used to import keys. However, wiping the buffers
931 * upon failure is not necessary because failure only can happen before any
932 * input is copied.
933 */
Janos Follatha778a942019-02-13 10:28:28 +0000934 return( ret );
935}
936
937/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000938 * Import X from unsigned binary data, big endian
939 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000941{
Janos Follath24eed8d2019-11-22 13:21:35 +0000942 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100943 size_t const limbs = CHARS_TO_LIMBS( buflen );
944 size_t const overhead = ( limbs * ciL ) - buflen;
945 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000946
Hanno Becker8ce11a32018-12-19 16:18:52 +0000947 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000948 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
949
Hanno Becker073c1992017-10-17 15:17:27 +0100950 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200951 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000952
Gilles Peskine3130ce22021-06-02 22:17:52 +0200953 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000954 * even if buflen is 0. */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200955 if( buflen != 0 )
Hanno Becker0e810b92019-01-03 17:13:11 +0000956 {
957 Xp = (unsigned char*) X->p;
958 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100959
Hanno Becker0e810b92019-01-03 17:13:11 +0000960 mpi_bigendian_to_host( X->p, limbs );
961 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000962
963cleanup:
964
Janos Follath171a7ef2019-02-15 16:17:45 +0000965 /*
966 * This function is also used to import keys. However, wiping the buffers
967 * upon failure is not necessary because failure only can happen before any
968 * input is copied.
969 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 return( ret );
971}
972
973/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000974 * Export X into unsigned binary data, little endian
975 */
976int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
977 unsigned char *buf, size_t buflen )
978{
979 size_t stored_bytes = X->n * ciL;
980 size_t bytes_to_copy;
981 size_t i;
982
983 if( stored_bytes < buflen )
984 {
985 bytes_to_copy = stored_bytes;
986 }
987 else
988 {
989 bytes_to_copy = buflen;
990
991 /* The output buffer is smaller than the allocated size of X.
992 * However X may fit if its leading bytes are zero. */
993 for( i = bytes_to_copy; i < stored_bytes; i++ )
994 {
995 if( GET_BYTE( X, i ) != 0 )
996 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
997 }
998 }
999
1000 for( i = 0; i < bytes_to_copy; i++ )
1001 buf[i] = GET_BYTE( X, i );
1002
1003 if( stored_bytes < buflen )
1004 {
1005 /* Write trailing 0 bytes */
1006 memset( buf + stored_bytes, 0, buflen - stored_bytes );
1007 }
1008
1009 return( 0 );
1010}
1011
1012/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001013 * Export X into unsigned binary data, big endian
1014 */
Gilles Peskine11cdb052018-11-20 16:47:47 +01001015int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
1016 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001017{
Hanno Becker73d7d792018-12-11 10:35:51 +00001018 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +01001019 size_t bytes_to_copy;
1020 unsigned char *p;
1021 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001022
Hanno Becker73d7d792018-12-11 10:35:51 +00001023 MPI_VALIDATE_RET( X != NULL );
1024 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
1025
1026 stored_bytes = X->n * ciL;
1027
Gilles Peskine11cdb052018-11-20 16:47:47 +01001028 if( stored_bytes < buflen )
1029 {
1030 /* There is enough space in the output buffer. Write initial
1031 * null bytes and record the position at which to start
1032 * writing the significant bytes. In this case, the execution
1033 * trace of this function does not depend on the value of the
1034 * number. */
1035 bytes_to_copy = stored_bytes;
1036 p = buf + buflen - stored_bytes;
1037 memset( buf, 0, buflen - stored_bytes );
1038 }
1039 else
1040 {
1041 /* The output buffer is smaller than the allocated size of X.
1042 * However X may fit if its leading bytes are zero. */
1043 bytes_to_copy = buflen;
1044 p = buf;
1045 for( i = bytes_to_copy; i < stored_bytes; i++ )
1046 {
1047 if( GET_BYTE( X, i ) != 0 )
1048 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1049 }
1050 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001051
Gilles Peskine11cdb052018-11-20 16:47:47 +01001052 for( i = 0; i < bytes_to_copy; i++ )
1053 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
1055 return( 0 );
1056}
1057
1058/*
1059 * Left-shift: X <<= count
1060 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001062{
Janos Follath24eed8d2019-11-22 13:21:35 +00001063 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001064 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001066 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001067
1068 v0 = count / (biL );
1069 t1 = count & (biL - 1);
1070
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001071 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001072
Paul Bakkerf9688572011-05-05 10:00:45 +00001073 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001075
1076 ret = 0;
1077
1078 /*
1079 * shift by count / limb_size
1080 */
1081 if( v0 > 0 )
1082 {
Paul Bakker23986e52011-04-24 08:57:21 +00001083 for( i = X->n; i > v0; i-- )
1084 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001085
Paul Bakker23986e52011-04-24 08:57:21 +00001086 for( ; i > 0; i-- )
1087 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 }
1089
1090 /*
1091 * shift by count % limb_size
1092 */
1093 if( t1 > 0 )
1094 {
1095 for( i = v0; i < X->n; i++ )
1096 {
1097 r1 = X->p[i] >> (biL - t1);
1098 X->p[i] <<= t1;
1099 X->p[i] |= r0;
1100 r0 = r1;
1101 }
1102 }
1103
1104cleanup:
1105
1106 return( ret );
1107}
1108
1109/*
1110 * Right-shift: X >>= count
1111 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001112int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001113{
Paul Bakker23986e52011-04-24 08:57:21 +00001114 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001116 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001117
1118 v0 = count / biL;
1119 v1 = count & (biL - 1);
1120
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001121 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001123
Paul Bakker5121ce52009-01-03 21:22:43 +00001124 /*
1125 * shift by count / limb_size
1126 */
1127 if( v0 > 0 )
1128 {
1129 for( i = 0; i < X->n - v0; i++ )
1130 X->p[i] = X->p[i + v0];
1131
1132 for( ; i < X->n; i++ )
1133 X->p[i] = 0;
1134 }
1135
1136 /*
1137 * shift by count % limb_size
1138 */
1139 if( v1 > 0 )
1140 {
Paul Bakker23986e52011-04-24 08:57:21 +00001141 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001142 {
Paul Bakker23986e52011-04-24 08:57:21 +00001143 r1 = X->p[i - 1] << (biL - v1);
1144 X->p[i - 1] >>= v1;
1145 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001146 r0 = r1;
1147 }
1148 }
1149
1150 return( 0 );
1151}
1152
1153/*
1154 * Compare unsigned values
1155 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001156int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001157{
Paul Bakker23986e52011-04-24 08:57:21 +00001158 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001159 MPI_VALIDATE_RET( X != NULL );
1160 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
Paul Bakker23986e52011-04-24 08:57:21 +00001162 for( i = X->n; i > 0; i-- )
1163 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001164 break;
1165
Paul Bakker23986e52011-04-24 08:57:21 +00001166 for( j = Y->n; j > 0; j-- )
1167 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 break;
1169
Paul Bakker23986e52011-04-24 08:57:21 +00001170 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 return( 0 );
1172
1173 if( i > j ) return( 1 );
1174 if( j > i ) return( -1 );
1175
Paul Bakker23986e52011-04-24 08:57:21 +00001176 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 {
Paul Bakker23986e52011-04-24 08:57:21 +00001178 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1179 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001180 }
1181
1182 return( 0 );
1183}
1184
1185/*
1186 * Compare signed values
1187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001189{
Paul Bakker23986e52011-04-24 08:57:21 +00001190 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001191 MPI_VALIDATE_RET( X != NULL );
1192 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001193
Paul Bakker23986e52011-04-24 08:57:21 +00001194 for( i = X->n; i > 0; i-- )
1195 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001196 break;
1197
Paul Bakker23986e52011-04-24 08:57:21 +00001198 for( j = Y->n; j > 0; j-- )
1199 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001200 break;
1201
Paul Bakker23986e52011-04-24 08:57:21 +00001202 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 return( 0 );
1204
1205 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001206 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001207
1208 if( X->s > 0 && Y->s < 0 ) return( 1 );
1209 if( Y->s > 0 && X->s < 0 ) return( -1 );
1210
Paul Bakker23986e52011-04-24 08:57:21 +00001211 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001212 {
Paul Bakker23986e52011-04-24 08:57:21 +00001213 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1214 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001215 }
1216
1217 return( 0 );
1218}
1219
Janos Follathee6abce2019-09-05 14:47:19 +01001220/*
1221 * Compare signed values in constant time
1222 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001223int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1224 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001225{
1226 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001227 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001228 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001229
1230 MPI_VALIDATE_RET( X != NULL );
1231 MPI_VALIDATE_RET( Y != NULL );
1232 MPI_VALIDATE_RET( ret != NULL );
1233
1234 if( X->n != Y->n )
1235 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1236
1237 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001238 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1239 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001240 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001241 X_is_negative = ( X->s & 2 ) >> 1;
1242 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001243
1244 /*
1245 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001246 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1247 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001248 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001249 cond = ( X_is_negative ^ Y_is_negative );
1250 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001251
1252 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001253 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001254 * need to go through the loop. Record if we have the result already.
1255 */
Janos Follathee6abce2019-09-05 14:47:19 +01001256 done = cond;
1257
1258 for( i = X->n; i > 0; i-- )
1259 {
1260 /*
Janos Follath30702422019-11-05 12:24:52 +00001261 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1262 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001263 *
1264 * Again even if we can make a decision, we just mark the result and
1265 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001266 */
gabor-mezei-arme41e3e82021-09-28 16:14:47 +02001267 cond = mbedtls_cf_mpi_uint_lt( Y->p[i - 1], X->p[i - 1] );
Janos Follath30702422019-11-05 12:24:52 +00001268 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001269 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001270
1271 /*
Janos Follath30702422019-11-05 12:24:52 +00001272 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1273 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001274 *
1275 * Again even if we can make a decision, we just mark the result and
1276 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001277 */
gabor-mezei-arme41e3e82021-09-28 16:14:47 +02001278 cond = mbedtls_cf_mpi_uint_lt( X->p[i - 1], Y->p[i - 1] );
Janos Follath30702422019-11-05 12:24:52 +00001279 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001280 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001281 }
1282
1283 return( 0 );
1284}
1285
Paul Bakker5121ce52009-01-03 21:22:43 +00001286/*
1287 * Compare signed values
1288 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001290{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 mbedtls_mpi Y;
1292 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001293 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001294
1295 *p = ( z < 0 ) ? -z : z;
1296 Y.s = ( z < 0 ) ? -1 : 1;
1297 Y.n = 1;
1298 Y.p = p;
1299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001301}
1302
1303/*
1304 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1305 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001307{
Janos Follath24eed8d2019-11-22 13:21:35 +00001308 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001309 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001310 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001311 MPI_VALIDATE_RET( X != NULL );
1312 MPI_VALIDATE_RET( A != NULL );
1313 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001314
1315 if( X == B )
1316 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001318 }
1319
1320 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001322
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001323 /*
1324 * X should always be positive as a result of unsigned additions.
1325 */
1326 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001327
Paul Bakker23986e52011-04-24 08:57:21 +00001328 for( j = B->n; j > 0; j-- )
1329 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 break;
1331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001333
1334 o = B->p; p = X->p; c = 0;
1335
Janos Follath6c922682015-10-30 17:43:11 +01001336 /*
1337 * tmp is used because it might happen that p == o
1338 */
Paul Bakker23986e52011-04-24 08:57:21 +00001339 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 {
Janos Follath6c922682015-10-30 17:43:11 +01001341 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001343 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344 }
1345
1346 while( c != 0 )
1347 {
1348 if( i >= X->n )
1349 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351 p = X->p + i;
1352 }
1353
Paul Bakker2d319fd2012-09-16 21:34:26 +00001354 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001355 }
1356
1357cleanup:
1358
1359 return( ret );
1360}
1361
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001362/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001363 * Helper for mbedtls_mpi subtraction.
1364 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001365 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001366 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001367 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001368 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001369 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001370 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001371 * \param n Number of limbs of \p d, \p l and \p r.
1372 * \param[out] d The result of the subtraction.
1373 * \param[in] l The left operand.
1374 * \param[in] r The right operand.
1375 *
1376 * \return 1 if `l < r`.
1377 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001379static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1380 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001381 const mbedtls_mpi_uint *l,
1382 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001383{
Paul Bakker23986e52011-04-24 08:57:21 +00001384 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001385 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001387 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001389 z = ( l[i] < c ); t = l[i] - c;
1390 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001391 }
1392
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001393 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001394}
1395
1396/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001397 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001400{
Janos Follath24eed8d2019-11-22 13:21:35 +00001401 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001402 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001403 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001404 MPI_VALIDATE_RET( X != NULL );
1405 MPI_VALIDATE_RET( A != NULL );
1406 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407
Paul Bakker23986e52011-04-24 08:57:21 +00001408 for( n = B->n; n > 0; n-- )
1409 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001411 if( n > A->n )
1412 {
1413 /* B >= (2^ciL)^n > A */
1414 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1415 goto cleanup;
1416 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001417
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001418 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1419
1420 /* Set the high limbs of X to match A. Don't touch the lower limbs
1421 * because X might be aliased to B, and we must not overwrite the
1422 * significant digits of B. */
1423 if( A->n > n )
1424 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1425 if( X->n > A->n )
1426 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1427
1428 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001429 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001430 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001431 /* Propagate the carry to the first nonzero limb of X. */
1432 for( ; n < X->n && X->p[n] == 0; n++ )
1433 --X->p[n];
1434 /* If we ran out of space for the carry, it means that the result
1435 * is negative. */
1436 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001437 {
1438 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1439 goto cleanup;
1440 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001441 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001442 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001443
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001444 /* X should always be positive as a result of unsigned subtractions. */
1445 X->s = 1;
1446
Paul Bakker5121ce52009-01-03 21:22:43 +00001447cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001448 return( ret );
1449}
1450
1451/*
1452 * Signed addition: X = A + B
1453 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001454int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001455{
Hanno Becker73d7d792018-12-11 10:35:51 +00001456 int ret, s;
1457 MPI_VALIDATE_RET( X != NULL );
1458 MPI_VALIDATE_RET( A != NULL );
1459 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001460
Hanno Becker73d7d792018-12-11 10:35:51 +00001461 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001462 if( A->s * B->s < 0 )
1463 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001465 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467 X->s = s;
1468 }
1469 else
1470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001472 X->s = -s;
1473 }
1474 }
1475 else
1476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001478 X->s = s;
1479 }
1480
1481cleanup:
1482
1483 return( ret );
1484}
1485
1486/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001487 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001488 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001490{
Hanno Becker73d7d792018-12-11 10:35:51 +00001491 int ret, s;
1492 MPI_VALIDATE_RET( X != NULL );
1493 MPI_VALIDATE_RET( A != NULL );
1494 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
Hanno Becker73d7d792018-12-11 10:35:51 +00001496 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 if( A->s * B->s > 0 )
1498 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 X->s = s;
1503 }
1504 else
1505 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507 X->s = -s;
1508 }
1509 }
1510 else
1511 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513 X->s = s;
1514 }
1515
1516cleanup:
1517
1518 return( ret );
1519}
1520
1521/*
1522 * Signed addition: X = A + b
1523 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001525{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001526 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001527 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001528 MPI_VALIDATE_RET( X != NULL );
1529 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001530
1531 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001532 B.s = ( b < 0 ) ? -1 : 1;
1533 B.n = 1;
1534 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001536 return( mbedtls_mpi_add_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001537}
1538
1539/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001540 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001543{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001544 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001546 MPI_VALIDATE_RET( X != NULL );
1547 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001548
1549 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001550 B.s = ( b < 0 ) ? -1 : 1;
1551 B.n = 1;
1552 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001554 return( mbedtls_mpi_sub_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555}
1556
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001557/** Helper for mbedtls_mpi multiplication.
1558 *
1559 * Add \p b * \p s to \p d.
1560 *
1561 * \param i The number of limbs of \p s.
1562 * \param[in] s A bignum to multiply, of size \p i.
1563 * It may overlap with \p d, but only if
1564 * \p d <= \p s.
1565 * Its leading limb must not be \c 0.
1566 * \param[in,out] d The bignum to add to.
1567 * It must be sufficiently large to store the
1568 * result of the multiplication. This means
1569 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1570 * is not known a priori.
1571 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001572 */
1573static
1574#if defined(__APPLE__) && defined(__arm__)
1575/*
1576 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1577 * appears to need this to prevent bad ARM code generation at -O3.
1578 */
1579__attribute__ ((noinline))
1580#endif
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001581void mpi_mul_hlp( size_t i,
1582 const mbedtls_mpi_uint *s,
1583 mbedtls_mpi_uint *d,
1584 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001585{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001587
1588#if defined(MULADDC_HUIT)
1589 for( ; i >= 8; i -= 8 )
1590 {
1591 MULADDC_INIT
1592 MULADDC_HUIT
1593 MULADDC_STOP
1594 }
1595
1596 for( ; i > 0; i-- )
1597 {
1598 MULADDC_INIT
1599 MULADDC_CORE
1600 MULADDC_STOP
1601 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001602#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001603 for( ; i >= 16; i -= 16 )
1604 {
1605 MULADDC_INIT
1606 MULADDC_CORE MULADDC_CORE
1607 MULADDC_CORE MULADDC_CORE
1608 MULADDC_CORE MULADDC_CORE
1609 MULADDC_CORE MULADDC_CORE
1610
1611 MULADDC_CORE MULADDC_CORE
1612 MULADDC_CORE MULADDC_CORE
1613 MULADDC_CORE MULADDC_CORE
1614 MULADDC_CORE MULADDC_CORE
1615 MULADDC_STOP
1616 }
1617
1618 for( ; i >= 8; i -= 8 )
1619 {
1620 MULADDC_INIT
1621 MULADDC_CORE MULADDC_CORE
1622 MULADDC_CORE MULADDC_CORE
1623
1624 MULADDC_CORE MULADDC_CORE
1625 MULADDC_CORE MULADDC_CORE
1626 MULADDC_STOP
1627 }
1628
1629 for( ; i > 0; i-- )
1630 {
1631 MULADDC_INIT
1632 MULADDC_CORE
1633 MULADDC_STOP
1634 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001635#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001636
1637 t++;
1638
Gilles Peskine8e464c42020-07-24 00:08:38 +02001639 while( c != 0 )
1640 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001641 *d += c; c = ( *d < c ); d++;
1642 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001643}
1644
1645/*
1646 * Baseline multiplication: X = A * B (HAC 14.12)
1647 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001649{
Janos Follath24eed8d2019-11-22 13:21:35 +00001650 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001651 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652 mbedtls_mpi TA, TB;
Gilles Peskined65b5002021-06-15 21:44:32 +02001653 int result_is_zero = 0;
Hanno Becker73d7d792018-12-11 10:35:51 +00001654 MPI_VALIDATE_RET( X != NULL );
1655 MPI_VALIDATE_RET( A != NULL );
1656 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1661 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001662
Paul Bakker23986e52011-04-24 08:57:21 +00001663 for( i = A->n; i > 0; i-- )
1664 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001665 break;
Gilles Peskine38a384d2021-06-17 14:35:25 +02001666 if( i == 0 )
Gilles Peskined65b5002021-06-15 21:44:32 +02001667 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001668
Paul Bakker23986e52011-04-24 08:57:21 +00001669 for( j = B->n; j > 0; j-- )
1670 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001671 break;
Gilles Peskine38a384d2021-06-17 14:35:25 +02001672 if( j == 0 )
Gilles Peskined65b5002021-06-15 21:44:32 +02001673 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001674
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001675 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1676 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001677
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001678 for( ; j > 0; j-- )
1679 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001680
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001681 /* If the result is 0, we don't shortcut the operation, which reduces
1682 * but does not eliminate side channels leaking the zero-ness. We do
1683 * need to take care to set the sign bit properly since the library does
1684 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskined65b5002021-06-15 21:44:32 +02001685 if( result_is_zero )
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001686 X->s = 1;
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001687 else
1688 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
1690cleanup:
1691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
1694 return( ret );
1695}
1696
1697/*
1698 * Baseline multiplication: X = A * b
1699 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001701{
Hanno Becker73d7d792018-12-11 10:35:51 +00001702 MPI_VALIDATE_RET( X != NULL );
1703 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001705 /* mpi_mul_hlp can't deal with a leading 0. */
1706 size_t n = A->n;
1707 while( n > 0 && A->p[n - 1] == 0 )
1708 --n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001709
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001710 /* The general method below doesn't work if n==0 or b==0. By chance
1711 * calculating the result is trivial in those cases. */
1712 if( b == 0 || n == 0 )
1713 {
Paul Elliott986b55a2021-04-20 21:46:29 +01001714 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001715 }
1716
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001717 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001718 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001719 /* In general, A * b requires 1 limb more than b. If
1720 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1721 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001722 * copy() will take care of the growth if needed. However, experimentally,
1723 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001724 * calls to calloc() in ECP code, presumably because it reuses the
1725 * same mpi for a while and this way the mpi is more likely to directly
1726 * grow to its final size. */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001727 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
1728 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1729 mpi_mul_hlp( n, A->p, X->p, b - 1 );
1730
1731cleanup:
1732 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733}
1734
1735/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001736 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1737 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001738 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001739static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1740 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001741{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001742#if defined(MBEDTLS_HAVE_UDBL)
1743 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001744#else
Simon Butcher9803d072016-01-03 00:24:34 +00001745 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1746 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001747 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1748 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001749 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001750#endif
1751
Simon Butcher15b15d12015-11-26 19:35:03 +00001752 /*
1753 * Check for overflow
1754 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001755 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001756 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001757 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001758
Simon Butcherf5ba0452015-12-27 23:01:55 +00001759 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001760 }
1761
1762#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001763 dividend = (mbedtls_t_udbl) u1 << biL;
1764 dividend |= (mbedtls_t_udbl) u0;
1765 quotient = dividend / d;
1766 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1767 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1768
1769 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001770 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001771
1772 return (mbedtls_mpi_uint) quotient;
1773#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001774
1775 /*
1776 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1777 * Vol. 2 - Seminumerical Algorithms, Knuth
1778 */
1779
1780 /*
1781 * Normalize the divisor, d, and dividend, u0, u1
1782 */
1783 s = mbedtls_clz( d );
1784 d = d << s;
1785
1786 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001787 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001788 u0 = u0 << s;
1789
1790 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001791 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001792
1793 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001794 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001795
1796 /*
1797 * Find the first quotient and remainder
1798 */
1799 q1 = u1 / d1;
1800 r0 = u1 - d1 * q1;
1801
1802 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1803 {
1804 q1 -= 1;
1805 r0 += d1;
1806
1807 if ( r0 >= radix ) break;
1808 }
1809
Simon Butcherf5ba0452015-12-27 23:01:55 +00001810 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001811 q0 = rAX / d1;
1812 r0 = rAX - q0 * d1;
1813
1814 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1815 {
1816 q0 -= 1;
1817 r0 += d1;
1818
1819 if ( r0 >= radix ) break;
1820 }
1821
1822 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001823 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001824
1825 quotient = q1 * radix + q0;
1826
1827 return quotient;
1828#endif
1829}
1830
1831/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001834int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1835 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001836{
Janos Follath24eed8d2019-11-22 13:21:35 +00001837 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001838 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001840 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001841 MPI_VALIDATE_RET( A != NULL );
1842 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1845 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001848 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001849 /*
1850 * Avoid dynamic memory allocations for constant-size T2.
1851 *
1852 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1853 * so nobody increase the size of the MPI and we're safe to use an on-stack
1854 * buffer.
1855 */
Alexander K35d6d462019-10-31 14:46:45 +03001856 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001857 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1858 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001859
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001861 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1863 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 return( 0 );
1865 }
1866
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1868 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 X.s = Y.s = 1;
1870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1872 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001873 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001874
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001875 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001876 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001877 {
1878 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 }
1882 else k = 0;
1883
1884 n = X.n - 1;
1885 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 {
1890 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894
1895 for( i = n; i > t ; i-- )
1896 {
1897 if( X.p[i] >= Y.p[t] )
1898 Z.p[i - t - 1] = ~0;
1899 else
1900 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001901 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1902 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 }
1904
Alexander K35d6d462019-10-31 14:46:45 +03001905 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1906 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1907 T2.p[2] = X.p[i];
1908
Paul Bakker5121ce52009-01-03 21:22:43 +00001909 Z.p[i - t - 1]++;
1910 do
1911 {
1912 Z.p[i - t - 1]--;
1913
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001914 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001915 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001916 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001918 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1922 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1923 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1928 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1929 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930 Z.p[i - t - 1]--;
1931 }
1932 }
1933
1934 if( Q != NULL )
1935 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001936 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937 Q->s = A->s * B->s;
1938 }
1939
1940 if( R != NULL )
1941 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001943 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 R->s = 1;
1948 }
1949
1950cleanup:
1951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001953 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001954 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955
1956 return( ret );
1957}
1958
1959/*
1960 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001961 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001962int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1963 const mbedtls_mpi *A,
1964 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001965{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001966 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001968 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001971 B.s = ( b < 0 ) ? -1 : 1;
1972 B.n = 1;
1973 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001975 return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001976}
1977
1978/*
1979 * Modulo: R = A mod B
1980 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001982{
Janos Follath24eed8d2019-11-22 13:21:35 +00001983 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001984 MPI_VALIDATE_RET( R != NULL );
1985 MPI_VALIDATE_RET( A != NULL );
1986 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1989 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001990
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1994 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1997 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
1999cleanup:
2000
2001 return( ret );
2002}
2003
2004/*
2005 * Modulo: r = A mod b
2006 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00002008{
Paul Bakker23986e52011-04-24 08:57:21 +00002009 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00002011 MPI_VALIDATE_RET( r != NULL );
2012 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
2014 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00002016
2017 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
2020 /*
2021 * handle trivial cases
2022 */
2023 if( b == 1 )
2024 {
2025 *r = 0;
2026 return( 0 );
2027 }
2028
2029 if( b == 2 )
2030 {
2031 *r = A->p[0] & 1;
2032 return( 0 );
2033 }
2034
2035 /*
2036 * general case
2037 */
Paul Bakker23986e52011-04-24 08:57:21 +00002038 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00002039 {
Paul Bakker23986e52011-04-24 08:57:21 +00002040 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00002041 y = ( y << biH ) | ( x >> biH );
2042 z = y / b;
2043 y -= z * b;
2044
2045 x <<= biH;
2046 y = ( y << biH ) | ( x >> biH );
2047 z = y / b;
2048 y -= z * b;
2049 }
2050
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002051 /*
2052 * If A is negative, then the current y represents a negative value.
2053 * Flipping it to the positive side.
2054 */
2055 if( A->s < 0 && y != 0 )
2056 y = b - y;
2057
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 *r = y;
2059
2060 return( 0 );
2061}
2062
2063/*
2064 * Fast Montgomery initialization (thanks to Tom St Denis)
2065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002067{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002069 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
2071 x = m0;
2072 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002073
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002074 for( i = biL; i >= 8; i /= 2 )
2075 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002076
2077 *mm = ~x + 1;
2078}
2079
Gilles Peskine2a82f722020-06-04 15:00:49 +02002080/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2081 *
2082 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002083 * It must have at least as many limbs as N
2084 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002085 * On successful completion, A contains the result of
2086 * the multiplication A * B * R^-1 mod N where
2087 * R = (2^ciL)^n.
2088 * \param[in] B One of the numbers to multiply.
2089 * It must be nonzero and must not have more limbs than N
2090 * (B->n <= N->n).
2091 * \param[in] N The modulo. N must be odd.
2092 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2093 * This is -N^-1 mod 2^ciL.
2094 * \param[in,out] T A bignum for temporary storage.
2095 * It must be at least twice the limb size of N plus 2
2096 * (T->n >= 2 * (N->n + 1)).
2097 * Its initial content is unused and
2098 * its final content is indeterminate.
2099 * Note that unlike the usual convention in the library
2100 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002101 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002102static 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 +02002103 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002104{
Paul Bakker23986e52011-04-24 08:57:21 +00002105 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
2108 memset( T->p, 0, T->n * ciL );
2109
2110 d = T->p;
2111 n = N->n;
2112 m = ( B->n < n ) ? B->n : n;
2113
2114 for( i = 0; i < n; i++ )
2115 {
2116 /*
2117 * T = (T + u0*B + u1*N) / 2^biL
2118 */
2119 u0 = A->p[i];
2120 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2121
2122 mpi_mul_hlp( m, B->p, d, u0 );
2123 mpi_mul_hlp( n, N->p, d, u1 );
2124
2125 *d++ = u0; d[n + 1] = 0;
2126 }
2127
Gilles Peskine221626f2020-06-08 22:37:50 +02002128 /* At this point, d is either the desired result or the desired result
2129 * plus N. We now potentially subtract N, avoiding leaking whether the
2130 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002131
Gilles Peskine221626f2020-06-08 22:37:50 +02002132 /* Copy the n least significant limbs of d to A, so that
2133 * A = d if d < N (recall that N has n limbs). */
2134 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002135 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002136 * do the calculation without using conditional tests. */
2137 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002138 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02002139 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02002140 /* If d0 < N then d < (2^biL)^n
2141 * so d[n] == 0 and we want to keep A as it is.
2142 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2143 * so d[n] == 1 and we want to set A to the result of the subtraction
2144 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2145 * This exactly corresponds to a conditional assignment. */
gabor-mezei-arme41e3e82021-09-28 16:14:47 +02002146 mbedtls_cf_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147}
2148
2149/*
2150 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002151 *
2152 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002153 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002154static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2155 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002156{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 mbedtls_mpi_uint z = 1;
2158 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
Paul Bakker8ddb6452013-02-27 14:56:33 +01002160 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002161 U.p = &z;
2162
Gilles Peskine4e91d472020-06-04 20:55:15 +02002163 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002164}
2165
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002166/**
2167 * Select an MPI from a table without leaking the index.
2168 *
2169 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2170 * reads the entire table in order to avoid leaking the value of idx to an
2171 * attacker able to observe memory access patterns.
2172 *
2173 * \param[out] R Where to write the selected MPI.
2174 * \param[in] T The table to read from.
2175 * \param[in] T_size The number of elements in the table.
2176 * \param[in] idx The index of the element to select;
2177 * this must satisfy 0 <= idx < T_size.
2178 *
2179 * \return \c 0 on success, or a negative error code.
2180 */
2181static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2182{
2183 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2184
2185 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002186 {
2187 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
gabor-mezei-arme41e3e82021-09-28 16:14:47 +02002188 (unsigned char) mbedtls_cf_size_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002189 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002190
2191cleanup:
2192 return( ret );
2193}
2194
Paul Bakker5121ce52009-01-03 21:22:43 +00002195/*
2196 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2197 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002198int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2199 const mbedtls_mpi *E, const mbedtls_mpi *N,
Yuto Takano284857e2021-07-14 10:20:09 +01002200 mbedtls_mpi *prec_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002201{
Janos Follath24eed8d2019-11-22 13:21:35 +00002202 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002203 size_t wbits, wsize, one = 1;
2204 size_t i, j, nblimbs;
2205 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002207 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002208 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002209
Hanno Becker73d7d792018-12-11 10:35:51 +00002210 MPI_VALIDATE_RET( X != NULL );
2211 MPI_VALIDATE_RET( A != NULL );
2212 MPI_VALIDATE_RET( E != NULL );
2213 MPI_VALIDATE_RET( N != NULL );
2214
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002215 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002216 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2219 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002220
Chris Jones9246d042020-11-25 15:12:39 +00002221 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2222 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2223 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2224
Paul Bakkerf6198c12012-05-16 08:02:29 +00002225 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002226 * Init temps and window size
2227 */
2228 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2230 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002231 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002232 memset( W, 0, sizeof( W ) );
2233
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002234 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002235
2236 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2237 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2238
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002239#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2241 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002242#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002243
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 j = N->n + 1;
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002245 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2246 * and mpi_montred() calls later. Here we ensure that W[1] and X are
2247 * large enough, and later we'll grow other W[i] to the same length.
2248 * They must not be shrunk midway through this function!
2249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2251 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2252 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002253
2254 /*
Paul Bakker50546922012-05-19 08:40:49 +00002255 * Compensate for negative A (and correct at the end)
2256 */
2257 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002258 if( neg )
2259 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002261 Apos.s = 1;
2262 A = &Apos;
2263 }
2264
2265 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002266 * If 1st call, pre-compute R^2 mod N
2267 */
Yuto Takano284857e2021-07-14 10:20:09 +01002268 if( prec_RR == NULL || prec_RR->p == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2271 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2272 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
Yuto Takano284857e2021-07-14 10:20:09 +01002274 if( prec_RR != NULL )
2275 memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 }
2277 else
Yuto Takano284857e2021-07-14 10:20:09 +01002278 memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
2280 /*
2281 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2282 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002284 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002286 /* This should be a no-op because W[1] is already that large before
2287 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2288 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine0759cad2021-06-15 21:22:48 +02002289 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002290 }
Paul Bakkerc2024f42014-01-23 20:38:35 +01002291 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002293
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002294 /* Note that this is safe because W[1] always has at least N->n limbs
2295 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002296 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
2298 /*
2299 * X = R^2 * R^-1 mod N = R mod N
2300 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002302 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
2304 if( wsize > 1 )
2305 {
2306 /*
2307 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2308 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002309 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2312 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
2314 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002315 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002316
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 /*
2318 * W[i] = W[i - 1] * W[1]
2319 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002320 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002321 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2323 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002324
Gilles Peskine4e91d472020-06-04 20:55:15 +02002325 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002326 }
2327 }
2328
2329 nblimbs = E->n;
2330 bufsize = 0;
2331 nbits = 0;
2332 wbits = 0;
2333 state = 0;
2334
2335 while( 1 )
2336 {
2337 if( bufsize == 0 )
2338 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002339 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002340 break;
2341
Paul Bakker0d7702c2013-10-29 16:18:35 +01002342 nblimbs--;
2343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002345 }
2346
2347 bufsize--;
2348
2349 ei = (E->p[nblimbs] >> bufsize) & 1;
2350
2351 /*
2352 * skip leading 0s
2353 */
2354 if( ei == 0 && state == 0 )
2355 continue;
2356
2357 if( ei == 0 && state == 1 )
2358 {
2359 /*
2360 * out of window, square X
2361 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002362 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002363 continue;
2364 }
2365
2366 /*
2367 * add ei to current window
2368 */
2369 state = 2;
2370
2371 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002372 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
2374 if( nbits == wsize )
2375 {
2376 /*
2377 * X = X^wsize R^-1 mod N
2378 */
2379 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002380 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002381
2382 /*
2383 * X = X * W[wbits] R^-1 mod N
2384 */
Manuel Pégourié-Gonnard0b3bde52021-06-10 09:34:00 +02002385 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002386 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
2388 state--;
2389 nbits = 0;
2390 wbits = 0;
2391 }
2392 }
2393
2394 /*
2395 * process the remaining bits
2396 */
2397 for( i = 0; i < nbits; i++ )
2398 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002399 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002400
2401 wbits <<= 1;
2402
Paul Bakker66d5d072014-06-17 16:39:18 +02002403 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002404 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 }
2406
2407 /*
2408 * X = A^E * R * R^-1 mod N = A^E mod N
2409 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002410 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002411
Hanno Beckera4af1c42017-04-18 09:07:45 +01002412 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002413 {
2414 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002416 }
2417
Paul Bakker5121ce52009-01-03 21:22:43 +00002418cleanup:
2419
Paul Bakker66d5d072014-06-17 16:39:18 +02002420 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002424 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002425
Yuto Takano284857e2021-07-14 10:20:09 +01002426 if( prec_RR == NULL || prec_RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
2429 return( ret );
2430}
2431
Paul Bakker5121ce52009-01-03 21:22:43 +00002432/*
2433 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2434 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002435int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002436{
Janos Follath24eed8d2019-11-22 13:21:35 +00002437 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002438 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002439 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002440
Hanno Becker73d7d792018-12-11 10:35:51 +00002441 MPI_VALIDATE_RET( G != NULL );
2442 MPI_VALIDATE_RET( A != NULL );
2443 MPI_VALIDATE_RET( B != NULL );
2444
Alexander Ke8ad49f2019-08-16 16:16:07 +03002445 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2448 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 lz = mbedtls_mpi_lsb( &TA );
2451 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002452
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002453 /* The loop below gives the correct result when A==0 but not when B==0.
2454 * So have a special case for B==0. Leverage the fact that we just
2455 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2456 * slightly more efficient than cmp_int(). */
2457 if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2458 {
2459 ret = mbedtls_mpi_copy( G, A );
2460 goto cleanup;
2461 }
2462
Paul Bakker66d5d072014-06-17 16:39:18 +02002463 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002464 lz = lzt;
2465
Paul Bakker5121ce52009-01-03 21:22:43 +00002466 TA.s = TB.s = 1;
2467
Gilles Peskineea9aa142021-06-16 13:42:04 +02002468 /* We mostly follow the procedure described in HAC 14.54, but with some
2469 * minor differences:
2470 * - Sequences of multiplications or divisions by 2 are grouped into a
2471 * single shift operation.
Gilles Peskine37d690c2021-06-21 18:58:39 +02002472 * - The procedure in HAC assumes that 0 < TB <= TA.
2473 * - The condition TB <= TA is not actually necessary for correctness.
2474 * TA and TB have symmetric roles except for the loop termination
2475 * condition, and the shifts at the beginning of the loop body
2476 * remove any significance from the ordering of TA vs TB before
2477 * the shifts.
2478 * - If TA = 0, the loop goes through 0 iterations and the result is
2479 * correctly TB.
2480 * - The case TB = 0 was short-circuited above.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002481 *
2482 * For the correctness proof below, decompose the original values of
2483 * A and B as
2484 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2485 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2486 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2487 * and gcd(A',B') is odd or 0.
2488 *
2489 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2490 * The code maintains the following invariant:
2491 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine6537bdb2021-06-15 22:09:39 +02002492 */
2493
Gilles Peskineea9aa142021-06-16 13:42:04 +02002494 /* Proof that the loop terminates:
2495 * At each iteration, either the right-shift by 1 is made on a nonzero
2496 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2497 * by at least 1, or the right-shift by 1 is made on zero and then
2498 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2499 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2500 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002502 {
Gilles Peskineea9aa142021-06-16 13:42:04 +02002503 /* Divisions by 2 preserve the invariant (I). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2505 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002506
Gilles Peskineea9aa142021-06-16 13:42:04 +02002507 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2508 * TA-TB is even so the division by 2 has an integer result.
2509 * Invariant (I) is preserved since any odd divisor of both TA and TB
2510 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2511 * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
2512 * divides TA.
2513 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002516 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2517 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002518 }
2519 else
2520 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2522 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002523 }
Gilles Peskineea9aa142021-06-16 13:42:04 +02002524 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002525 }
2526
Gilles Peskineea9aa142021-06-16 13:42:04 +02002527 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2528 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2529 * - If there was at least one loop iteration, then one of TA or TB is odd,
2530 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2531 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2532 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskineb798b352021-06-21 11:40:38 +02002533 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002534 */
2535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002536 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2537 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002538
2539cleanup:
2540
Alexander Ke8ad49f2019-08-16 16:16:07 +03002541 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002542
2543 return( ret );
2544}
2545
Gilles Peskine8f454702021-04-01 15:57:18 +02002546/* Fill X with n_bytes random bytes.
2547 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002548 * The ordering of the bytes returned from the RNG is suitable for
2549 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002550 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002551 * n_bytes must not be 0.
2552 */
2553static int mpi_fill_random_internal(
2554 mbedtls_mpi *X, size_t n_bytes,
2555 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2556{
2557 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2558 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2559 const size_t overhead = ( limbs * ciL ) - n_bytes;
2560
2561 if( X->n < limbs )
2562 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine8f454702021-04-01 15:57:18 +02002563
Gilles Peskinea16001e2021-04-13 21:55:35 +02002564 memset( X->p, 0, overhead );
2565 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine8f454702021-04-01 15:57:18 +02002566 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2567 mpi_bigendian_to_host( X->p, limbs );
2568
2569cleanup:
2570 return( ret );
2571}
2572
Paul Bakker33dc46b2014-04-30 16:11:39 +02002573/*
2574 * Fill X with size bytes of random.
2575 *
2576 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002577 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002578 * deterministic, eg for tests).
2579 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002580int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002581 int (*f_rng)(void *, unsigned char *, size_t),
2582 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002583{
Janos Follath24eed8d2019-11-22 13:21:35 +00002584 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002585 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002586
Hanno Becker8ce11a32018-12-19 16:18:52 +00002587 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002588 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002589
Hanno Beckerda1655a2017-10-18 14:21:44 +01002590 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002591 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002592 if( size == 0 )
2593 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002594
Gilles Peskine8f454702021-04-01 15:57:18 +02002595 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002596
2597cleanup:
2598 return( ret );
2599}
2600
Gilles Peskine4699fa42021-03-29 22:02:55 +02002601int mbedtls_mpi_random( mbedtls_mpi *X,
2602 mbedtls_mpi_sint min,
2603 const mbedtls_mpi *N,
2604 int (*f_rng)(void *, unsigned char *, size_t),
2605 void *p_rng )
2606{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002607 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002608 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002609 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002610 size_t n_bits = mbedtls_mpi_bitlen( N );
2611 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002612 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002613
Gilles Peskine9312ba52021-03-29 22:14:51 +02002614 if( min < 0 )
2615 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2616 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2617 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2618
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002619 /*
2620 * When min == 0, each try has at worst a probability 1/2 of failing
2621 * (the msb has a probability 1/2 of being 0, and then the result will
2622 * be < N), so after 30 tries failure probability is a most 2**(-30).
2623 *
2624 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002625 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002626 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002627 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002628 * a probability of failing that is almost 1/2.
2629 *
2630 * The probabilities are almost the same if min is nonzero but negligible
2631 * compared to N. This is always the case when N is crypto-sized, but
2632 * it's convenient to support small N for testing purposes. When N
2633 * is small, use a higher repeat count, otherwise the probability of
2634 * failure is macroscopic.
2635 */
Gilles Peskine11779072021-06-02 21:18:59 +02002636 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002637
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002638 mbedtls_mpi_init( &lower_bound );
2639
Gilles Peskine8f454702021-04-01 15:57:18 +02002640 /* Ensure that target MPI has exactly the same number of limbs
2641 * as the upper bound, even if the upper bound has leading zeros.
2642 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002643 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002644 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2645 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002646
Gilles Peskine4699fa42021-03-29 22:02:55 +02002647 /*
2648 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2649 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2650 * - use the same byte ordering;
2651 * - keep the leftmost n_bits bits of the generated octet string;
2652 * - try until result is in the desired range.
2653 * This also avoids any bias, which is especially important for ECDSA.
2654 */
2655 do
2656 {
Gilles Peskine8f454702021-04-01 15:57:18 +02002657 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002658 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2659
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002660 if( --count == 0 )
Gilles Peskine4699fa42021-03-29 22:02:55 +02002661 {
2662 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2663 goto cleanup;
2664 }
2665
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002666 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2667 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002668 }
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002669 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002670
2671cleanup:
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002672 mbedtls_mpi_free( &lower_bound );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002673 return( ret );
2674}
2675
Paul Bakker5121ce52009-01-03 21:22:43 +00002676/*
2677 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2678 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002679int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002680{
Janos Follath24eed8d2019-11-22 13:21:35 +00002681 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002683 MPI_VALIDATE_RET( X != NULL );
2684 MPI_VALIDATE_RET( A != NULL );
2685 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002686
Hanno Becker4bcb4912017-04-18 15:49:39 +01002687 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002688 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2691 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2692 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002696 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002697 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002699 goto cleanup;
2700 }
2701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2703 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2704 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2705 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002706
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002707 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2708 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2709 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2710 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002711
2712 do
2713 {
2714 while( ( TU.p[0] & 1 ) == 0 )
2715 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002716 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002717
2718 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2719 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002720 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2721 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 }
2723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002724 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2725 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002726 }
2727
2728 while( ( TV.p[0] & 1 ) == 0 )
2729 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002731
2732 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2733 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002734 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2735 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002736 }
2737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002738 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2739 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002740 }
2741
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002742 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002743 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2745 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2746 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002747 }
2748 else
2749 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002750 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2751 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2752 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002753 }
2754 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002755 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002756
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002757 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2758 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002760 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2761 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002763 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002764
2765cleanup:
2766
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002767 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2768 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2769 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002770
2771 return( ret );
2772}
2773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002775
Paul Bakker5121ce52009-01-03 21:22:43 +00002776static const int small_prime[] =
2777{
2778 3, 5, 7, 11, 13, 17, 19, 23,
2779 29, 31, 37, 41, 43, 47, 53, 59,
2780 61, 67, 71, 73, 79, 83, 89, 97,
2781 101, 103, 107, 109, 113, 127, 131, 137,
2782 139, 149, 151, 157, 163, 167, 173, 179,
2783 181, 191, 193, 197, 199, 211, 223, 227,
2784 229, 233, 239, 241, 251, 257, 263, 269,
2785 271, 277, 281, 283, 293, 307, 311, 313,
2786 317, 331, 337, 347, 349, 353, 359, 367,
2787 373, 379, 383, 389, 397, 401, 409, 419,
2788 421, 431, 433, 439, 443, 449, 457, 461,
2789 463, 467, 479, 487, 491, 499, 503, 509,
2790 521, 523, 541, 547, 557, 563, 569, 571,
2791 577, 587, 593, 599, 601, 607, 613, 617,
2792 619, 631, 641, 643, 647, 653, 659, 661,
2793 673, 677, 683, 691, 701, 709, 719, 727,
2794 733, 739, 743, 751, 757, 761, 769, 773,
2795 787, 797, 809, 811, 821, 823, 827, 829,
2796 839, 853, 857, 859, 863, 877, 881, 883,
2797 887, 907, 911, 919, 929, 937, 941, 947,
2798 953, 967, 971, 977, 983, 991, 997, -103
2799};
2800
2801/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002802 * Small divisors test (X must be positive)
2803 *
2804 * Return values:
2805 * 0: no small factor (possible prime, more tests needed)
2806 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002808 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002809 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002810static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002811{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002812 int ret = 0;
2813 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002814 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002815
Paul Bakker5121ce52009-01-03 21:22:43 +00002816 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002818
2819 for( i = 0; small_prime[i] > 0; i++ )
2820 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002821 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002822 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002824 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002825
2826 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002827 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002828 }
2829
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002830cleanup:
2831 return( ret );
2832}
2833
2834/*
2835 * Miller-Rabin pseudo-primality test (HAC 4.24)
2836 */
Janos Follathda31fa12018-09-03 14:45:23 +01002837static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002838 int (*f_rng)(void *, unsigned char *, size_t),
2839 void *p_rng )
2840{
Pascal Junodb99183d2015-03-11 16:49:45 +01002841 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002842 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002843 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002844
Hanno Becker8ce11a32018-12-19 16:18:52 +00002845 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002846 MPI_VALIDATE_RET( f_rng != NULL );
2847
2848 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2849 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002850 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002851
Paul Bakker5121ce52009-01-03 21:22:43 +00002852 /*
2853 * W = |X| - 1
2854 * R = W >> lsb( W )
2855 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002856 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2857 s = mbedtls_mpi_lsb( &W );
2858 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2859 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002860
Janos Follathda31fa12018-09-03 14:45:23 +01002861 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002862 {
2863 /*
2864 * pick a random A, 1 < A < |X| - 1
2865 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002866 count = 0;
2867 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002868 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002869
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002870 j = mbedtls_mpi_bitlen( &A );
2871 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002872 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002873 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002874 }
2875
2876 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002877 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2878 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002879 }
2880
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002881 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2882 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002883
2884 /*
2885 * A = A^R mod |X|
2886 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002887 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002888
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002889 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2890 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002891 continue;
2892
2893 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002894 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002895 {
2896 /*
2897 * A = A * A mod |X|
2898 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002899 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2900 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002902 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002903 break;
2904
2905 j++;
2906 }
2907
2908 /*
2909 * not prime if A != |X| - 1 or A == 1
2910 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002911 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2912 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002913 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002914 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002915 break;
2916 }
2917 }
2918
2919cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002920 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2921 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002922 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002923
2924 return( ret );
2925}
2926
2927/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002928 * Pseudo-primality test: small factors, then Miller-Rabin
2929 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002930int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2931 int (*f_rng)(void *, unsigned char *, size_t),
2932 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002933{
Janos Follath24eed8d2019-11-22 13:21:35 +00002934 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002935 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002936 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002937 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002938
2939 XX.s = 1;
2940 XX.n = X->n;
2941 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002942
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002943 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2944 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2945 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002946
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002947 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002948 return( 0 );
2949
2950 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2951 {
2952 if( ret == 1 )
2953 return( 0 );
2954
2955 return( ret );
2956 }
2957
Janos Follathda31fa12018-09-03 14:45:23 +01002958 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002959}
2960
Janos Follatha0b67c22018-09-18 14:48:23 +01002961#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002962/*
2963 * Pseudo-primality test, error probability 2^-80
2964 */
2965int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2966 int (*f_rng)(void *, unsigned char *, size_t),
2967 void *p_rng )
2968{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002969 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002970 MPI_VALIDATE_RET( f_rng != NULL );
2971
Janos Follatha0b67c22018-09-18 14:48:23 +01002972 /*
2973 * In the past our key generation aimed for an error rate of at most
2974 * 2^-80. Since this function is deprecated, aim for the same certainty
2975 * here as well.
2976 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002977 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002978}
Janos Follatha0b67c22018-09-18 14:48:23 +01002979#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002980
2981/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002982 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002983 *
Janos Follathf301d232018-08-14 13:34:01 +01002984 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2985 * be either 1024 bits or 1536 bits long, and flags must contain
2986 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002987 */
Janos Follath7c025a92018-08-14 11:08:41 +01002988int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002989 int (*f_rng)(void *, unsigned char *, size_t),
2990 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002991{
Jethro Beekman66689272018-02-14 19:24:10 -08002992#ifdef MBEDTLS_HAVE_INT64
2993// ceil(2^63.5)
2994#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2995#else
2996// ceil(2^31.5)
2997#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2998#endif
2999 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00003000 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01003001 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003002 mbedtls_mpi_uint r;
3003 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00003004
Hanno Becker8ce11a32018-12-19 16:18:52 +00003005 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00003006 MPI_VALIDATE_RET( f_rng != NULL );
3007
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003008 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
3009 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00003010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003011 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00003012
3013 n = BITS_TO_LIMBS( nbits );
3014
Janos Follathda31fa12018-09-03 14:45:23 +01003015 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
3016 {
3017 /*
3018 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
3019 */
3020 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
3021 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
3022 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
3023 }
3024 else
3025 {
3026 /*
3027 * 2^-100 error probability, number of rounds computed based on HAC,
3028 * fact 4.48
3029 */
3030 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
3031 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
3032 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
3033 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
3034 }
3035
Jethro Beekman66689272018-02-14 19:24:10 -08003036 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003037 {
Jethro Beekman66689272018-02-14 19:24:10 -08003038 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
3039 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
3040 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
3041
3042 k = n * biL;
3043 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
3044 X->p[0] |= 1;
3045
Janos Follath7c025a92018-08-14 11:08:41 +01003046 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003047 {
Janos Follatha0b67c22018-09-18 14:48:23 +01003048 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08003049
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003050 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00003051 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003052 }
Jethro Beekman66689272018-02-14 19:24:10 -08003053 else
Paul Bakker5121ce52009-01-03 21:22:43 +00003054 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003055 /*
Jethro Beekman66689272018-02-14 19:24:10 -08003056 * An necessary condition for Y and X = 2Y + 1 to be prime
3057 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
3058 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003059 */
Jethro Beekman66689272018-02-14 19:24:10 -08003060
3061 X->p[0] |= 2;
3062
3063 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
3064 if( r == 0 )
3065 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
3066 else if( r == 1 )
3067 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
3068
3069 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
3070 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
3071 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
3072
3073 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003074 {
Jethro Beekman66689272018-02-14 19:24:10 -08003075 /*
3076 * First, check small factors for X and Y
3077 * before doing Miller-Rabin on any of them
3078 */
3079 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
3080 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003081 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003082 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003083 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003084 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08003085 goto cleanup;
3086
3087 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
3088 goto cleanup;
3089
3090 /*
3091 * Next candidates. We want to preserve Y = (X-1) / 2 and
3092 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3093 * so up Y by 6 and X by 12.
3094 */
3095 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
3096 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003097 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003098 }
3099 }
3100
3101cleanup:
3102
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003103 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00003104
3105 return( ret );
3106}
3107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003108#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003110#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003111
Paul Bakker23986e52011-04-24 08:57:21 +00003112#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003113
3114static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3115{
3116 { 693, 609, 21 },
3117 { 1764, 868, 28 },
3118 { 768454923, 542167814, 1 }
3119};
3120
Paul Bakker5121ce52009-01-03 21:22:43 +00003121/*
3122 * Checkup routine
3123 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003124int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00003125{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003126 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003127 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003129 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
3130 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003132 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003133 "EFE021C2645FD1DC586E69184AF4A31E" \
3134 "D5F53E93B5F123FA41680867BA110131" \
3135 "944FE7952E2517337780CB0DB80E61AA" \
3136 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003138 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003139 "B2E7EFD37075B9F03FF989C7C5051C20" \
3140 "34D2A323810251127E7BF8625A4F49A5" \
3141 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3142 "5B5C25763222FEFCCFC38B832366C29E" ) );
3143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003144 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003145 "0066A198186C18C10B2F5ED9B522752A" \
3146 "9830B69916E535C8F047518A889A43A5" \
3147 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003149 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003151 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003152 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3153 "9E857EA95A03512E2BAE7391688D264A" \
3154 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3155 "8001B72E848A38CAE1C65F78E56ABDEF" \
3156 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3157 "ECF677152EF804370C1A305CAF3B5BF1" \
3158 "30879B56C61DE584A0F53A2447A51E" ) );
3159
3160 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003161 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003163 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003164 {
3165 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003166 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003167
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003168 ret = 1;
3169 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003170 }
3171
3172 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003173 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003175 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003177 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003178 "256567336059E52CAE22925474705F39A94" ) );
3179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003180 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003181 "6613F26162223DF488E9CD48CC132C7A" \
3182 "0AC93C701B001B092E4E5B9F73BCD27B" \
3183 "9EE50D0657C77F374E903CDFA4C642" ) );
3184
3185 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003186 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003188 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3189 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003190 {
3191 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003192 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003193
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003194 ret = 1;
3195 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003196 }
3197
3198 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003199 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003201 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003203 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003204 "36E139AEA55215609D2816998ED020BB" \
3205 "BD96C37890F65171D948E9BC7CBAA4D9" \
3206 "325D24D6A3C12710F10A09FA08AB87" ) );
3207
3208 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003209 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003211 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003212 {
3213 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003214 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003215
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003216 ret = 1;
3217 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003218 }
3219
3220 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003221 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003223 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003225 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003226 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3227 "C3DBA76456363A10869622EAC2DD84EC" \
3228 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3229
3230 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003231 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003233 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003234 {
3235 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003236 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003237
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003238 ret = 1;
3239 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003240 }
3241
3242 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003243 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003244
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003245 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003246 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003247
Paul Bakker66d5d072014-06-17 16:39:18 +02003248 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003249 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003250 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3251 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003253 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003254
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003255 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003256 {
3257 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003258 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003259
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003260 ret = 1;
3261 goto cleanup;
3262 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003263 }
3264
3265 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003266 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003267
Paul Bakker5121ce52009-01-03 21:22:43 +00003268cleanup:
3269
3270 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003271 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003273 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3274 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003275
3276 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003277 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003278
3279 return( ret );
3280}
3281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003282#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003284#endif /* MBEDTLS_BIGNUM_C */