blob: dd80eb4fd3ad2026bec3376cab0c25312d64d32f [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"
Paul Bakker5121ce52009-01-03 21:22:43 +000044
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <string.h>
46
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000048#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020049#else
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <stdio.h>
51#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020053#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020055#endif
56
Hanno Becker73d7d792018-12-11 10:35:51 +000057#define MPI_VALIDATE_RET( cond ) \
58 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
59#define MPI_VALIDATE( cond ) \
60 MBEDTLS_INTERNAL_VALIDATE( cond )
61
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000063#define biL (ciL << 3) /* bits in limb */
64#define biH (ciL << 2) /* half limb size */
65
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010066#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
67
Paul Bakker5121ce52009-01-03 21:22:43 +000068/*
69 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020070 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000071 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020072#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
73#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000074
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050075/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050076static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
77{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050078 mbedtls_platform_zeroize( v, ciL * n );
79}
80
Paul Bakker5121ce52009-01-03 21:22:43 +000081/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000083 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000085{
Hanno Becker73d7d792018-12-11 10:35:51 +000086 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000087
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 X->s = 1;
89 X->n = 0;
90 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000091}
92
93/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000094 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 if( X == NULL )
99 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200103 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 }
106
Paul Bakker6c591fa2011-05-05 11:49:20 +0000107 X->s = 1;
108 X->n = 0;
109 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000110}
111
112/*
113 * Enlarge to the specified number of limbs
114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000116{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000118 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200121 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000122
Paul Bakker5121ce52009-01-03 21:22:43 +0000123 if( X->n < nblimbs )
124 {
Simon Butcher29176892016-05-20 00:19:09 +0100125 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->p != NULL )
129 {
130 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200131 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 }
134
135 X->n = nblimbs;
136 X->p = p;
137 }
138
139 return( 0 );
140}
141
142/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143 * Resize down as much as possible,
144 * while keeping at least the specified number of limbs
145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000150 MPI_VALIDATE_RET( X != NULL );
151
152 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
153 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100155 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100156 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100158 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 for( i = X->n - 1; i > 0; i-- )
161 if( X->p[i] != 0 )
162 break;
163 i++;
164
165 if( i < nblimbs )
166 i = nblimbs;
167
Simon Butcher29176892016-05-20 00:19:09 +0100168 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200169 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171 if( X->p != NULL )
172 {
173 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200174 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100176 }
177
178 X->n = i;
179 X->p = p;
180
181 return( 0 );
182}
183
Gilles Peskine3130ce22021-06-02 22:17:52 +0200184/* Resize X to have exactly n limbs and set it to 0. */
185static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
186{
187 if( limbs == 0 )
188 {
189 mbedtls_mpi_free( X );
190 return( 0 );
191 }
192 else if( X->n == limbs )
193 {
194 memset( X->p, 0, limbs * ciL );
195 X->s = 1;
196 return( 0 );
197 }
198 else
199 {
200 mbedtls_mpi_free( X );
201 return( mbedtls_mpi_grow( X, limbs ) );
202 }
203}
204
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100205/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000206 * Copy the contents of Y into X
207 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000209{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100210 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000211 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000212 MPI_VALIDATE_RET( X != NULL );
213 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
215 if( X == Y )
216 return( 0 );
217
Gilles Peskinedb420622020-01-20 21:12:50 +0100218 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200219 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200221 return( 0 );
222 }
223
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 for( i = Y->n - 1; i > 0; i-- )
225 if( Y->p[i] != 0 )
226 break;
227 i++;
228
229 X->s = Y->s;
230
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100231 if( X->n < i )
232 {
233 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
234 }
235 else
236 {
237 memset( X->p + i, 0, ( X->n - i ) * ciL );
238 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
Paul Bakker5121ce52009-01-03 21:22:43 +0000240 memcpy( X->p, Y->p, i * ciL );
241
242cleanup:
243
244 return( ret );
245}
246
247/*
248 * Swap the contents of X and Y
249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000251{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE( X != NULL );
254 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 memcpy( &T, X, sizeof( mbedtls_mpi ) );
257 memcpy( X, Y, sizeof( mbedtls_mpi ) );
258 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000259}
260
Manuel Pégourié-Gonnard5325b972021-06-07 09:51:00 +0200261/**
262 * Select between two sign values in constant-time.
263 *
264 * This is functionally equivalent to second ? a : b but uses only bit
265 * operations in order to avoid branches.
266 *
267 * \param[in] a The first sign; must be either +1 or -1.
268 * \param[in] b The second sign; must be either +1 or -1.
269 * \param[in] second Must be either 1 (return b) or 0 (return a).
270 *
271 * \return The selected sign value.
272 */
273static int mpi_safe_cond_select_sign( int a, int b, unsigned char second )
274{
275 /* In order to avoid questions about what we can reasonnably assume about
276 * the representations of signed integers, move everything to unsigned
277 * by taking advantage of the fact that a and b are either +1 or -1. */
278 unsigned ua = a + 1;
279 unsigned ub = b + 1;
280
Manuel Pégourié-Gonnardf10d2892021-06-10 09:36:41 +0200281 /* second was 0 or 1, mask is 0 or 2 as are ua and ub */
282 const unsigned mask = second << 1;
Manuel Pégourié-Gonnard5325b972021-06-07 09:51:00 +0200283
284 /* select ua or ub */
285 unsigned ur = ( ua & ~mask ) | ( ub & mask );
286
287 /* ur is now 0 or 2, convert back to -1 or +1 */
288 return( (int) ur - 1 );
289}
290
Paul Bakker5121ce52009-01-03 21:22:43 +0000291/*
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200292 * Conditionally assign dest = src, without leaking information
293 * about whether the assignment was made or not.
294 * dest and src must be arrays of limbs of size n.
295 * assign must be 0 or 1.
296 */
297static void mpi_safe_cond_assign( size_t n,
298 mbedtls_mpi_uint *dest,
299 const mbedtls_mpi_uint *src,
300 unsigned char assign )
301{
302 size_t i;
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200303
304 /* MSVC has a warning about unary minus on unsigned integer types,
305 * but this is well-defined and precisely what we want to do here. */
306#if defined(_MSC_VER)
307#pragma warning( push )
308#pragma warning( disable : 4146 )
309#endif
310
311 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
312 const mbedtls_mpi_uint mask = -assign;
313
314#if defined(_MSC_VER)
315#pragma warning( pop )
316#endif
317
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200318 for( i = 0; i < n; i++ )
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200319 dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200320}
321
322/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100323 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100324 * about whether the assignment was made or not.
325 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100328{
329 int ret = 0;
330 size_t i;
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200331 mbedtls_mpi_uint limb_mask;
Hanno Becker73d7d792018-12-11 10:35:51 +0000332 MPI_VALIDATE_RET( X != NULL );
333 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100334
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200335 /* MSVC has a warning about unary minus on unsigned integer types,
336 * but this is well-defined and precisely what we want to do here. */
337#if defined(_MSC_VER)
338#pragma warning( push )
339#pragma warning( disable : 4146 )
340#endif
341
Pascal Junodb99183d2015-03-11 16:49:45 +0100342 /* make sure assign is 0 or 1 in a time-constant manner */
Manuel Pégourié-Gonnardc94b6b02021-06-17 13:25:03 +0200343 assign = (assign | (unsigned char)-assign) >> (sizeof( assign ) * 8 - 1);
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200344 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200345 limb_mask = -assign;
346
347#if defined(_MSC_VER)
348#pragma warning( pop )
349#endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100352
Manuel Pégourié-Gonnard5325b972021-06-07 09:51:00 +0200353 X->s = mpi_safe_cond_select_sign( X->s, Y->s, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100354
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200355 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100356
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200357 for( i = Y->n; i < X->n; i++ )
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200358 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100359
360cleanup:
361 return( ret );
362}
363
364/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100365 * Conditionally swap X and Y, without leaking information
366 * about whether the swap was made or not.
367 * Here it is not ok to simply swap the pointers, which whould lead to
368 * different memory access patterns when X and Y are used afterwards.
369 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100371{
372 int ret, s;
373 size_t i;
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200374 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000376 MPI_VALIDATE_RET( X != NULL );
377 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100378
379 if( X == Y )
380 return( 0 );
381
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200382 /* MSVC has a warning about unary minus on unsigned integer types,
383 * but this is well-defined and precisely what we want to do here. */
384#if defined(_MSC_VER)
385#pragma warning( push )
386#pragma warning( disable : 4146 )
387#endif
388
Pascal Junodb99183d2015-03-11 16:49:45 +0100389 /* make sure swap is 0 or 1 in a time-constant manner */
Manuel Pégourié-Gonnardc94b6b02021-06-17 13:25:03 +0200390 swap = (swap | (unsigned char)-swap) >> (sizeof( swap ) * 8 - 1);
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200391 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200392 limb_mask = -swap;
393
394#if defined(_MSC_VER)
395#pragma warning( pop )
396#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100397
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
399 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100400
401 s = X->s;
Manuel Pégourié-Gonnard5325b972021-06-07 09:51:00 +0200402 X->s = mpi_safe_cond_select_sign( X->s, Y->s, swap );
403 Y->s = mpi_safe_cond_select_sign( Y->s, s, swap );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100404
405
406 for( i = 0; i < X->n; i++ )
407 {
408 tmp = X->p[i];
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200409 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
410 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100411 }
412
413cleanup:
414 return( ret );
415}
416
417/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000418 * Set value from integer
419 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000421{
Janos Follath24eed8d2019-11-22 13:21:35 +0000422 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000423 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426 memset( X->p, 0, X->n * ciL );
427
428 X->p[0] = ( z < 0 ) ? -z : z;
429 X->s = ( z < 0 ) ? -1 : 1;
430
431cleanup:
432
433 return( ret );
434}
435
436/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000437 * Get a specific bit
438 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000440{
Hanno Becker73d7d792018-12-11 10:35:51 +0000441 MPI_VALIDATE_RET( X != NULL );
442
Paul Bakker2f5947e2011-05-18 15:47:11 +0000443 if( X->n * biL <= pos )
444 return( 0 );
445
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200446 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000447}
448
Gilles Peskine11cdb052018-11-20 16:47:47 +0100449/* Get a specific byte, without range checks. */
450#define GET_BYTE( X, i ) \
451 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
452
Paul Bakker2f5947e2011-05-18 15:47:11 +0000453/*
454 * Set a bit to a specific value of 0 or 1
455 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000457{
458 int ret = 0;
459 size_t off = pos / biL;
460 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000461 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000462
463 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200465
Paul Bakker2f5947e2011-05-18 15:47:11 +0000466 if( X->n * biL <= pos )
467 {
468 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200469 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000472 }
473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
475 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000476
477cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200478
Paul Bakker2f5947e2011-05-18 15:47:11 +0000479 return( ret );
480}
481
482/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200483 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000484 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000486{
Paul Bakker23986e52011-04-24 08:57:21 +0000487 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000488 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000491 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000492 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
493 return( count );
494
495 return( 0 );
496}
497
498/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000499 * Count leading zero bits in a given integer
500 */
501static size_t mbedtls_clz( const mbedtls_mpi_uint x )
502{
503 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100504 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000505
506 for( j = 0; j < biL; j++ )
507 {
508 if( x & mask ) break;
509
510 mask >>= 1;
511 }
512
513 return j;
514}
515
516/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200517 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000518 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200519size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000520{
Paul Bakker23986e52011-04-24 08:57:21 +0000521 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200523 if( X->n == 0 )
524 return( 0 );
525
Paul Bakker5121ce52009-01-03 21:22:43 +0000526 for( i = X->n - 1; i > 0; i-- )
527 if( X->p[i] != 0 )
528 break;
529
Simon Butcher15b15d12015-11-26 19:35:03 +0000530 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000531
Paul Bakker23986e52011-04-24 08:57:21 +0000532 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000533}
534
535/*
536 * Return the total size in bytes
537 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000539{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200540 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000541}
542
543/*
544 * Convert an ASCII character to digit value
545 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000547{
548 *d = 255;
549
550 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
551 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
552 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 if( *d >= (mbedtls_mpi_uint) radix )
555 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
557 return( 0 );
558}
559
560/*
561 * Import from an ASCII string
562 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000564{
Janos Follath24eed8d2019-11-22 13:21:35 +0000565 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000566 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200567 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 mbedtls_mpi_uint d;
569 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000570 MPI_VALIDATE_RET( X != NULL );
571 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000572
573 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000574 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
Gilles Peskine80f56732021-04-03 18:26:13 +0200578 if( s[0] == '-' )
579 {
580 ++s;
581 sign = -1;
582 }
583
Paul Bakkerff60ee62010-03-16 21:09:09 +0000584 slen = strlen( s );
585
Paul Bakker5121ce52009-01-03 21:22:43 +0000586 if( radix == 16 )
587 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100588 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200589 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
590
Paul Bakkerff60ee62010-03-16 21:09:09 +0000591 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
594 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
Paul Bakker23986e52011-04-24 08:57:21 +0000596 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000597 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200599 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000600 }
601 }
602 else
603 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
Paul Bakkerff60ee62010-03-16 21:09:09 +0000606 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000607 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
609 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200610 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 }
612 }
613
Gilles Peskine80f56732021-04-03 18:26:13 +0200614 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
615 X->s = -1;
616
Paul Bakker5121ce52009-01-03 21:22:43 +0000617cleanup:
618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000620
621 return( ret );
622}
623
624/*
Ron Eldora16fa292018-11-20 14:07:01 +0200625 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000626 */
Ron Eldora16fa292018-11-20 14:07:01 +0200627static int mpi_write_hlp( mbedtls_mpi *X, int radix,
628 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000629{
Janos Follath24eed8d2019-11-22 13:21:35 +0000630 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200632 size_t length = 0;
633 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000634
Ron Eldora16fa292018-11-20 14:07:01 +0200635 do
636 {
637 if( length >= buflen )
638 {
639 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
640 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
Ron Eldora16fa292018-11-20 14:07:01 +0200642 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
643 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
644 /*
645 * Write the residue in the current position, as an ASCII character.
646 */
647 if( r < 0xA )
648 *(--p_end) = (char)( '0' + r );
649 else
650 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
Ron Eldora16fa292018-11-20 14:07:01 +0200652 length++;
653 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654
Ron Eldora16fa292018-11-20 14:07:01 +0200655 memmove( *p, p_end, length );
656 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658cleanup:
659
660 return( ret );
661}
662
663/*
664 * Export into an ASCII string
665 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100666int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
667 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000668{
Paul Bakker23986e52011-04-24 08:57:21 +0000669 int ret = 0;
670 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000671 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000673 MPI_VALIDATE_RET( X != NULL );
674 MPI_VALIDATE_RET( olen != NULL );
675 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
677 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000678 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
Hanno Becker23cfea02019-02-04 09:45:07 +0000680 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
681 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
682 * `n`. If radix > 4, this might be a strict
683 * overapproximation of the number of
684 * radix-adic digits needed to present `n`. */
685 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
686 * present `n`. */
687
Janos Follath80470622019-03-06 13:43:02 +0000688 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000689 n += 1; /* Compensate for the divisions above, which round down `n`
690 * in case it's not even. */
691 n += 1; /* Potential '-'-sign. */
692 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
693 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100695 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000696 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100697 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000699 }
700
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100701 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
704 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000705 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000706 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000707 buflen--;
708 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000709
710 if( radix == 16 )
711 {
Paul Bakker23986e52011-04-24 08:57:21 +0000712 int c;
713 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
Paul Bakker23986e52011-04-24 08:57:21 +0000715 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000716 {
Paul Bakker23986e52011-04-24 08:57:21 +0000717 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000718 {
Paul Bakker23986e52011-04-24 08:57:21 +0000719 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
Paul Bakker6c343d72014-07-10 14:36:19 +0200721 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000722 continue;
723
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000724 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000725 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000726 k = 1;
727 }
728 }
729 }
730 else
731 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000733
734 if( T.s == -1 )
735 T.s = 1;
736
Ron Eldora16fa292018-11-20 14:07:01 +0200737 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000738 }
739
740 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100741 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
743cleanup:
744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000746
747 return( ret );
748}
749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000751/*
752 * Read X from an opened file
753 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200754int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000755{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000757 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000758 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000759 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000760 * Buffer should have space for (short) label and decimal formatted MPI,
761 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000762 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
Hanno Becker73d7d792018-12-11 10:35:51 +0000765 MPI_VALIDATE_RET( X != NULL );
766 MPI_VALIDATE_RET( fin != NULL );
767
768 if( radix < 2 || radix > 16 )
769 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
770
Paul Bakker5121ce52009-01-03 21:22:43 +0000771 memset( s, 0, sizeof( s ) );
772 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
775 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000776 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000778
Hanno Beckerb2034b72017-04-26 11:46:46 +0100779 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
780 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000781
782 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100783 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000784 if( mpi_get_digit( &d, radix, *p ) != 0 )
785 break;
786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000788}
789
790/*
791 * Write X into an opened file (or stdout if fout == NULL)
792 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200793int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000794{
Janos Follath24eed8d2019-11-22 13:21:35 +0000795 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000796 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000797 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000798 * Buffer should have space for (short) label and decimal formatted MPI,
799 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000800 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200801 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000802 MPI_VALIDATE_RET( X != NULL );
803
804 if( radix < 2 || radix > 16 )
805 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100807 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000808
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100809 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000810
811 if( p == NULL ) p = "";
812
813 plen = strlen( p );
814 slen = strlen( s );
815 s[slen++] = '\r';
816 s[slen++] = '\n';
817
818 if( fout != NULL )
819 {
820 if( fwrite( p, 1, plen, fout ) != plen ||
821 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200822 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000823 }
824 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000826
827cleanup:
828
829 return( ret );
830}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000832
Hanno Beckerda1655a2017-10-18 14:21:44 +0100833
834/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
835 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000836
837static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
838{
839 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100840 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000841 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100842
843 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
844 {
845 tmp <<= CHAR_BIT;
846 tmp |= (mbedtls_mpi_uint) *x_ptr;
847 }
848
Hanno Beckerf8720072018-11-08 11:53:49 +0000849 return( tmp );
850}
851
852static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
853{
854#if defined(__BYTE_ORDER__)
855
856/* Nothing to do on bigendian systems. */
857#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
858 return( x );
859#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
860
861#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
862
863/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000864#if defined(__GNUC__) && defined(__GNUC_PREREQ)
865#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000866#define have_bswap
867#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000868#endif
869
870#if defined(__clang__) && defined(__has_builtin)
871#if __has_builtin(__builtin_bswap32) && \
872 __has_builtin(__builtin_bswap64)
873#define have_bswap
874#endif
875#endif
876
Hanno Beckerf8720072018-11-08 11:53:49 +0000877#if defined(have_bswap)
878 /* The compiler is hopefully able to statically evaluate this! */
879 switch( sizeof(mbedtls_mpi_uint) )
880 {
881 case 4:
882 return( __builtin_bswap32(x) );
883 case 8:
884 return( __builtin_bswap64(x) );
885 }
886#endif
887#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
888#endif /* __BYTE_ORDER__ */
889
890 /* Fall back to C-based reordering if we don't know the byte order
891 * or we couldn't use a compiler-specific builtin. */
892 return( mpi_uint_bigendian_to_host_c( x ) );
893}
894
Hanno Becker2be8a552018-10-25 12:40:09 +0100895static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100896{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100897 mbedtls_mpi_uint *cur_limb_left;
898 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100899 if( limbs == 0 )
900 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100901
902 /*
903 * Traverse limbs and
904 * - adapt byte-order in each limb
905 * - swap the limbs themselves.
906 * For that, simultaneously traverse the limbs from left to right
907 * and from right to left, as long as the left index is not bigger
908 * than the right index (it's not a problem if limbs is odd and the
909 * indices coincide in the last iteration).
910 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100911 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
912 cur_limb_left <= cur_limb_right;
913 cur_limb_left++, cur_limb_right-- )
914 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000915 mbedtls_mpi_uint tmp;
916 /* Note that if cur_limb_left == cur_limb_right,
917 * this code effectively swaps the bytes only once. */
918 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
919 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
920 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100921 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100922}
923
Paul Bakker5121ce52009-01-03 21:22:43 +0000924/*
Janos Follatha778a942019-02-13 10:28:28 +0000925 * Import X from unsigned binary data, little endian
926 */
927int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
928 const unsigned char *buf, size_t buflen )
929{
Janos Follath24eed8d2019-11-22 13:21:35 +0000930 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000931 size_t i;
932 size_t const limbs = CHARS_TO_LIMBS( buflen );
933
934 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200935 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000936
937 for( i = 0; i < buflen; i++ )
938 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
939
940cleanup:
941
Janos Follath171a7ef2019-02-15 16:17:45 +0000942 /*
943 * This function is also used to import keys. However, wiping the buffers
944 * upon failure is not necessary because failure only can happen before any
945 * input is copied.
946 */
Janos Follatha778a942019-02-13 10:28:28 +0000947 return( ret );
948}
949
950/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000951 * Import X from unsigned binary data, big endian
952 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000954{
Janos Follath24eed8d2019-11-22 13:21:35 +0000955 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100956 size_t const limbs = CHARS_TO_LIMBS( buflen );
957 size_t const overhead = ( limbs * ciL ) - buflen;
958 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000959
Hanno Becker8ce11a32018-12-19 16:18:52 +0000960 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000961 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
962
Hanno Becker073c1992017-10-17 15:17:27 +0100963 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200964 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000965
Gilles Peskine3130ce22021-06-02 22:17:52 +0200966 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000967 * even if buflen is 0. */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200968 if( buflen != 0 )
Hanno Becker0e810b92019-01-03 17:13:11 +0000969 {
970 Xp = (unsigned char*) X->p;
971 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100972
Hanno Becker0e810b92019-01-03 17:13:11 +0000973 mpi_bigendian_to_host( X->p, limbs );
974 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000975
976cleanup:
977
Janos Follath171a7ef2019-02-15 16:17:45 +0000978 /*
979 * This function is also used to import keys. However, wiping the buffers
980 * upon failure is not necessary because failure only can happen before any
981 * input is copied.
982 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000983 return( ret );
984}
985
986/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000987 * Export X into unsigned binary data, little endian
988 */
989int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
990 unsigned char *buf, size_t buflen )
991{
992 size_t stored_bytes = X->n * ciL;
993 size_t bytes_to_copy;
994 size_t i;
995
996 if( stored_bytes < buflen )
997 {
998 bytes_to_copy = stored_bytes;
999 }
1000 else
1001 {
1002 bytes_to_copy = buflen;
1003
1004 /* The output buffer is smaller than the allocated size of X.
1005 * However X may fit if its leading bytes are zero. */
1006 for( i = bytes_to_copy; i < stored_bytes; i++ )
1007 {
1008 if( GET_BYTE( X, i ) != 0 )
1009 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1010 }
1011 }
1012
1013 for( i = 0; i < bytes_to_copy; i++ )
1014 buf[i] = GET_BYTE( X, i );
1015
1016 if( stored_bytes < buflen )
1017 {
1018 /* Write trailing 0 bytes */
1019 memset( buf + stored_bytes, 0, buflen - stored_bytes );
1020 }
1021
1022 return( 0 );
1023}
1024
1025/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001026 * Export X into unsigned binary data, big endian
1027 */
Gilles Peskine11cdb052018-11-20 16:47:47 +01001028int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
1029 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001030{
Hanno Becker73d7d792018-12-11 10:35:51 +00001031 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +01001032 size_t bytes_to_copy;
1033 unsigned char *p;
1034 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001035
Hanno Becker73d7d792018-12-11 10:35:51 +00001036 MPI_VALIDATE_RET( X != NULL );
1037 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
1038
1039 stored_bytes = X->n * ciL;
1040
Gilles Peskine11cdb052018-11-20 16:47:47 +01001041 if( stored_bytes < buflen )
1042 {
1043 /* There is enough space in the output buffer. Write initial
1044 * null bytes and record the position at which to start
1045 * writing the significant bytes. In this case, the execution
1046 * trace of this function does not depend on the value of the
1047 * number. */
1048 bytes_to_copy = stored_bytes;
1049 p = buf + buflen - stored_bytes;
1050 memset( buf, 0, buflen - stored_bytes );
1051 }
1052 else
1053 {
1054 /* The output buffer is smaller than the allocated size of X.
1055 * However X may fit if its leading bytes are zero. */
1056 bytes_to_copy = buflen;
1057 p = buf;
1058 for( i = bytes_to_copy; i < stored_bytes; i++ )
1059 {
1060 if( GET_BYTE( X, i ) != 0 )
1061 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1062 }
1063 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001064
Gilles Peskine11cdb052018-11-20 16:47:47 +01001065 for( i = 0; i < bytes_to_copy; i++ )
1066 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001067
1068 return( 0 );
1069}
1070
1071/*
1072 * Left-shift: X <<= count
1073 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001075{
Janos Follath24eed8d2019-11-22 13:21:35 +00001076 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001077 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001079 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001080
1081 v0 = count / (biL );
1082 t1 = count & (biL - 1);
1083
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001084 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001085
Paul Bakkerf9688572011-05-05 10:00:45 +00001086 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001088
1089 ret = 0;
1090
1091 /*
1092 * shift by count / limb_size
1093 */
1094 if( v0 > 0 )
1095 {
Paul Bakker23986e52011-04-24 08:57:21 +00001096 for( i = X->n; i > v0; i-- )
1097 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001098
Paul Bakker23986e52011-04-24 08:57:21 +00001099 for( ; i > 0; i-- )
1100 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 }
1102
1103 /*
1104 * shift by count % limb_size
1105 */
1106 if( t1 > 0 )
1107 {
1108 for( i = v0; i < X->n; i++ )
1109 {
1110 r1 = X->p[i] >> (biL - t1);
1111 X->p[i] <<= t1;
1112 X->p[i] |= r0;
1113 r0 = r1;
1114 }
1115 }
1116
1117cleanup:
1118
1119 return( ret );
1120}
1121
1122/*
1123 * Right-shift: X >>= count
1124 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001126{
Paul Bakker23986e52011-04-24 08:57:21 +00001127 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001128 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001129 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001130
1131 v0 = count / biL;
1132 v1 = count & (biL - 1);
1133
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001134 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001135 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001136
Paul Bakker5121ce52009-01-03 21:22:43 +00001137 /*
1138 * shift by count / limb_size
1139 */
1140 if( v0 > 0 )
1141 {
1142 for( i = 0; i < X->n - v0; i++ )
1143 X->p[i] = X->p[i + v0];
1144
1145 for( ; i < X->n; i++ )
1146 X->p[i] = 0;
1147 }
1148
1149 /*
1150 * shift by count % limb_size
1151 */
1152 if( v1 > 0 )
1153 {
Paul Bakker23986e52011-04-24 08:57:21 +00001154 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001155 {
Paul Bakker23986e52011-04-24 08:57:21 +00001156 r1 = X->p[i - 1] << (biL - v1);
1157 X->p[i - 1] >>= v1;
1158 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001159 r0 = r1;
1160 }
1161 }
1162
1163 return( 0 );
1164}
1165
1166/*
1167 * Compare unsigned values
1168 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001170{
Paul Bakker23986e52011-04-24 08:57:21 +00001171 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001172 MPI_VALIDATE_RET( X != NULL );
1173 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
Paul Bakker23986e52011-04-24 08:57:21 +00001175 for( i = X->n; i > 0; i-- )
1176 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 break;
1178
Paul Bakker23986e52011-04-24 08:57:21 +00001179 for( j = Y->n; j > 0; j-- )
1180 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 break;
1182
Paul Bakker23986e52011-04-24 08:57:21 +00001183 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001184 return( 0 );
1185
1186 if( i > j ) return( 1 );
1187 if( j > i ) return( -1 );
1188
Paul Bakker23986e52011-04-24 08:57:21 +00001189 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 {
Paul Bakker23986e52011-04-24 08:57:21 +00001191 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1192 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 }
1194
1195 return( 0 );
1196}
1197
1198/*
1199 * Compare signed values
1200 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001201int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001202{
Paul Bakker23986e52011-04-24 08:57:21 +00001203 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001204 MPI_VALIDATE_RET( X != NULL );
1205 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001206
Paul Bakker23986e52011-04-24 08:57:21 +00001207 for( i = X->n; i > 0; i-- )
1208 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001209 break;
1210
Paul Bakker23986e52011-04-24 08:57:21 +00001211 for( j = Y->n; j > 0; j-- )
1212 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001213 break;
1214
Paul Bakker23986e52011-04-24 08:57:21 +00001215 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001216 return( 0 );
1217
1218 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001219 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001220
1221 if( X->s > 0 && Y->s < 0 ) return( 1 );
1222 if( Y->s > 0 && X->s < 0 ) return( -1 );
1223
Paul Bakker23986e52011-04-24 08:57:21 +00001224 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001225 {
Paul Bakker23986e52011-04-24 08:57:21 +00001226 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1227 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 }
1229
1230 return( 0 );
1231}
1232
Janos Follath3f6f0e42019-10-14 09:09:32 +01001233/** Decide if an integer is less than the other, without branches.
1234 *
1235 * \param x First integer.
1236 * \param y Second integer.
1237 *
1238 * \return 1 if \p x is less than \p y, 0 otherwise
1239 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001240static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1241 const mbedtls_mpi_uint y )
Janos Follathee6abce2019-09-05 14:47:19 +01001242{
1243 mbedtls_mpi_uint ret;
1244 mbedtls_mpi_uint cond;
1245
1246 /*
1247 * Check if the most significant bits (MSB) of the operands are different.
1248 */
1249 cond = ( x ^ y );
1250 /*
1251 * If the MSB are the same then the difference x-y will be negative (and
1252 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1253 */
1254 ret = ( x - y ) & ~cond;
1255 /*
1256 * If the MSB are different, then the operand with the MSB of 1 is the
1257 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1258 * the MSB of y is 0.)
1259 */
1260 ret |= y & cond;
1261
1262
Janos Follatha0f732b2019-10-14 08:59:14 +01001263 ret = ret >> ( biL - 1 );
Janos Follathee6abce2019-09-05 14:47:19 +01001264
Janos Follath67ce6472019-10-29 15:08:46 +00001265 return (unsigned) ret;
Janos Follathee6abce2019-09-05 14:47:19 +01001266}
1267
1268/*
1269 * Compare signed values in constant time
1270 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001271int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1272 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001273{
1274 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001275 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001276 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001277
1278 MPI_VALIDATE_RET( X != NULL );
1279 MPI_VALIDATE_RET( Y != NULL );
1280 MPI_VALIDATE_RET( ret != NULL );
1281
1282 if( X->n != Y->n )
1283 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1284
1285 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001286 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1287 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001288 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001289 X_is_negative = ( X->s & 2 ) >> 1;
1290 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001291
1292 /*
1293 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001294 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1295 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001296 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001297 cond = ( X_is_negative ^ Y_is_negative );
1298 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001299
1300 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001301 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001302 * need to go through the loop. Record if we have the result already.
1303 */
Janos Follathee6abce2019-09-05 14:47:19 +01001304 done = cond;
1305
1306 for( i = X->n; i > 0; i-- )
1307 {
1308 /*
Janos Follath30702422019-11-05 12:24:52 +00001309 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1310 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001311 *
1312 * Again even if we can make a decision, we just mark the result and
1313 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001314 */
Janos Follath30702422019-11-05 12:24:52 +00001315 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1316 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001317 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001318
1319 /*
Janos Follath30702422019-11-05 12:24:52 +00001320 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1321 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001322 *
1323 * Again even if we can make a decision, we just mark the result and
1324 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001325 */
Janos Follath30702422019-11-05 12:24:52 +00001326 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1327 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001328 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001329 }
1330
1331 return( 0 );
1332}
1333
Paul Bakker5121ce52009-01-03 21:22:43 +00001334/*
1335 * Compare signed values
1336 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001338{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339 mbedtls_mpi Y;
1340 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001341 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001342
1343 *p = ( z < 0 ) ? -z : z;
1344 Y.s = ( z < 0 ) ? -1 : 1;
1345 Y.n = 1;
1346 Y.p = p;
1347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001348 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001349}
1350
1351/*
1352 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001355{
Janos Follath24eed8d2019-11-22 13:21:35 +00001356 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001357 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001358 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001359 MPI_VALIDATE_RET( X != NULL );
1360 MPI_VALIDATE_RET( A != NULL );
1361 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
1363 if( X == B )
1364 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001366 }
1367
1368 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001370
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001371 /*
1372 * X should always be positive as a result of unsigned additions.
1373 */
1374 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001375
Paul Bakker23986e52011-04-24 08:57:21 +00001376 for( j = B->n; j > 0; j-- )
1377 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 break;
1379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001381
1382 o = B->p; p = X->p; c = 0;
1383
Janos Follath6c922682015-10-30 17:43:11 +01001384 /*
1385 * tmp is used because it might happen that p == o
1386 */
Paul Bakker23986e52011-04-24 08:57:21 +00001387 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 {
Janos Follath6c922682015-10-30 17:43:11 +01001389 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001390 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001391 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001392 }
1393
1394 while( c != 0 )
1395 {
1396 if( i >= X->n )
1397 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 p = X->p + i;
1400 }
1401
Paul Bakker2d319fd2012-09-16 21:34:26 +00001402 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001403 }
1404
1405cleanup:
1406
1407 return( ret );
1408}
1409
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001410/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001411 * Helper for mbedtls_mpi subtraction.
1412 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001413 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001414 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001415 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001416 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001417 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001418 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001419 * \param n Number of limbs of \p d, \p l and \p r.
1420 * \param[out] d The result of the subtraction.
1421 * \param[in] l The left operand.
1422 * \param[in] r The right operand.
1423 *
1424 * \return 1 if `l < r`.
1425 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001427static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1428 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001429 const mbedtls_mpi_uint *l,
1430 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001431{
Paul Bakker23986e52011-04-24 08:57:21 +00001432 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001433 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001435 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001437 z = ( l[i] < c ); t = l[i] - c;
1438 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 }
1440
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001441 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001442}
1443
1444/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001445 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001446 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001447int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001448{
Janos Follath24eed8d2019-11-22 13:21:35 +00001449 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001450 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001451 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001452 MPI_VALIDATE_RET( X != NULL );
1453 MPI_VALIDATE_RET( A != NULL );
1454 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001455
Paul Bakker23986e52011-04-24 08:57:21 +00001456 for( n = B->n; n > 0; n-- )
1457 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001458 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001459 if( n > A->n )
1460 {
1461 /* B >= (2^ciL)^n > A */
1462 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1463 goto cleanup;
1464 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001465
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1467
1468 /* Set the high limbs of X to match A. Don't touch the lower limbs
1469 * because X might be aliased to B, and we must not overwrite the
1470 * significant digits of B. */
1471 if( A->n > n )
1472 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1473 if( X->n > A->n )
1474 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1475
1476 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001477 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001478 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001479 /* Propagate the carry to the first nonzero limb of X. */
1480 for( ; n < X->n && X->p[n] == 0; n++ )
1481 --X->p[n];
1482 /* If we ran out of space for the carry, it means that the result
1483 * is negative. */
1484 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001485 {
1486 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1487 goto cleanup;
1488 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001489 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001490 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001491
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001492 /* X should always be positive as a result of unsigned subtractions. */
1493 X->s = 1;
1494
Paul Bakker5121ce52009-01-03 21:22:43 +00001495cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001496 return( ret );
1497}
1498
1499/*
1500 * Signed addition: X = A + B
1501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001503{
Hanno Becker73d7d792018-12-11 10:35:51 +00001504 int ret, s;
1505 MPI_VALIDATE_RET( X != NULL );
1506 MPI_VALIDATE_RET( A != NULL );
1507 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
Hanno Becker73d7d792018-12-11 10:35:51 +00001509 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 if( A->s * B->s < 0 )
1511 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001513 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001515 X->s = s;
1516 }
1517 else
1518 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 X->s = -s;
1521 }
1522 }
1523 else
1524 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001525 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001526 X->s = s;
1527 }
1528
1529cleanup:
1530
1531 return( ret );
1532}
1533
1534/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001535 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001536 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001538{
Hanno Becker73d7d792018-12-11 10:35:51 +00001539 int ret, s;
1540 MPI_VALIDATE_RET( X != NULL );
1541 MPI_VALIDATE_RET( A != NULL );
1542 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001543
Hanno Becker73d7d792018-12-11 10:35:51 +00001544 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001545 if( A->s * B->s > 0 )
1546 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001548 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 X->s = s;
1551 }
1552 else
1553 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555 X->s = -s;
1556 }
1557 }
1558 else
1559 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001561 X->s = s;
1562 }
1563
1564cleanup:
1565
1566 return( ret );
1567}
1568
1569/*
1570 * Signed addition: X = A + b
1571 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001573{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 mbedtls_mpi _B;
1575 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001576 MPI_VALIDATE_RET( X != NULL );
1577 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001578
1579 p[0] = ( b < 0 ) ? -b : b;
1580 _B.s = ( b < 0 ) ? -1 : 1;
1581 _B.n = 1;
1582 _B.p = p;
1583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585}
1586
1587/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001588 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001591{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 mbedtls_mpi _B;
1593 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001594 MPI_VALIDATE_RET( X != NULL );
1595 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001596
1597 p[0] = ( b < 0 ) ? -b : b;
1598 _B.s = ( b < 0 ) ? -1 : 1;
1599 _B.n = 1;
1600 _B.p = p;
1601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603}
1604
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001605/** Helper for mbedtls_mpi multiplication.
1606 *
1607 * Add \p b * \p s to \p d.
1608 *
1609 * \param i The number of limbs of \p s.
1610 * \param[in] s A bignum to multiply, of size \p i.
1611 * It may overlap with \p d, but only if
1612 * \p d <= \p s.
1613 * Its leading limb must not be \c 0.
1614 * \param[in,out] d The bignum to add to.
1615 * It must be sufficiently large to store the
1616 * result of the multiplication. This means
1617 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1618 * is not known a priori.
1619 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001620 */
1621static
1622#if defined(__APPLE__) && defined(__arm__)
1623/*
1624 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1625 * appears to need this to prevent bad ARM code generation at -O3.
1626 */
1627__attribute__ ((noinline))
1628#endif
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001629void mpi_mul_hlp( size_t i,
1630 const mbedtls_mpi_uint *s,
1631 mbedtls_mpi_uint *d,
1632 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001633{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001635
1636#if defined(MULADDC_HUIT)
1637 for( ; i >= 8; i -= 8 )
1638 {
1639 MULADDC_INIT
1640 MULADDC_HUIT
1641 MULADDC_STOP
1642 }
1643
1644 for( ; i > 0; i-- )
1645 {
1646 MULADDC_INIT
1647 MULADDC_CORE
1648 MULADDC_STOP
1649 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001650#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001651 for( ; i >= 16; i -= 16 )
1652 {
1653 MULADDC_INIT
1654 MULADDC_CORE MULADDC_CORE
1655 MULADDC_CORE MULADDC_CORE
1656 MULADDC_CORE MULADDC_CORE
1657 MULADDC_CORE MULADDC_CORE
1658
1659 MULADDC_CORE MULADDC_CORE
1660 MULADDC_CORE MULADDC_CORE
1661 MULADDC_CORE MULADDC_CORE
1662 MULADDC_CORE MULADDC_CORE
1663 MULADDC_STOP
1664 }
1665
1666 for( ; i >= 8; i -= 8 )
1667 {
1668 MULADDC_INIT
1669 MULADDC_CORE MULADDC_CORE
1670 MULADDC_CORE MULADDC_CORE
1671
1672 MULADDC_CORE MULADDC_CORE
1673 MULADDC_CORE MULADDC_CORE
1674 MULADDC_STOP
1675 }
1676
1677 for( ; i > 0; i-- )
1678 {
1679 MULADDC_INIT
1680 MULADDC_CORE
1681 MULADDC_STOP
1682 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001683#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001684
1685 t++;
1686
Gilles Peskine8e464c42020-07-24 00:08:38 +02001687 while( c != 0 )
1688 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 *d += c; c = ( *d < c ); d++;
1690 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001691}
1692
1693/*
1694 * Baseline multiplication: X = A * B (HAC 14.12)
1695 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001697{
Janos Follath24eed8d2019-11-22 13:21:35 +00001698 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001699 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001701 MPI_VALIDATE_RET( X != NULL );
1702 MPI_VALIDATE_RET( A != NULL );
1703 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001707 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1708 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001709
Paul Bakker23986e52011-04-24 08:57:21 +00001710 for( i = A->n; i > 0; i-- )
1711 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 break;
1713
Paul Bakker23986e52011-04-24 08:57:21 +00001714 for( j = B->n; j > 0; j-- )
1715 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001716 break;
1717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1719 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001720
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001721 for( ; j > 0; j-- )
1722 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
1724 X->s = A->s * B->s;
1725
1726cleanup:
1727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
1730 return( ret );
1731}
1732
1733/*
1734 * Baseline multiplication: X = A * b
1735 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001737{
Hanno Becker73d7d792018-12-11 10:35:51 +00001738 MPI_VALIDATE_RET( X != NULL );
1739 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001740
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001741 /* mpi_mul_hlp can't deal with a leading 0. */
1742 size_t n = A->n;
1743 while( n > 0 && A->p[n - 1] == 0 )
1744 --n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001745
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001746 /* The general method below doesn't work if n==0 or b==0. By chance
1747 * calculating the result is trivial in those cases. */
1748 if( b == 0 || n == 0 )
1749 {
Paul Elliott986b55a2021-04-20 21:46:29 +01001750 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001751 }
1752
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001753 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001754 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001755 /* In general, A * b requires 1 limb more than b. If
1756 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1757 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001758 * copy() will take care of the growth if needed. However, experimentally,
1759 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001760 * calls to calloc() in ECP code, presumably because it reuses the
1761 * same mpi for a while and this way the mpi is more likely to directly
1762 * grow to its final size. */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001763 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
1764 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1765 mpi_mul_hlp( n, A->p, X->p, b - 1 );
1766
1767cleanup:
1768 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001769}
1770
1771/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001772 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1773 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001774 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001775static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1776 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001777{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001778#if defined(MBEDTLS_HAVE_UDBL)
1779 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001780#else
Simon Butcher9803d072016-01-03 00:24:34 +00001781 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1782 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001783 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1784 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001785 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001786#endif
1787
Simon Butcher15b15d12015-11-26 19:35:03 +00001788 /*
1789 * Check for overflow
1790 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001791 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001792 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001793 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001794
Simon Butcherf5ba0452015-12-27 23:01:55 +00001795 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001796 }
1797
1798#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001799 dividend = (mbedtls_t_udbl) u1 << biL;
1800 dividend |= (mbedtls_t_udbl) u0;
1801 quotient = dividend / d;
1802 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1803 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1804
1805 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001806 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001807
1808 return (mbedtls_mpi_uint) quotient;
1809#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001810
1811 /*
1812 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1813 * Vol. 2 - Seminumerical Algorithms, Knuth
1814 */
1815
1816 /*
1817 * Normalize the divisor, d, and dividend, u0, u1
1818 */
1819 s = mbedtls_clz( d );
1820 d = d << s;
1821
1822 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001823 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001824 u0 = u0 << s;
1825
1826 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001827 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001828
1829 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001830 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001831
1832 /*
1833 * Find the first quotient and remainder
1834 */
1835 q1 = u1 / d1;
1836 r0 = u1 - d1 * q1;
1837
1838 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1839 {
1840 q1 -= 1;
1841 r0 += d1;
1842
1843 if ( r0 >= radix ) break;
1844 }
1845
Simon Butcherf5ba0452015-12-27 23:01:55 +00001846 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001847 q0 = rAX / d1;
1848 r0 = rAX - q0 * d1;
1849
1850 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1851 {
1852 q0 -= 1;
1853 r0 += d1;
1854
1855 if ( r0 >= radix ) break;
1856 }
1857
1858 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001859 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001860
1861 quotient = q1 * radix + q0;
1862
1863 return quotient;
1864#endif
1865}
1866
1867/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001870int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1871 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001872{
Janos Follath24eed8d2019-11-22 13:21:35 +00001873 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001874 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001876 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001877 MPI_VALIDATE_RET( A != NULL );
1878 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1881 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001884 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001885 /*
1886 * Avoid dynamic memory allocations for constant-size T2.
1887 *
1888 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1889 * so nobody increase the size of the MPI and we're safe to use an on-stack
1890 * buffer.
1891 */
Alexander K35d6d462019-10-31 14:46:45 +03001892 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001893 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1894 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1899 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900 return( 0 );
1901 }
1902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1904 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001905 X.s = Y.s = 1;
1906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1908 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001909 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001911 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001912 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 {
1914 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1916 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 }
1918 else k = 0;
1919
1920 n = X.n - 1;
1921 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001925 {
1926 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
1931 for( i = n; i > t ; i-- )
1932 {
1933 if( X.p[i] >= Y.p[t] )
1934 Z.p[i - t - 1] = ~0;
1935 else
1936 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001937 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1938 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001939 }
1940
Alexander K35d6d462019-10-31 14:46:45 +03001941 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1942 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1943 T2.p[2] = X.p[i];
1944
Paul Bakker5121ce52009-01-03 21:22:43 +00001945 Z.p[i - t - 1]++;
1946 do
1947 {
1948 Z.p[i - t - 1]--;
1949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001951 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001952 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001953 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001954 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1958 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1959 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1964 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1965 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966 Z.p[i - t - 1]--;
1967 }
1968 }
1969
1970 if( Q != NULL )
1971 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973 Q->s = A->s * B->s;
1974 }
1975
1976 if( R != NULL )
1977 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001979 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001981
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001983 R->s = 1;
1984 }
1985
1986cleanup:
1987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001989 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001990 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
1992 return( ret );
1993}
1994
1995/*
1996 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001997 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001998int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1999 const mbedtls_mpi *A,
2000 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00002001{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002002 mbedtls_mpi _B;
2003 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00002004 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002005
2006 p[0] = ( b < 0 ) ? -b : b;
2007 _B.s = ( b < 0 ) ? -1 : 1;
2008 _B.n = 1;
2009 _B.p = p;
2010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002012}
2013
2014/*
2015 * Modulo: R = A mod B
2016 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002018{
Janos Follath24eed8d2019-11-22 13:21:35 +00002019 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00002020 MPI_VALIDATE_RET( R != NULL );
2021 MPI_VALIDATE_RET( A != NULL );
2022 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
2025 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
2030 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
2033 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
2035cleanup:
2036
2037 return( ret );
2038}
2039
2040/*
2041 * Modulo: r = A mod b
2042 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00002044{
Paul Bakker23986e52011-04-24 08:57:21 +00002045 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00002047 MPI_VALIDATE_RET( r != NULL );
2048 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
2050 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
2053 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002055
2056 /*
2057 * handle trivial cases
2058 */
2059 if( b == 1 )
2060 {
2061 *r = 0;
2062 return( 0 );
2063 }
2064
2065 if( b == 2 )
2066 {
2067 *r = A->p[0] & 1;
2068 return( 0 );
2069 }
2070
2071 /*
2072 * general case
2073 */
Paul Bakker23986e52011-04-24 08:57:21 +00002074 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00002075 {
Paul Bakker23986e52011-04-24 08:57:21 +00002076 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00002077 y = ( y << biH ) | ( x >> biH );
2078 z = y / b;
2079 y -= z * b;
2080
2081 x <<= biH;
2082 y = ( y << biH ) | ( x >> biH );
2083 z = y / b;
2084 y -= z * b;
2085 }
2086
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002087 /*
2088 * If A is negative, then the current y represents a negative value.
2089 * Flipping it to the positive side.
2090 */
2091 if( A->s < 0 && y != 0 )
2092 y = b - y;
2093
Paul Bakker5121ce52009-01-03 21:22:43 +00002094 *r = y;
2095
2096 return( 0 );
2097}
2098
2099/*
2100 * Fast Montgomery initialization (thanks to Tom St Denis)
2101 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002103{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002104 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002105 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
2107 x = m0;
2108 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002110 for( i = biL; i >= 8; i /= 2 )
2111 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
2113 *mm = ~x + 1;
2114}
2115
Gilles Peskine2a82f722020-06-04 15:00:49 +02002116/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2117 *
2118 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002119 * It must have at least as many limbs as N
2120 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002121 * On successful completion, A contains the result of
2122 * the multiplication A * B * R^-1 mod N where
2123 * R = (2^ciL)^n.
2124 * \param[in] B One of the numbers to multiply.
2125 * It must be nonzero and must not have more limbs than N
2126 * (B->n <= N->n).
2127 * \param[in] N The modulo. N must be odd.
2128 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2129 * This is -N^-1 mod 2^ciL.
2130 * \param[in,out] T A bignum for temporary storage.
2131 * It must be at least twice the limb size of N plus 2
2132 * (T->n >= 2 * (N->n + 1)).
2133 * Its initial content is unused and
2134 * its final content is indeterminate.
2135 * Note that unlike the usual convention in the library
2136 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002137 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002138static 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 +02002139 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002140{
Paul Bakker23986e52011-04-24 08:57:21 +00002141 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
2144 memset( T->p, 0, T->n * ciL );
2145
2146 d = T->p;
2147 n = N->n;
2148 m = ( B->n < n ) ? B->n : n;
2149
2150 for( i = 0; i < n; i++ )
2151 {
2152 /*
2153 * T = (T + u0*B + u1*N) / 2^biL
2154 */
2155 u0 = A->p[i];
2156 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2157
2158 mpi_mul_hlp( m, B->p, d, u0 );
2159 mpi_mul_hlp( n, N->p, d, u1 );
2160
2161 *d++ = u0; d[n + 1] = 0;
2162 }
2163
Gilles Peskine221626f2020-06-08 22:37:50 +02002164 /* At this point, d is either the desired result or the desired result
2165 * plus N. We now potentially subtract N, avoiding leaking whether the
2166 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002167
Gilles Peskine221626f2020-06-08 22:37:50 +02002168 /* Copy the n least significant limbs of d to A, so that
2169 * A = d if d < N (recall that N has n limbs). */
2170 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002171 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002172 * do the calculation without using conditional tests. */
2173 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002174 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02002175 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02002176 /* If d0 < N then d < (2^biL)^n
2177 * so d[n] == 0 and we want to keep A as it is.
2178 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2179 * so d[n] == 1 and we want to set A to the result of the subtraction
2180 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2181 * This exactly corresponds to a conditional assignment. */
2182 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183}
2184
2185/*
2186 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002187 *
2188 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002189 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002190static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2191 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002192{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 mbedtls_mpi_uint z = 1;
2194 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002195
Paul Bakker8ddb6452013-02-27 14:56:33 +01002196 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002197 U.p = &z;
2198
Gilles Peskine4e91d472020-06-04 20:55:15 +02002199 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200}
2201
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002202/*
2203 * Constant-flow boolean "equal" comparison:
2204 * return x == y
2205 *
2206 * This function can be used to write constant-time code by replacing branches
2207 * with bit operations - it can be used in conjunction with
2208 * mbedtls_ssl_cf_mask_from_bit().
2209 *
2210 * This function is implemented without using comparison operators, as those
2211 * might be translated to branches by some compilers on some platforms.
2212 */
2213static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2214{
2215 /* diff = 0 if x == y, non-zero otherwise */
2216 const size_t diff = x ^ y;
2217
2218 /* MSVC has a warning about unary minus on unsigned integer types,
2219 * but this is well-defined and precisely what we want to do here. */
2220#if defined(_MSC_VER)
2221#pragma warning( push )
2222#pragma warning( disable : 4146 )
2223#endif
2224
2225 /* diff_msb's most significant bit is equal to x != y */
Manuel Pégourié-Gonnardc94b6b02021-06-17 13:25:03 +02002226 const size_t diff_msb = ( diff | (size_t) -diff );
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002227
2228#if defined(_MSC_VER)
2229#pragma warning( pop )
2230#endif
2231
2232 /* diff1 = (x != y) ? 1 : 0 */
2233 const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2234
2235 return( 1 ^ diff1 );
2236}
2237
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002238/**
2239 * Select an MPI from a table without leaking the index.
2240 *
2241 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2242 * reads the entire table in order to avoid leaking the value of idx to an
2243 * attacker able to observe memory access patterns.
2244 *
2245 * \param[out] R Where to write the selected MPI.
2246 * \param[in] T The table to read from.
2247 * \param[in] T_size The number of elements in the table.
2248 * \param[in] idx The index of the element to select;
2249 * this must satisfy 0 <= idx < T_size.
2250 *
2251 * \return \c 0 on success, or a negative error code.
2252 */
2253static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2254{
2255 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2256
2257 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002258 {
2259 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
Manuel Pégourié-Gonnard0b3bde52021-06-10 09:34:00 +02002260 (unsigned char) mbedtls_mpi_cf_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002261 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002262
2263cleanup:
2264 return( ret );
2265}
2266
Paul Bakker5121ce52009-01-03 21:22:43 +00002267/*
2268 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2269 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002270int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2271 const mbedtls_mpi *E, const mbedtls_mpi *N,
2272 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002273{
Janos Follath24eed8d2019-11-22 13:21:35 +00002274 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002275 size_t wbits, wsize, one = 1;
2276 size_t i, j, nblimbs;
2277 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002279 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002280 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
Hanno Becker73d7d792018-12-11 10:35:51 +00002282 MPI_VALIDATE_RET( X != NULL );
2283 MPI_VALIDATE_RET( A != NULL );
2284 MPI_VALIDATE_RET( E != NULL );
2285 MPI_VALIDATE_RET( N != NULL );
2286
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002287 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2291 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002292
Chris Jones9246d042020-11-25 15:12:39 +00002293 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2294 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2295 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2296
Paul Bakkerf6198c12012-05-16 08:02:29 +00002297 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002298 * Init temps and window size
2299 */
2300 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2302 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002303 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 memset( W, 0, sizeof( W ) );
2305
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002306 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002307
2308 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2309 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2310
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002311#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2313 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002314#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002315
Paul Bakker5121ce52009-01-03 21:22:43 +00002316 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2318 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2319 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
2321 /*
Paul Bakker50546922012-05-19 08:40:49 +00002322 * Compensate for negative A (and correct at the end)
2323 */
2324 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002325 if( neg )
2326 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002328 Apos.s = 1;
2329 A = &Apos;
2330 }
2331
2332 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 * If 1st call, pre-compute R^2 mod N
2334 */
2335 if( _RR == NULL || _RR->p == NULL )
2336 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2338 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2339 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
2341 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343 }
2344 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
2347 /*
2348 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2349 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2351 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002352 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
Gilles Peskine4e91d472020-06-04 20:55:15 +02002355 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
2357 /*
2358 * X = R^2 * R^-1 mod N = R mod N
2359 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002361 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002362
2363 if( wsize > 1 )
2364 {
2365 /*
2366 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2367 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002368 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2371 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
2373 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002374 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002375
Paul Bakker5121ce52009-01-03 21:22:43 +00002376 /*
2377 * W[i] = W[i - 1] * W[1]
2378 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002379 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002380 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2382 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002383
Gilles Peskine4e91d472020-06-04 20:55:15 +02002384 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385 }
2386 }
2387
2388 nblimbs = E->n;
2389 bufsize = 0;
2390 nbits = 0;
2391 wbits = 0;
2392 state = 0;
2393
2394 while( 1 )
2395 {
2396 if( bufsize == 0 )
2397 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002398 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002399 break;
2400
Paul Bakker0d7702c2013-10-29 16:18:35 +01002401 nblimbs--;
2402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002404 }
2405
2406 bufsize--;
2407
2408 ei = (E->p[nblimbs] >> bufsize) & 1;
2409
2410 /*
2411 * skip leading 0s
2412 */
2413 if( ei == 0 && state == 0 )
2414 continue;
2415
2416 if( ei == 0 && state == 1 )
2417 {
2418 /*
2419 * out of window, square X
2420 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002421 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422 continue;
2423 }
2424
2425 /*
2426 * add ei to current window
2427 */
2428 state = 2;
2429
2430 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002431 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
2433 if( nbits == wsize )
2434 {
2435 /*
2436 * X = X^wsize R^-1 mod N
2437 */
2438 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002439 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002440
2441 /*
2442 * X = X * W[wbits] R^-1 mod N
2443 */
Manuel Pégourié-Gonnard0b3bde52021-06-10 09:34:00 +02002444 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002445 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002446
2447 state--;
2448 nbits = 0;
2449 wbits = 0;
2450 }
2451 }
2452
2453 /*
2454 * process the remaining bits
2455 */
2456 for( i = 0; i < nbits; i++ )
2457 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002458 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002459
2460 wbits <<= 1;
2461
Paul Bakker66d5d072014-06-17 16:39:18 +02002462 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002463 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002464 }
2465
2466 /*
2467 * X = A^E * R * R^-1 mod N = A^E mod N
2468 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002469 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002470
Hanno Beckera4af1c42017-04-18 09:07:45 +01002471 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002472 {
2473 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002474 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002475 }
2476
Paul Bakker5121ce52009-01-03 21:22:43 +00002477cleanup:
2478
Paul Bakker66d5d072014-06-17 16:39:18 +02002479 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002482 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002483 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002484
Paul Bakker75a28602014-03-31 12:08:17 +02002485 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002487
2488 return( ret );
2489}
2490
Paul Bakker5121ce52009-01-03 21:22:43 +00002491/*
2492 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2493 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002495{
Janos Follath24eed8d2019-11-22 13:21:35 +00002496 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002497 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002498 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002499
Hanno Becker73d7d792018-12-11 10:35:51 +00002500 MPI_VALIDATE_RET( G != NULL );
2501 MPI_VALIDATE_RET( A != NULL );
2502 MPI_VALIDATE_RET( B != NULL );
2503
Alexander Ke8ad49f2019-08-16 16:16:07 +03002504 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2507 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002509 lz = mbedtls_mpi_lsb( &TA );
2510 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002511
Paul Bakker66d5d072014-06-17 16:39:18 +02002512 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002513 lz = lzt;
2514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002515 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2516 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002517
Paul Bakker5121ce52009-01-03 21:22:43 +00002518 TA.s = TB.s = 1;
2519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002520 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002521 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002522 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2523 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002526 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2528 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002529 }
2530 else
2531 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2533 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002534 }
2535 }
2536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2538 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002539
2540cleanup:
2541
Alexander Ke8ad49f2019-08-16 16:16:07 +03002542 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002543
2544 return( ret );
2545}
2546
Gilles Peskine8f454702021-04-01 15:57:18 +02002547/* Fill X with n_bytes random bytes.
2548 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002549 * The ordering of the bytes returned from the RNG is suitable for
2550 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002551 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002552 * n_bytes must not be 0.
2553 */
2554static int mpi_fill_random_internal(
2555 mbedtls_mpi *X, size_t n_bytes,
2556 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2557{
2558 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2559 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2560 const size_t overhead = ( limbs * ciL ) - n_bytes;
2561
2562 if( X->n < limbs )
2563 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine8f454702021-04-01 15:57:18 +02002564
Gilles Peskinea16001e2021-04-13 21:55:35 +02002565 memset( X->p, 0, overhead );
2566 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine8f454702021-04-01 15:57:18 +02002567 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2568 mpi_bigendian_to_host( X->p, limbs );
2569
2570cleanup:
2571 return( ret );
2572}
2573
Paul Bakker33dc46b2014-04-30 16:11:39 +02002574/*
2575 * Fill X with size bytes of random.
2576 *
2577 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002578 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002579 * deterministic, eg for tests).
2580 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002582 int (*f_rng)(void *, unsigned char *, size_t),
2583 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002584{
Janos Follath24eed8d2019-11-22 13:21:35 +00002585 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002586 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002587
Hanno Becker8ce11a32018-12-19 16:18:52 +00002588 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002589 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002590
Hanno Beckerda1655a2017-10-18 14:21:44 +01002591 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002592 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002593 if( size == 0 )
2594 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002595
Gilles Peskine8f454702021-04-01 15:57:18 +02002596 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002597
2598cleanup:
2599 return( ret );
2600}
2601
Gilles Peskine4699fa42021-03-29 22:02:55 +02002602int mbedtls_mpi_random( mbedtls_mpi *X,
2603 mbedtls_mpi_sint min,
2604 const mbedtls_mpi *N,
2605 int (*f_rng)(void *, unsigned char *, size_t),
2606 void *p_rng )
2607{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002608 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002609 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002610 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002611 size_t n_bits = mbedtls_mpi_bitlen( N );
2612 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002613 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002614
Gilles Peskine9312ba52021-03-29 22:14:51 +02002615 if( min < 0 )
2616 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2617 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2618 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2619
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002620 /*
2621 * When min == 0, each try has at worst a probability 1/2 of failing
2622 * (the msb has a probability 1/2 of being 0, and then the result will
2623 * be < N), so after 30 tries failure probability is a most 2**(-30).
2624 *
2625 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002626 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002627 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002628 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002629 * a probability of failing that is almost 1/2.
2630 *
2631 * The probabilities are almost the same if min is nonzero but negligible
2632 * compared to N. This is always the case when N is crypto-sized, but
2633 * it's convenient to support small N for testing purposes. When N
2634 * is small, use a higher repeat count, otherwise the probability of
2635 * failure is macroscopic.
2636 */
Gilles Peskine11779072021-06-02 21:18:59 +02002637 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002638
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002639 mbedtls_mpi_init( &lower_bound );
2640
Gilles Peskine8f454702021-04-01 15:57:18 +02002641 /* Ensure that target MPI has exactly the same number of limbs
2642 * as the upper bound, even if the upper bound has leading zeros.
2643 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002644 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002645 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2646 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002647
Gilles Peskine4699fa42021-03-29 22:02:55 +02002648 /*
2649 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2650 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2651 * - use the same byte ordering;
2652 * - keep the leftmost n_bits bits of the generated octet string;
2653 * - try until result is in the desired range.
2654 * This also avoids any bias, which is especially important for ECDSA.
2655 */
2656 do
2657 {
Gilles Peskine8f454702021-04-01 15:57:18 +02002658 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002659 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2660
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002661 if( --count == 0 )
Gilles Peskine4699fa42021-03-29 22:02:55 +02002662 {
2663 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2664 goto cleanup;
2665 }
2666
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002667 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2668 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002669 }
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002670 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002671
2672cleanup:
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002673 mbedtls_mpi_free( &lower_bound );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002674 return( ret );
2675}
2676
Paul Bakker5121ce52009-01-03 21:22:43 +00002677/*
2678 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2679 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002680int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002681{
Janos Follath24eed8d2019-11-22 13:21:35 +00002682 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002683 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002684 MPI_VALIDATE_RET( X != NULL );
2685 MPI_VALIDATE_RET( A != NULL );
2686 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002687
Hanno Becker4bcb4912017-04-18 15:49:39 +01002688 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2692 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2693 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002694
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002698 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002699 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002700 goto cleanup;
2701 }
2702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002703 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2704 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2705 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2706 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2709 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2710 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2711 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002712
2713 do
2714 {
2715 while( ( TU.p[0] & 1 ) == 0 )
2716 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002717 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002718
2719 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2720 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002721 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2722 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002723 }
2724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2726 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002727 }
2728
2729 while( ( TV.p[0] & 1 ) == 0 )
2730 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002732
2733 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2734 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002735 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2736 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002737 }
2738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002739 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2740 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002741 }
2742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002743 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002744 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002745 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2746 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2747 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002748 }
2749 else
2750 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002751 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2752 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2753 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002754 }
2755 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002757
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002758 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2759 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002761 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2762 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002763
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002764 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002765
2766cleanup:
2767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2769 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2770 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002771
2772 return( ret );
2773}
2774
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002775#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002776
Paul Bakker5121ce52009-01-03 21:22:43 +00002777static const int small_prime[] =
2778{
2779 3, 5, 7, 11, 13, 17, 19, 23,
2780 29, 31, 37, 41, 43, 47, 53, 59,
2781 61, 67, 71, 73, 79, 83, 89, 97,
2782 101, 103, 107, 109, 113, 127, 131, 137,
2783 139, 149, 151, 157, 163, 167, 173, 179,
2784 181, 191, 193, 197, 199, 211, 223, 227,
2785 229, 233, 239, 241, 251, 257, 263, 269,
2786 271, 277, 281, 283, 293, 307, 311, 313,
2787 317, 331, 337, 347, 349, 353, 359, 367,
2788 373, 379, 383, 389, 397, 401, 409, 419,
2789 421, 431, 433, 439, 443, 449, 457, 461,
2790 463, 467, 479, 487, 491, 499, 503, 509,
2791 521, 523, 541, 547, 557, 563, 569, 571,
2792 577, 587, 593, 599, 601, 607, 613, 617,
2793 619, 631, 641, 643, 647, 653, 659, 661,
2794 673, 677, 683, 691, 701, 709, 719, 727,
2795 733, 739, 743, 751, 757, 761, 769, 773,
2796 787, 797, 809, 811, 821, 823, 827, 829,
2797 839, 853, 857, 859, 863, 877, 881, 883,
2798 887, 907, 911, 919, 929, 937, 941, 947,
2799 953, 967, 971, 977, 983, 991, 997, -103
2800};
2801
2802/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002803 * Small divisors test (X must be positive)
2804 *
2805 * Return values:
2806 * 0: no small factor (possible prime, more tests needed)
2807 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002808 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002809 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002810 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002812{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002813 int ret = 0;
2814 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002815 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002816
Paul Bakker5121ce52009-01-03 21:22:43 +00002817 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002818 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002819
2820 for( i = 0; small_prime[i] > 0; i++ )
2821 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002822 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002823 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002826
2827 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002828 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002829 }
2830
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002831cleanup:
2832 return( ret );
2833}
2834
2835/*
2836 * Miller-Rabin pseudo-primality test (HAC 4.24)
2837 */
Janos Follathda31fa12018-09-03 14:45:23 +01002838static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002839 int (*f_rng)(void *, unsigned char *, size_t),
2840 void *p_rng )
2841{
Pascal Junodb99183d2015-03-11 16:49:45 +01002842 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002843 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002844 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002845
Hanno Becker8ce11a32018-12-19 16:18:52 +00002846 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002847 MPI_VALIDATE_RET( f_rng != NULL );
2848
2849 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2850 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002851 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002852
Paul Bakker5121ce52009-01-03 21:22:43 +00002853 /*
2854 * W = |X| - 1
2855 * R = W >> lsb( W )
2856 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002857 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2858 s = mbedtls_mpi_lsb( &W );
2859 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2860 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002861
Janos Follathda31fa12018-09-03 14:45:23 +01002862 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002863 {
2864 /*
2865 * pick a random A, 1 < A < |X| - 1
2866 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002867 count = 0;
2868 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002869 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002870
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002871 j = mbedtls_mpi_bitlen( &A );
2872 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002873 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002874 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002875 }
2876
2877 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002878 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2879 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002880 }
2881
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002882 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2883 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002884
2885 /*
2886 * A = A^R mod |X|
2887 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002888 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002890 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2891 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002892 continue;
2893
2894 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002895 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002896 {
2897 /*
2898 * A = A * A mod |X|
2899 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002900 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2901 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002903 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002904 break;
2905
2906 j++;
2907 }
2908
2909 /*
2910 * not prime if A != |X| - 1 or A == 1
2911 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002912 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2913 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002914 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002915 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002916 break;
2917 }
2918 }
2919
2920cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002921 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2922 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002923 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002924
2925 return( ret );
2926}
2927
2928/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002929 * Pseudo-primality test: small factors, then Miller-Rabin
2930 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002931int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2932 int (*f_rng)(void *, unsigned char *, size_t),
2933 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002934{
Janos Follath24eed8d2019-11-22 13:21:35 +00002935 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002936 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002937 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002938 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002939
2940 XX.s = 1;
2941 XX.n = X->n;
2942 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002943
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002944 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2945 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2946 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002947
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002948 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002949 return( 0 );
2950
2951 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2952 {
2953 if( ret == 1 )
2954 return( 0 );
2955
2956 return( ret );
2957 }
2958
Janos Follathda31fa12018-09-03 14:45:23 +01002959 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002960}
2961
Janos Follatha0b67c22018-09-18 14:48:23 +01002962#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002963/*
2964 * Pseudo-primality test, error probability 2^-80
2965 */
2966int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2967 int (*f_rng)(void *, unsigned char *, size_t),
2968 void *p_rng )
2969{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002970 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002971 MPI_VALIDATE_RET( f_rng != NULL );
2972
Janos Follatha0b67c22018-09-18 14:48:23 +01002973 /*
2974 * In the past our key generation aimed for an error rate of at most
2975 * 2^-80. Since this function is deprecated, aim for the same certainty
2976 * here as well.
2977 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002978 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002979}
Janos Follatha0b67c22018-09-18 14:48:23 +01002980#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002981
2982/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002983 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002984 *
Janos Follathf301d232018-08-14 13:34:01 +01002985 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2986 * be either 1024 bits or 1536 bits long, and flags must contain
2987 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002988 */
Janos Follath7c025a92018-08-14 11:08:41 +01002989int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002990 int (*f_rng)(void *, unsigned char *, size_t),
2991 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002992{
Jethro Beekman66689272018-02-14 19:24:10 -08002993#ifdef MBEDTLS_HAVE_INT64
2994// ceil(2^63.5)
2995#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2996#else
2997// ceil(2^31.5)
2998#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2999#endif
3000 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00003001 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01003002 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003003 mbedtls_mpi_uint r;
3004 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00003005
Hanno Becker8ce11a32018-12-19 16:18:52 +00003006 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00003007 MPI_VALIDATE_RET( f_rng != NULL );
3008
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003009 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
3010 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00003011
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003012 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00003013
3014 n = BITS_TO_LIMBS( nbits );
3015
Janos Follathda31fa12018-09-03 14:45:23 +01003016 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
3017 {
3018 /*
3019 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
3020 */
3021 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
3022 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
3023 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
3024 }
3025 else
3026 {
3027 /*
3028 * 2^-100 error probability, number of rounds computed based on HAC,
3029 * fact 4.48
3030 */
3031 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
3032 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
3033 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
3034 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
3035 }
3036
Jethro Beekman66689272018-02-14 19:24:10 -08003037 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003038 {
Jethro Beekman66689272018-02-14 19:24:10 -08003039 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
3040 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
3041 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
3042
3043 k = n * biL;
3044 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
3045 X->p[0] |= 1;
3046
Janos Follath7c025a92018-08-14 11:08:41 +01003047 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003048 {
Janos Follatha0b67c22018-09-18 14:48:23 +01003049 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08003050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003051 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00003052 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003053 }
Jethro Beekman66689272018-02-14 19:24:10 -08003054 else
Paul Bakker5121ce52009-01-03 21:22:43 +00003055 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003056 /*
Jethro Beekman66689272018-02-14 19:24:10 -08003057 * An necessary condition for Y and X = 2Y + 1 to be prime
3058 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
3059 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003060 */
Jethro Beekman66689272018-02-14 19:24:10 -08003061
3062 X->p[0] |= 2;
3063
3064 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
3065 if( r == 0 )
3066 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
3067 else if( r == 1 )
3068 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
3069
3070 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
3071 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
3072 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
3073
3074 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003075 {
Jethro Beekman66689272018-02-14 19:24:10 -08003076 /*
3077 * First, check small factors for X and Y
3078 * before doing Miller-Rabin on any of them
3079 */
3080 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
3081 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003082 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003083 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003084 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003085 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08003086 goto cleanup;
3087
3088 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
3089 goto cleanup;
3090
3091 /*
3092 * Next candidates. We want to preserve Y = (X-1) / 2 and
3093 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3094 * so up Y by 6 and X by 12.
3095 */
3096 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
3097 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003098 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003099 }
3100 }
3101
3102cleanup:
3103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003104 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00003105
3106 return( ret );
3107}
3108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003109#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003111#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003112
Paul Bakker23986e52011-04-24 08:57:21 +00003113#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003114
3115static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3116{
3117 { 693, 609, 21 },
3118 { 1764, 868, 28 },
3119 { 768454923, 542167814, 1 }
3120};
3121
Paul Bakker5121ce52009-01-03 21:22:43 +00003122/*
3123 * Checkup routine
3124 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003125int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00003126{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003127 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003128 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003130 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
3131 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003133 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003134 "EFE021C2645FD1DC586E69184AF4A31E" \
3135 "D5F53E93B5F123FA41680867BA110131" \
3136 "944FE7952E2517337780CB0DB80E61AA" \
3137 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003139 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003140 "B2E7EFD37075B9F03FF989C7C5051C20" \
3141 "34D2A323810251127E7BF8625A4F49A5" \
3142 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3143 "5B5C25763222FEFCCFC38B832366C29E" ) );
3144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003145 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003146 "0066A198186C18C10B2F5ED9B522752A" \
3147 "9830B69916E535C8F047518A889A43A5" \
3148 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003150 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003152 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003153 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3154 "9E857EA95A03512E2BAE7391688D264A" \
3155 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3156 "8001B72E848A38CAE1C65F78E56ABDEF" \
3157 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3158 "ECF677152EF804370C1A305CAF3B5BF1" \
3159 "30879B56C61DE584A0F53A2447A51E" ) );
3160
3161 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003162 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003164 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003165 {
3166 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003167 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003168
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003169 ret = 1;
3170 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003171 }
3172
3173 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003174 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003176 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003178 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003179 "256567336059E52CAE22925474705F39A94" ) );
3180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003181 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003182 "6613F26162223DF488E9CD48CC132C7A" \
3183 "0AC93C701B001B092E4E5B9F73BCD27B" \
3184 "9EE50D0657C77F374E903CDFA4C642" ) );
3185
3186 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003187 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003189 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3190 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003191 {
3192 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003193 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003194
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003195 ret = 1;
3196 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003197 }
3198
3199 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003200 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003202 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003204 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003205 "36E139AEA55215609D2816998ED020BB" \
3206 "BD96C37890F65171D948E9BC7CBAA4D9" \
3207 "325D24D6A3C12710F10A09FA08AB87" ) );
3208
3209 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003210 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003212 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003213 {
3214 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003215 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003216
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003217 ret = 1;
3218 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003219 }
3220
3221 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003222 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003224 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003226 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003227 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3228 "C3DBA76456363A10869622EAC2DD84EC" \
3229 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3230
3231 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003232 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003234 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003235 {
3236 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003237 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003238
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003239 ret = 1;
3240 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003241 }
3242
3243 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003244 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003245
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003246 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003247 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003248
Paul Bakker66d5d072014-06-17 16:39:18 +02003249 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003250 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003251 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3252 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003254 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003256 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003257 {
3258 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003259 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003260
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003261 ret = 1;
3262 goto cleanup;
3263 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003264 }
3265
3266 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003267 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003268
Paul Bakker5121ce52009-01-03 21:22:43 +00003269cleanup:
3270
3271 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003272 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003274 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3275 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003276
3277 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003278 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003279
3280 return( ret );
3281}
3282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003283#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003285#endif /* MBEDTLS_BIGNUM_C */