blob: 7cc42766e44c2e97da5bdedb69b65c9fef87313e [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
261/*
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200262 * Conditionally assign dest = src, without leaking information
263 * about whether the assignment was made or not.
264 * dest and src must be arrays of limbs of size n.
265 * assign must be 0 or 1.
266 */
267static void mpi_safe_cond_assign( size_t n,
268 mbedtls_mpi_uint *dest,
269 const mbedtls_mpi_uint *src,
270 unsigned char assign )
271{
272 size_t i;
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200273
274 /* MSVC has a warning about unary minus on unsigned integer types,
275 * but this is well-defined and precisely what we want to do here. */
276#if defined(_MSC_VER)
277#pragma warning( push )
278#pragma warning( disable : 4146 )
279#endif
280
281 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
282 const mbedtls_mpi_uint mask = -assign;
283
284#if defined(_MSC_VER)
285#pragma warning( pop )
286#endif
287
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200288 for( i = 0; i < n; i++ )
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200289 dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200290}
291
292/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100293 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100294 * about whether the assignment was made or not.
295 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100296 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100298{
299 int ret = 0;
300 size_t i;
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200301 unsigned int mask;
302 mbedtls_mpi_uint limb_mask;
Hanno Becker73d7d792018-12-11 10:35:51 +0000303 MPI_VALIDATE_RET( X != NULL );
304 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100305
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200306 /* MSVC has a warning about unary minus on unsigned integer types,
307 * but this is well-defined and precisely what we want to do here. */
308#if defined(_MSC_VER)
309#pragma warning( push )
310#pragma warning( disable : 4146 )
311#endif
312
Pascal Junodb99183d2015-03-11 16:49:45 +0100313 /* make sure assign is 0 or 1 in a time-constant manner */
314 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200315 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
316 mask = -assign;
317 limb_mask = -assign;
318
319#if defined(_MSC_VER)
320#pragma warning( pop )
321#endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100324
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200325 X->s = ( X->s & ~mask ) | ( Y->s & mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100326
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200327 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100328
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200329 for( i = Y->n; i < X->n; i++ )
Manuel Pégourié-Gonnardc3be3992021-05-31 11:48:45 +0200330 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100331
332cleanup:
333 return( ret );
334}
335
336/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100337 * Conditionally swap X and Y, without leaking information
338 * about whether the swap was made or not.
339 * Here it is not ok to simply swap the pointers, which whould lead to
340 * different memory access patterns when X and Y are used afterwards.
341 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100343{
344 int ret, s;
345 size_t i;
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200346 unsigned int sign_mask;
347 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000349 MPI_VALIDATE_RET( X != NULL );
350 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100351
352 if( X == Y )
353 return( 0 );
354
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200355 /* MSVC has a warning about unary minus on unsigned integer types,
356 * but this is well-defined and precisely what we want to do here. */
357#if defined(_MSC_VER)
358#pragma warning( push )
359#pragma warning( disable : 4146 )
360#endif
361
Pascal Junodb99183d2015-03-11 16:49:45 +0100362 /* make sure swap is 0 or 1 in a time-constant manner */
363 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200364 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
365 sign_mask = -swap;
366 limb_mask = -swap;
367
368#if defined(_MSC_VER)
369#pragma warning( pop )
370#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
373 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100374
375 s = X->s;
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200376 X->s = ( X->s & ~sign_mask ) | ( Y->s & sign_mask );
377 Y->s = ( Y->s & ~sign_mask ) | ( s & sign_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100378
379
380 for( i = 0; i < X->n; i++ )
381 {
382 tmp = X->p[i];
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200383 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
384 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100385 }
386
387cleanup:
388 return( ret );
389}
390
391/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000392 * Set value from integer
393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000395{
Janos Follath24eed8d2019-11-22 13:21:35 +0000396 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000397 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000400 memset( X->p, 0, X->n * ciL );
401
402 X->p[0] = ( z < 0 ) ? -z : z;
403 X->s = ( z < 0 ) ? -1 : 1;
404
405cleanup:
406
407 return( ret );
408}
409
410/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000411 * Get a specific bit
412 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000414{
Hanno Becker73d7d792018-12-11 10:35:51 +0000415 MPI_VALIDATE_RET( X != NULL );
416
Paul Bakker2f5947e2011-05-18 15:47:11 +0000417 if( X->n * biL <= pos )
418 return( 0 );
419
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200420 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000421}
422
Gilles Peskine11cdb052018-11-20 16:47:47 +0100423/* Get a specific byte, without range checks. */
424#define GET_BYTE( X, i ) \
425 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
426
Paul Bakker2f5947e2011-05-18 15:47:11 +0000427/*
428 * Set a bit to a specific value of 0 or 1
429 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000431{
432 int ret = 0;
433 size_t off = pos / biL;
434 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000435 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000436
437 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200439
Paul Bakker2f5947e2011-05-18 15:47:11 +0000440 if( X->n * biL <= pos )
441 {
442 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200443 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000446 }
447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
449 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000450
451cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200452
Paul Bakker2f5947e2011-05-18 15:47:11 +0000453 return( ret );
454}
455
456/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200457 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000460{
Paul Bakker23986e52011-04-24 08:57:21 +0000461 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000462 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
464 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000465 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000466 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
467 return( count );
468
469 return( 0 );
470}
471
472/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000473 * Count leading zero bits in a given integer
474 */
475static size_t mbedtls_clz( const mbedtls_mpi_uint x )
476{
477 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100478 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000479
480 for( j = 0; j < biL; j++ )
481 {
482 if( x & mask ) break;
483
484 mask >>= 1;
485 }
486
487 return j;
488}
489
490/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200491 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000492 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200493size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000494{
Paul Bakker23986e52011-04-24 08:57:21 +0000495 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000496
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200497 if( X->n == 0 )
498 return( 0 );
499
Paul Bakker5121ce52009-01-03 21:22:43 +0000500 for( i = X->n - 1; i > 0; i-- )
501 if( X->p[i] != 0 )
502 break;
503
Simon Butcher15b15d12015-11-26 19:35:03 +0000504 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
Paul Bakker23986e52011-04-24 08:57:21 +0000506 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000507}
508
509/*
510 * Return the total size in bytes
511 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000513{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200514 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000515}
516
517/*
518 * Convert an ASCII character to digit value
519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000521{
522 *d = 255;
523
524 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
525 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
526 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528 if( *d >= (mbedtls_mpi_uint) radix )
529 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
531 return( 0 );
532}
533
534/*
535 * Import from an ASCII string
536 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000538{
Janos Follath24eed8d2019-11-22 13:21:35 +0000539 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000540 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200541 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 mbedtls_mpi_uint d;
543 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000544 MPI_VALIDATE_RET( X != NULL );
545 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
547 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000548 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
Gilles Peskine80f56732021-04-03 18:26:13 +0200552 if( s[0] == '-' )
553 {
554 ++s;
555 sign = -1;
556 }
557
Paul Bakkerff60ee62010-03-16 21:09:09 +0000558 slen = strlen( s );
559
Paul Bakker5121ce52009-01-03 21:22:43 +0000560 if( radix == 16 )
561 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100562 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200563 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
564
Paul Bakkerff60ee62010-03-16 21:09:09 +0000565 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
568 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
Paul Bakker23986e52011-04-24 08:57:21 +0000570 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200573 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 }
575 }
576 else
577 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
Paul Bakkerff60ee62010-03-16 21:09:09 +0000580 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
583 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200584 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000585 }
586 }
587
Gilles Peskine80f56732021-04-03 18:26:13 +0200588 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
589 X->s = -1;
590
Paul Bakker5121ce52009-01-03 21:22:43 +0000591cleanup:
592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
595 return( ret );
596}
597
598/*
Ron Eldora16fa292018-11-20 14:07:01 +0200599 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000600 */
Ron Eldora16fa292018-11-20 14:07:01 +0200601static int mpi_write_hlp( mbedtls_mpi *X, int radix,
602 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000603{
Janos Follath24eed8d2019-11-22 13:21:35 +0000604 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200606 size_t length = 0;
607 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
Ron Eldora16fa292018-11-20 14:07:01 +0200609 do
610 {
611 if( length >= buflen )
612 {
613 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
614 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000615
Ron Eldora16fa292018-11-20 14:07:01 +0200616 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
617 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
618 /*
619 * Write the residue in the current position, as an ASCII character.
620 */
621 if( r < 0xA )
622 *(--p_end) = (char)( '0' + r );
623 else
624 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
Ron Eldora16fa292018-11-20 14:07:01 +0200626 length++;
627 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000628
Ron Eldora16fa292018-11-20 14:07:01 +0200629 memmove( *p, p_end, length );
630 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632cleanup:
633
634 return( ret );
635}
636
637/*
638 * Export into an ASCII string
639 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100640int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
641 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000642{
Paul Bakker23986e52011-04-24 08:57:21 +0000643 int ret = 0;
644 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000645 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000647 MPI_VALIDATE_RET( X != NULL );
648 MPI_VALIDATE_RET( olen != NULL );
649 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
651 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000652 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653
Hanno Becker23cfea02019-02-04 09:45:07 +0000654 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
655 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
656 * `n`. If radix > 4, this might be a strict
657 * overapproximation of the number of
658 * radix-adic digits needed to present `n`. */
659 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
660 * present `n`. */
661
Janos Follath80470622019-03-06 13:43:02 +0000662 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000663 n += 1; /* Compensate for the divisions above, which round down `n`
664 * in case it's not even. */
665 n += 1; /* Potential '-'-sign. */
666 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
667 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100669 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000670 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100671 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673 }
674
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100675 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
678 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000679 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000680 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000681 buflen--;
682 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
684 if( radix == 16 )
685 {
Paul Bakker23986e52011-04-24 08:57:21 +0000686 int c;
687 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000688
Paul Bakker23986e52011-04-24 08:57:21 +0000689 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000690 {
Paul Bakker23986e52011-04-24 08:57:21 +0000691 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000692 {
Paul Bakker23986e52011-04-24 08:57:21 +0000693 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
Paul Bakker6c343d72014-07-10 14:36:19 +0200695 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000696 continue;
697
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000698 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000699 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000700 k = 1;
701 }
702 }
703 }
704 else
705 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000707
708 if( T.s == -1 )
709 T.s = 1;
710
Ron Eldora16fa292018-11-20 14:07:01 +0200711 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000712 }
713
714 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100715 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
717cleanup:
718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
721 return( ret );
722}
723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000725/*
726 * Read X from an opened file
727 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000729{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000731 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000732 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000733 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000734 * Buffer should have space for (short) label and decimal formatted MPI,
735 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000736 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
Hanno Becker73d7d792018-12-11 10:35:51 +0000739 MPI_VALIDATE_RET( X != NULL );
740 MPI_VALIDATE_RET( fin != NULL );
741
742 if( radix < 2 || radix > 16 )
743 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
744
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 memset( s, 0, sizeof( s ) );
746 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000748
749 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000750 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000752
Hanno Beckerb2034b72017-04-26 11:46:46 +0100753 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
754 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000755
756 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100757 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000758 if( mpi_get_digit( &d, radix, *p ) != 0 )
759 break;
760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000762}
763
764/*
765 * Write X into an opened file (or stdout if fout == NULL)
766 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200767int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000768{
Janos Follath24eed8d2019-11-22 13:21:35 +0000769 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000770 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000771 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000772 * Buffer should have space for (short) label and decimal formatted MPI,
773 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000774 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000776 MPI_VALIDATE_RET( X != NULL );
777
778 if( radix < 2 || radix > 16 )
779 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100781 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100783 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000784
785 if( p == NULL ) p = "";
786
787 plen = strlen( p );
788 slen = strlen( s );
789 s[slen++] = '\r';
790 s[slen++] = '\n';
791
792 if( fout != NULL )
793 {
794 if( fwrite( p, 1, plen, fout ) != plen ||
795 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000797 }
798 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200799 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000800
801cleanup:
802
803 return( ret );
804}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000806
Hanno Beckerda1655a2017-10-18 14:21:44 +0100807
808/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
809 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000810
811static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
812{
813 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100814 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000815 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100816
817 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
818 {
819 tmp <<= CHAR_BIT;
820 tmp |= (mbedtls_mpi_uint) *x_ptr;
821 }
822
Hanno Beckerf8720072018-11-08 11:53:49 +0000823 return( tmp );
824}
825
826static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
827{
828#if defined(__BYTE_ORDER__)
829
830/* Nothing to do on bigendian systems. */
831#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
832 return( x );
833#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
834
835#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
836
837/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000838#if defined(__GNUC__) && defined(__GNUC_PREREQ)
839#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000840#define have_bswap
841#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000842#endif
843
844#if defined(__clang__) && defined(__has_builtin)
845#if __has_builtin(__builtin_bswap32) && \
846 __has_builtin(__builtin_bswap64)
847#define have_bswap
848#endif
849#endif
850
Hanno Beckerf8720072018-11-08 11:53:49 +0000851#if defined(have_bswap)
852 /* The compiler is hopefully able to statically evaluate this! */
853 switch( sizeof(mbedtls_mpi_uint) )
854 {
855 case 4:
856 return( __builtin_bswap32(x) );
857 case 8:
858 return( __builtin_bswap64(x) );
859 }
860#endif
861#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
862#endif /* __BYTE_ORDER__ */
863
864 /* Fall back to C-based reordering if we don't know the byte order
865 * or we couldn't use a compiler-specific builtin. */
866 return( mpi_uint_bigendian_to_host_c( x ) );
867}
868
Hanno Becker2be8a552018-10-25 12:40:09 +0100869static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100870{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100871 mbedtls_mpi_uint *cur_limb_left;
872 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100873 if( limbs == 0 )
874 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100875
876 /*
877 * Traverse limbs and
878 * - adapt byte-order in each limb
879 * - swap the limbs themselves.
880 * For that, simultaneously traverse the limbs from left to right
881 * and from right to left, as long as the left index is not bigger
882 * than the right index (it's not a problem if limbs is odd and the
883 * indices coincide in the last iteration).
884 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100885 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
886 cur_limb_left <= cur_limb_right;
887 cur_limb_left++, cur_limb_right-- )
888 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000889 mbedtls_mpi_uint tmp;
890 /* Note that if cur_limb_left == cur_limb_right,
891 * this code effectively swaps the bytes only once. */
892 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
893 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
894 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100895 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100896}
897
Paul Bakker5121ce52009-01-03 21:22:43 +0000898/*
Janos Follatha778a942019-02-13 10:28:28 +0000899 * Import X from unsigned binary data, little endian
900 */
901int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
902 const unsigned char *buf, size_t buflen )
903{
Janos Follath24eed8d2019-11-22 13:21:35 +0000904 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000905 size_t i;
906 size_t const limbs = CHARS_TO_LIMBS( buflen );
907
908 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200909 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000910
911 for( i = 0; i < buflen; i++ )
912 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
913
914cleanup:
915
Janos Follath171a7ef2019-02-15 16:17:45 +0000916 /*
917 * This function is also used to import keys. However, wiping the buffers
918 * upon failure is not necessary because failure only can happen before any
919 * input is copied.
920 */
Janos Follatha778a942019-02-13 10:28:28 +0000921 return( ret );
922}
923
924/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000925 * Import X from unsigned binary data, big endian
926 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000928{
Janos Follath24eed8d2019-11-22 13:21:35 +0000929 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100930 size_t const limbs = CHARS_TO_LIMBS( buflen );
931 size_t const overhead = ( limbs * ciL ) - buflen;
932 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000933
Hanno Becker8ce11a32018-12-19 16:18:52 +0000934 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000935 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
936
Hanno Becker073c1992017-10-17 15:17:27 +0100937 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200938 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
Gilles Peskine3130ce22021-06-02 22:17:52 +0200940 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000941 * even if buflen is 0. */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200942 if( buflen != 0 )
Hanno Becker0e810b92019-01-03 17:13:11 +0000943 {
944 Xp = (unsigned char*) X->p;
945 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100946
Hanno Becker0e810b92019-01-03 17:13:11 +0000947 mpi_bigendian_to_host( X->p, limbs );
948 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000949
950cleanup:
951
Janos Follath171a7ef2019-02-15 16:17:45 +0000952 /*
953 * This function is also used to import keys. However, wiping the buffers
954 * upon failure is not necessary because failure only can happen before any
955 * input is copied.
956 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000957 return( ret );
958}
959
960/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000961 * Export X into unsigned binary data, little endian
962 */
963int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
964 unsigned char *buf, size_t buflen )
965{
966 size_t stored_bytes = X->n * ciL;
967 size_t bytes_to_copy;
968 size_t i;
969
970 if( stored_bytes < buflen )
971 {
972 bytes_to_copy = stored_bytes;
973 }
974 else
975 {
976 bytes_to_copy = buflen;
977
978 /* The output buffer is smaller than the allocated size of X.
979 * However X may fit if its leading bytes are zero. */
980 for( i = bytes_to_copy; i < stored_bytes; i++ )
981 {
982 if( GET_BYTE( X, i ) != 0 )
983 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
984 }
985 }
986
987 for( i = 0; i < bytes_to_copy; i++ )
988 buf[i] = GET_BYTE( X, i );
989
990 if( stored_bytes < buflen )
991 {
992 /* Write trailing 0 bytes */
993 memset( buf + stored_bytes, 0, buflen - stored_bytes );
994 }
995
996 return( 0 );
997}
998
999/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 * Export X into unsigned binary data, big endian
1001 */
Gilles Peskine11cdb052018-11-20 16:47:47 +01001002int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
1003 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001004{
Hanno Becker73d7d792018-12-11 10:35:51 +00001005 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +01001006 size_t bytes_to_copy;
1007 unsigned char *p;
1008 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001009
Hanno Becker73d7d792018-12-11 10:35:51 +00001010 MPI_VALIDATE_RET( X != NULL );
1011 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
1012
1013 stored_bytes = X->n * ciL;
1014
Gilles Peskine11cdb052018-11-20 16:47:47 +01001015 if( stored_bytes < buflen )
1016 {
1017 /* There is enough space in the output buffer. Write initial
1018 * null bytes and record the position at which to start
1019 * writing the significant bytes. In this case, the execution
1020 * trace of this function does not depend on the value of the
1021 * number. */
1022 bytes_to_copy = stored_bytes;
1023 p = buf + buflen - stored_bytes;
1024 memset( buf, 0, buflen - stored_bytes );
1025 }
1026 else
1027 {
1028 /* The output buffer is smaller than the allocated size of X.
1029 * However X may fit if its leading bytes are zero. */
1030 bytes_to_copy = buflen;
1031 p = buf;
1032 for( i = bytes_to_copy; i < stored_bytes; i++ )
1033 {
1034 if( GET_BYTE( X, i ) != 0 )
1035 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1036 }
1037 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001038
Gilles Peskine11cdb052018-11-20 16:47:47 +01001039 for( i = 0; i < bytes_to_copy; i++ )
1040 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001041
1042 return( 0 );
1043}
1044
1045/*
1046 * Left-shift: X <<= count
1047 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001049{
Janos Follath24eed8d2019-11-22 13:21:35 +00001050 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001051 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001053 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
1055 v0 = count / (biL );
1056 t1 = count & (biL - 1);
1057
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001058 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001059
Paul Bakkerf9688572011-05-05 10:00:45 +00001060 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062
1063 ret = 0;
1064
1065 /*
1066 * shift by count / limb_size
1067 */
1068 if( v0 > 0 )
1069 {
Paul Bakker23986e52011-04-24 08:57:21 +00001070 for( i = X->n; i > v0; i-- )
1071 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001072
Paul Bakker23986e52011-04-24 08:57:21 +00001073 for( ; i > 0; i-- )
1074 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 }
1076
1077 /*
1078 * shift by count % limb_size
1079 */
1080 if( t1 > 0 )
1081 {
1082 for( i = v0; i < X->n; i++ )
1083 {
1084 r1 = X->p[i] >> (biL - t1);
1085 X->p[i] <<= t1;
1086 X->p[i] |= r0;
1087 r0 = r1;
1088 }
1089 }
1090
1091cleanup:
1092
1093 return( ret );
1094}
1095
1096/*
1097 * Right-shift: X >>= count
1098 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001099int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001100{
Paul Bakker23986e52011-04-24 08:57:21 +00001101 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001103 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001104
1105 v0 = count / biL;
1106 v1 = count & (biL - 1);
1107
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001108 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001110
Paul Bakker5121ce52009-01-03 21:22:43 +00001111 /*
1112 * shift by count / limb_size
1113 */
1114 if( v0 > 0 )
1115 {
1116 for( i = 0; i < X->n - v0; i++ )
1117 X->p[i] = X->p[i + v0];
1118
1119 for( ; i < X->n; i++ )
1120 X->p[i] = 0;
1121 }
1122
1123 /*
1124 * shift by count % limb_size
1125 */
1126 if( v1 > 0 )
1127 {
Paul Bakker23986e52011-04-24 08:57:21 +00001128 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001129 {
Paul Bakker23986e52011-04-24 08:57:21 +00001130 r1 = X->p[i - 1] << (biL - v1);
1131 X->p[i - 1] >>= v1;
1132 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 r0 = r1;
1134 }
1135 }
1136
1137 return( 0 );
1138}
1139
1140/*
1141 * Compare unsigned values
1142 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001144{
Paul Bakker23986e52011-04-24 08:57:21 +00001145 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001146 MPI_VALIDATE_RET( X != NULL );
1147 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
Paul Bakker23986e52011-04-24 08:57:21 +00001149 for( i = X->n; i > 0; i-- )
1150 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001151 break;
1152
Paul Bakker23986e52011-04-24 08:57:21 +00001153 for( j = Y->n; j > 0; j-- )
1154 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001155 break;
1156
Paul Bakker23986e52011-04-24 08:57:21 +00001157 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001158 return( 0 );
1159
1160 if( i > j ) return( 1 );
1161 if( j > i ) return( -1 );
1162
Paul Bakker23986e52011-04-24 08:57:21 +00001163 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001164 {
Paul Bakker23986e52011-04-24 08:57:21 +00001165 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1166 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 }
1168
1169 return( 0 );
1170}
1171
1172/*
1173 * Compare signed values
1174 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001175int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001176{
Paul Bakker23986e52011-04-24 08:57:21 +00001177 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001178 MPI_VALIDATE_RET( X != NULL );
1179 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001180
Paul Bakker23986e52011-04-24 08:57:21 +00001181 for( i = X->n; i > 0; i-- )
1182 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001183 break;
1184
Paul Bakker23986e52011-04-24 08:57:21 +00001185 for( j = Y->n; j > 0; j-- )
1186 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001187 break;
1188
Paul Bakker23986e52011-04-24 08:57:21 +00001189 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 return( 0 );
1191
1192 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001193 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001194
1195 if( X->s > 0 && Y->s < 0 ) return( 1 );
1196 if( Y->s > 0 && X->s < 0 ) return( -1 );
1197
Paul Bakker23986e52011-04-24 08:57:21 +00001198 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001199 {
Paul Bakker23986e52011-04-24 08:57:21 +00001200 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1201 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 }
1203
1204 return( 0 );
1205}
1206
Janos Follath3f6f0e42019-10-14 09:09:32 +01001207/** Decide if an integer is less than the other, without branches.
1208 *
1209 * \param x First integer.
1210 * \param y Second integer.
1211 *
1212 * \return 1 if \p x is less than \p y, 0 otherwise
1213 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001214static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1215 const mbedtls_mpi_uint y )
Janos Follathee6abce2019-09-05 14:47:19 +01001216{
1217 mbedtls_mpi_uint ret;
1218 mbedtls_mpi_uint cond;
1219
1220 /*
1221 * Check if the most significant bits (MSB) of the operands are different.
1222 */
1223 cond = ( x ^ y );
1224 /*
1225 * If the MSB are the same then the difference x-y will be negative (and
1226 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1227 */
1228 ret = ( x - y ) & ~cond;
1229 /*
1230 * If the MSB are different, then the operand with the MSB of 1 is the
1231 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1232 * the MSB of y is 0.)
1233 */
1234 ret |= y & cond;
1235
1236
Janos Follatha0f732b2019-10-14 08:59:14 +01001237 ret = ret >> ( biL - 1 );
Janos Follathee6abce2019-09-05 14:47:19 +01001238
Janos Follath67ce6472019-10-29 15:08:46 +00001239 return (unsigned) ret;
Janos Follathee6abce2019-09-05 14:47:19 +01001240}
1241
1242/*
1243 * Compare signed values in constant time
1244 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001245int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1246 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001247{
1248 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001249 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001250 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001251
1252 MPI_VALIDATE_RET( X != NULL );
1253 MPI_VALIDATE_RET( Y != NULL );
1254 MPI_VALIDATE_RET( ret != NULL );
1255
1256 if( X->n != Y->n )
1257 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1258
1259 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001260 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1261 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001262 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001263 X_is_negative = ( X->s & 2 ) >> 1;
1264 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001265
1266 /*
1267 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001268 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1269 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001270 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001271 cond = ( X_is_negative ^ Y_is_negative );
1272 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001273
1274 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001275 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001276 * need to go through the loop. Record if we have the result already.
1277 */
Janos Follathee6abce2019-09-05 14:47:19 +01001278 done = cond;
1279
1280 for( i = X->n; i > 0; i-- )
1281 {
1282 /*
Janos Follath30702422019-11-05 12:24:52 +00001283 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1284 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001285 *
1286 * Again even if we can make a decision, we just mark the result and
1287 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001288 */
Janos Follath30702422019-11-05 12:24:52 +00001289 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1290 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001291 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001292
1293 /*
Janos Follath30702422019-11-05 12:24:52 +00001294 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1295 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001296 *
1297 * Again even if we can make a decision, we just mark the result and
1298 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001299 */
Janos Follath30702422019-11-05 12:24:52 +00001300 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1301 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001302 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001303 }
1304
1305 return( 0 );
1306}
1307
Paul Bakker5121ce52009-01-03 21:22:43 +00001308/*
1309 * Compare signed values
1310 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001312{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 mbedtls_mpi Y;
1314 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001315 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001316
1317 *p = ( z < 0 ) ? -z : z;
1318 Y.s = ( z < 0 ) ? -1 : 1;
1319 Y.n = 1;
1320 Y.p = p;
1321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001323}
1324
1325/*
1326 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001329{
Janos Follath24eed8d2019-11-22 13:21:35 +00001330 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001331 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001332 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001333 MPI_VALIDATE_RET( X != NULL );
1334 MPI_VALIDATE_RET( A != NULL );
1335 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001336
1337 if( X == B )
1338 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 }
1341
1342 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001344
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001345 /*
1346 * X should always be positive as a result of unsigned additions.
1347 */
1348 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001349
Paul Bakker23986e52011-04-24 08:57:21 +00001350 for( j = B->n; j > 0; j-- )
1351 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001352 break;
1353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
1356 o = B->p; p = X->p; c = 0;
1357
Janos Follath6c922682015-10-30 17:43:11 +01001358 /*
1359 * tmp is used because it might happen that p == o
1360 */
Paul Bakker23986e52011-04-24 08:57:21 +00001361 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 {
Janos Follath6c922682015-10-30 17:43:11 +01001363 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001364 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001365 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001366 }
1367
1368 while( c != 0 )
1369 {
1370 if( i >= X->n )
1371 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 p = X->p + i;
1374 }
1375
Paul Bakker2d319fd2012-09-16 21:34:26 +00001376 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001377 }
1378
1379cleanup:
1380
1381 return( ret );
1382}
1383
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001384/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001385 * Helper for mbedtls_mpi subtraction.
1386 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001387 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001388 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001389 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001390 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001391 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001392 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001393 * \param n Number of limbs of \p d, \p l and \p r.
1394 * \param[out] d The result of the subtraction.
1395 * \param[in] l The left operand.
1396 * \param[in] r The right operand.
1397 *
1398 * \return 1 if `l < r`.
1399 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001400 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001401static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1402 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001403 const mbedtls_mpi_uint *l,
1404 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001405{
Paul Bakker23986e52011-04-24 08:57:21 +00001406 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001407 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001409 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001410 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001411 z = ( l[i] < c ); t = l[i] - c;
1412 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 }
1414
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001415 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416}
1417
1418/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001419 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001420 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001421int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001422{
Janos Follath24eed8d2019-11-22 13:21:35 +00001423 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001424 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001425 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001426 MPI_VALIDATE_RET( X != NULL );
1427 MPI_VALIDATE_RET( A != NULL );
1428 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001429
Paul Bakker23986e52011-04-24 08:57:21 +00001430 for( n = B->n; n > 0; n-- )
1431 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001432 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001433 if( n > A->n )
1434 {
1435 /* B >= (2^ciL)^n > A */
1436 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1437 goto cleanup;
1438 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001439
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001440 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1441
1442 /* Set the high limbs of X to match A. Don't touch the lower limbs
1443 * because X might be aliased to B, and we must not overwrite the
1444 * significant digits of B. */
1445 if( A->n > n )
1446 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1447 if( X->n > A->n )
1448 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1449
1450 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001451 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001452 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001453 /* Propagate the carry to the first nonzero limb of X. */
1454 for( ; n < X->n && X->p[n] == 0; n++ )
1455 --X->p[n];
1456 /* If we ran out of space for the carry, it means that the result
1457 * is negative. */
1458 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001459 {
1460 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1461 goto cleanup;
1462 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001463 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001464 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001465
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001466 /* X should always be positive as a result of unsigned subtractions. */
1467 X->s = 1;
1468
Paul Bakker5121ce52009-01-03 21:22:43 +00001469cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001470 return( ret );
1471}
1472
1473/*
1474 * Signed addition: X = A + B
1475 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001477{
Hanno Becker73d7d792018-12-11 10:35:51 +00001478 int ret, s;
1479 MPI_VALIDATE_RET( X != NULL );
1480 MPI_VALIDATE_RET( A != NULL );
1481 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482
Hanno Becker73d7d792018-12-11 10:35:51 +00001483 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001484 if( A->s * B->s < 0 )
1485 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001487 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489 X->s = s;
1490 }
1491 else
1492 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001494 X->s = -s;
1495 }
1496 }
1497 else
1498 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 X->s = s;
1501 }
1502
1503cleanup:
1504
1505 return( ret );
1506}
1507
1508/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001509 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001512{
Hanno Becker73d7d792018-12-11 10:35:51 +00001513 int ret, s;
1514 MPI_VALIDATE_RET( X != NULL );
1515 MPI_VALIDATE_RET( A != NULL );
1516 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001517
Hanno Becker73d7d792018-12-11 10:35:51 +00001518 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001519 if( A->s * B->s > 0 )
1520 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001521 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001522 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001523 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001524 X->s = s;
1525 }
1526 else
1527 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001529 X->s = -s;
1530 }
1531 }
1532 else
1533 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001535 X->s = s;
1536 }
1537
1538cleanup:
1539
1540 return( ret );
1541}
1542
1543/*
1544 * Signed addition: X = A + b
1545 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001547{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548 mbedtls_mpi _B;
1549 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001550 MPI_VALIDATE_RET( X != NULL );
1551 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001552
1553 p[0] = ( b < 0 ) ? -b : b;
1554 _B.s = ( b < 0 ) ? -1 : 1;
1555 _B.n = 1;
1556 _B.p = p;
1557
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001559}
1560
1561/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001562 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001564int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001565{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 mbedtls_mpi _B;
1567 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001568 MPI_VALIDATE_RET( X != NULL );
1569 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001570
1571 p[0] = ( b < 0 ) ? -b : b;
1572 _B.s = ( b < 0 ) ? -1 : 1;
1573 _B.n = 1;
1574 _B.p = p;
1575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001577}
1578
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001579/** Helper for mbedtls_mpi multiplication.
1580 *
1581 * Add \p b * \p s to \p d.
1582 *
1583 * \param i The number of limbs of \p s.
1584 * \param[in] s A bignum to multiply, of size \p i.
1585 * It may overlap with \p d, but only if
1586 * \p d <= \p s.
1587 * Its leading limb must not be \c 0.
1588 * \param[in,out] d The bignum to add to.
1589 * It must be sufficiently large to store the
1590 * result of the multiplication. This means
1591 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1592 * is not known a priori.
1593 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001594 */
1595static
1596#if defined(__APPLE__) && defined(__arm__)
1597/*
1598 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1599 * appears to need this to prevent bad ARM code generation at -O3.
1600 */
1601__attribute__ ((noinline))
1602#endif
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001603void mpi_mul_hlp( size_t i,
1604 const mbedtls_mpi_uint *s,
1605 mbedtls_mpi_uint *d,
1606 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001607{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
1610#if defined(MULADDC_HUIT)
1611 for( ; i >= 8; i -= 8 )
1612 {
1613 MULADDC_INIT
1614 MULADDC_HUIT
1615 MULADDC_STOP
1616 }
1617
1618 for( ; i > 0; i-- )
1619 {
1620 MULADDC_INIT
1621 MULADDC_CORE
1622 MULADDC_STOP
1623 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001624#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001625 for( ; i >= 16; i -= 16 )
1626 {
1627 MULADDC_INIT
1628 MULADDC_CORE MULADDC_CORE
1629 MULADDC_CORE MULADDC_CORE
1630 MULADDC_CORE MULADDC_CORE
1631 MULADDC_CORE MULADDC_CORE
1632
1633 MULADDC_CORE MULADDC_CORE
1634 MULADDC_CORE MULADDC_CORE
1635 MULADDC_CORE MULADDC_CORE
1636 MULADDC_CORE MULADDC_CORE
1637 MULADDC_STOP
1638 }
1639
1640 for( ; i >= 8; i -= 8 )
1641 {
1642 MULADDC_INIT
1643 MULADDC_CORE MULADDC_CORE
1644 MULADDC_CORE MULADDC_CORE
1645
1646 MULADDC_CORE MULADDC_CORE
1647 MULADDC_CORE MULADDC_CORE
1648 MULADDC_STOP
1649 }
1650
1651 for( ; i > 0; i-- )
1652 {
1653 MULADDC_INIT
1654 MULADDC_CORE
1655 MULADDC_STOP
1656 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001657#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001658
1659 t++;
1660
Gilles Peskine8e464c42020-07-24 00:08:38 +02001661 while( c != 0 )
1662 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001663 *d += c; c = ( *d < c ); d++;
1664 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001665}
1666
1667/*
1668 * Baseline multiplication: X = A * B (HAC 14.12)
1669 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001670int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001671{
Janos Follath24eed8d2019-11-22 13:21:35 +00001672 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001673 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001675 MPI_VALIDATE_RET( X != NULL );
1676 MPI_VALIDATE_RET( A != NULL );
1677 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001680
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001681 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1682 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001683
Paul Bakker23986e52011-04-24 08:57:21 +00001684 for( i = A->n; i > 0; i-- )
1685 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 break;
1687
Paul Bakker23986e52011-04-24 08:57:21 +00001688 for( j = B->n; j > 0; j-- )
1689 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 break;
1691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1693 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001695 for( ; j > 0; j-- )
1696 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 X->s = A->s * B->s;
1699
1700cleanup:
1701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
1704 return( ret );
1705}
1706
1707/*
1708 * Baseline multiplication: X = A * b
1709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001710int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001711{
Hanno Becker73d7d792018-12-11 10:35:51 +00001712 MPI_VALIDATE_RET( X != NULL );
1713 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001714
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001715 /* mpi_mul_hlp can't deal with a leading 0. */
1716 size_t n = A->n;
1717 while( n > 0 && A->p[n - 1] == 0 )
1718 --n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001720 /* The general method below doesn't work if n==0 or b==0. By chance
1721 * calculating the result is trivial in those cases. */
1722 if( b == 0 || n == 0 )
1723 {
Paul Elliott986b55a2021-04-20 21:46:29 +01001724 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001725 }
1726
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001727 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001728 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001729 /* In general, A * b requires 1 limb more than b. If
1730 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1731 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001732 * copy() will take care of the growth if needed. However, experimentally,
1733 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001734 * calls to calloc() in ECP code, presumably because it reuses the
1735 * same mpi for a while and this way the mpi is more likely to directly
1736 * grow to its final size. */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001737 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
1738 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1739 mpi_mul_hlp( n, A->p, X->p, b - 1 );
1740
1741cleanup:
1742 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001743}
1744
1745/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001746 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1747 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001748 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001749static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1750 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001751{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001752#if defined(MBEDTLS_HAVE_UDBL)
1753 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001754#else
Simon Butcher9803d072016-01-03 00:24:34 +00001755 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1756 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001757 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1758 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001759 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001760#endif
1761
Simon Butcher15b15d12015-11-26 19:35:03 +00001762 /*
1763 * Check for overflow
1764 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001765 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001766 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001767 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001768
Simon Butcherf5ba0452015-12-27 23:01:55 +00001769 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001770 }
1771
1772#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001773 dividend = (mbedtls_t_udbl) u1 << biL;
1774 dividend |= (mbedtls_t_udbl) u0;
1775 quotient = dividend / d;
1776 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1777 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1778
1779 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001780 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001781
1782 return (mbedtls_mpi_uint) quotient;
1783#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001784
1785 /*
1786 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1787 * Vol. 2 - Seminumerical Algorithms, Knuth
1788 */
1789
1790 /*
1791 * Normalize the divisor, d, and dividend, u0, u1
1792 */
1793 s = mbedtls_clz( d );
1794 d = d << s;
1795
1796 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001797 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001798 u0 = u0 << s;
1799
1800 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001801 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001802
1803 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001804 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001805
1806 /*
1807 * Find the first quotient and remainder
1808 */
1809 q1 = u1 / d1;
1810 r0 = u1 - d1 * q1;
1811
1812 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1813 {
1814 q1 -= 1;
1815 r0 += d1;
1816
1817 if ( r0 >= radix ) break;
1818 }
1819
Simon Butcherf5ba0452015-12-27 23:01:55 +00001820 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001821 q0 = rAX / d1;
1822 r0 = rAX - q0 * d1;
1823
1824 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1825 {
1826 q0 -= 1;
1827 r0 += d1;
1828
1829 if ( r0 >= radix ) break;
1830 }
1831
1832 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001833 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001834
1835 quotient = q1 * radix + q0;
1836
1837 return quotient;
1838#endif
1839}
1840
1841/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001844int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1845 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001846{
Janos Follath24eed8d2019-11-22 13:21:35 +00001847 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001848 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001850 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001851 MPI_VALIDATE_RET( A != NULL );
1852 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1855 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001858 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001859 /*
1860 * Avoid dynamic memory allocations for constant-size T2.
1861 *
1862 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1863 * so nobody increase the size of the MPI and we're safe to use an on-stack
1864 * buffer.
1865 */
Alexander K35d6d462019-10-31 14:46:45 +03001866 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001867 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1868 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001871 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1873 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 return( 0 );
1875 }
1876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1878 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001879 X.s = Y.s = 1;
1880
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001881 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1882 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001883 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001885 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001886 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001887 {
1888 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1890 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891 }
1892 else k = 0;
1893
1894 n = X.n - 1;
1895 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001899 {
1900 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904
1905 for( i = n; i > t ; i-- )
1906 {
1907 if( X.p[i] >= Y.p[t] )
1908 Z.p[i - t - 1] = ~0;
1909 else
1910 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001911 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1912 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 }
1914
Alexander K35d6d462019-10-31 14:46:45 +03001915 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1916 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1917 T2.p[2] = X.p[i];
1918
Paul Bakker5121ce52009-01-03 21:22:43 +00001919 Z.p[i - t - 1]++;
1920 do
1921 {
1922 Z.p[i - t - 1]--;
1923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001925 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1932 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1933 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001934
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001935 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001936 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1938 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1939 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 Z.p[i - t - 1]--;
1941 }
1942 }
1943
1944 if( Q != NULL )
1945 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 Q->s = A->s * B->s;
1948 }
1949
1950 if( R != NULL )
1951 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001953 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001957 R->s = 1;
1958 }
1959
1960cleanup:
1961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001963 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001964 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001965
1966 return( ret );
1967}
1968
1969/*
1970 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001971 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001972int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1973 const mbedtls_mpi *A,
1974 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001975{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 mbedtls_mpi _B;
1977 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001978 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
1980 p[0] = ( b < 0 ) ? -b : b;
1981 _B.s = ( b < 0 ) ? -1 : 1;
1982 _B.n = 1;
1983 _B.p = p;
1984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001986}
1987
1988/*
1989 * Modulo: R = A mod B
1990 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001992{
Janos Follath24eed8d2019-11-22 13:21:35 +00001993 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001994 MPI_VALIDATE_RET( R != NULL );
1995 MPI_VALIDATE_RET( A != NULL );
1996 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001997
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001998 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1999 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002003 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
2004 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002005
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
2007 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
2009cleanup:
2010
2011 return( ret );
2012}
2013
2014/*
2015 * Modulo: r = A mod b
2016 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00002018{
Paul Bakker23986e52011-04-24 08:57:21 +00002019 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00002021 MPI_VALIDATE_RET( r != NULL );
2022 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002023
2024 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
2027 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002029
2030 /*
2031 * handle trivial cases
2032 */
2033 if( b == 1 )
2034 {
2035 *r = 0;
2036 return( 0 );
2037 }
2038
2039 if( b == 2 )
2040 {
2041 *r = A->p[0] & 1;
2042 return( 0 );
2043 }
2044
2045 /*
2046 * general case
2047 */
Paul Bakker23986e52011-04-24 08:57:21 +00002048 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 {
Paul Bakker23986e52011-04-24 08:57:21 +00002050 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00002051 y = ( y << biH ) | ( x >> biH );
2052 z = y / b;
2053 y -= z * b;
2054
2055 x <<= biH;
2056 y = ( y << biH ) | ( x >> biH );
2057 z = y / b;
2058 y -= z * b;
2059 }
2060
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002061 /*
2062 * If A is negative, then the current y represents a negative value.
2063 * Flipping it to the positive side.
2064 */
2065 if( A->s < 0 && y != 0 )
2066 y = b - y;
2067
Paul Bakker5121ce52009-01-03 21:22:43 +00002068 *r = y;
2069
2070 return( 0 );
2071}
2072
2073/*
2074 * Fast Montgomery initialization (thanks to Tom St Denis)
2075 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002077{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002079 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002080
2081 x = m0;
2082 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002083
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002084 for( i = biL; i >= 8; i /= 2 )
2085 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
2087 *mm = ~x + 1;
2088}
2089
Gilles Peskine2a82f722020-06-04 15:00:49 +02002090/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2091 *
2092 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002093 * It must have at least as many limbs as N
2094 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002095 * On successful completion, A contains the result of
2096 * the multiplication A * B * R^-1 mod N where
2097 * R = (2^ciL)^n.
2098 * \param[in] B One of the numbers to multiply.
2099 * It must be nonzero and must not have more limbs than N
2100 * (B->n <= N->n).
2101 * \param[in] N The modulo. N must be odd.
2102 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2103 * This is -N^-1 mod 2^ciL.
2104 * \param[in,out] T A bignum for temporary storage.
2105 * It must be at least twice the limb size of N plus 2
2106 * (T->n >= 2 * (N->n + 1)).
2107 * Its initial content is unused and
2108 * its final content is indeterminate.
2109 * Note that unlike the usual convention in the library
2110 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002111 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002112static 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 +02002113 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002114{
Paul Bakker23986e52011-04-24 08:57:21 +00002115 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002116 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
2118 memset( T->p, 0, T->n * ciL );
2119
2120 d = T->p;
2121 n = N->n;
2122 m = ( B->n < n ) ? B->n : n;
2123
2124 for( i = 0; i < n; i++ )
2125 {
2126 /*
2127 * T = (T + u0*B + u1*N) / 2^biL
2128 */
2129 u0 = A->p[i];
2130 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2131
2132 mpi_mul_hlp( m, B->p, d, u0 );
2133 mpi_mul_hlp( n, N->p, d, u1 );
2134
2135 *d++ = u0; d[n + 1] = 0;
2136 }
2137
Gilles Peskine221626f2020-06-08 22:37:50 +02002138 /* At this point, d is either the desired result or the desired result
2139 * plus N. We now potentially subtract N, avoiding leaking whether the
2140 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Gilles Peskine221626f2020-06-08 22:37:50 +02002142 /* Copy the n least significant limbs of d to A, so that
2143 * A = d if d < N (recall that N has n limbs). */
2144 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002145 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002146 * do the calculation without using conditional tests. */
2147 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002148 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02002149 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02002150 /* If d0 < N then d < (2^biL)^n
2151 * so d[n] == 0 and we want to keep A as it is.
2152 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2153 * so d[n] == 1 and we want to set A to the result of the subtraction
2154 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2155 * This exactly corresponds to a conditional assignment. */
2156 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002157}
2158
2159/*
2160 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002161 *
2162 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002163 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002164static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2165 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002166{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 mbedtls_mpi_uint z = 1;
2168 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002169
Paul Bakker8ddb6452013-02-27 14:56:33 +01002170 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002171 U.p = &z;
2172
Gilles Peskine4e91d472020-06-04 20:55:15 +02002173 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002174}
2175
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002176/*
2177 * Constant-flow boolean "equal" comparison:
2178 * return x == y
2179 *
2180 * This function can be used to write constant-time code by replacing branches
2181 * with bit operations - it can be used in conjunction with
2182 * mbedtls_ssl_cf_mask_from_bit().
2183 *
2184 * This function is implemented without using comparison operators, as those
2185 * might be translated to branches by some compilers on some platforms.
2186 */
2187static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2188{
2189 /* diff = 0 if x == y, non-zero otherwise */
2190 const size_t diff = x ^ y;
2191
2192 /* MSVC has a warning about unary minus on unsigned integer types,
2193 * but this is well-defined and precisely what we want to do here. */
2194#if defined(_MSC_VER)
2195#pragma warning( push )
2196#pragma warning( disable : 4146 )
2197#endif
2198
2199 /* diff_msb's most significant bit is equal to x != y */
2200 const size_t diff_msb = ( diff | -diff );
2201
2202#if defined(_MSC_VER)
2203#pragma warning( pop )
2204#endif
2205
2206 /* diff1 = (x != y) ? 1 : 0 */
2207 const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2208
2209 return( 1 ^ diff1 );
2210}
2211
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002212/**
2213 * Select an MPI from a table without leaking the index.
2214 *
2215 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2216 * reads the entire table in order to avoid leaking the value of idx to an
2217 * attacker able to observe memory access patterns.
2218 *
2219 * \param[out] R Where to write the selected MPI.
2220 * \param[in] T The table to read from.
2221 * \param[in] T_size The number of elements in the table.
2222 * \param[in] idx The index of the element to select;
2223 * this must satisfy 0 <= idx < T_size.
2224 *
2225 * \return \c 0 on success, or a negative error code.
2226 */
2227static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2228{
2229 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2230
2231 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002232 {
2233 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
2234 mbedtls_mpi_cf_bool_eq( i, idx ) ) );
2235 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002236
2237cleanup:
2238 return( ret );
2239}
2240
Paul Bakker5121ce52009-01-03 21:22:43 +00002241/*
2242 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2243 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002244int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2245 const mbedtls_mpi *E, const mbedtls_mpi *N,
2246 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002247{
Janos Follath24eed8d2019-11-22 13:21:35 +00002248 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002249 size_t wbits, wsize, one = 1;
2250 size_t i, j, nblimbs;
2251 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002253 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002254 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002255
Hanno Becker73d7d792018-12-11 10:35:51 +00002256 MPI_VALIDATE_RET( X != NULL );
2257 MPI_VALIDATE_RET( A != NULL );
2258 MPI_VALIDATE_RET( E != NULL );
2259 MPI_VALIDATE_RET( N != NULL );
2260
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002261 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2265 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002266
Chris Jones9246d042020-11-25 15:12:39 +00002267 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2268 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2269 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2270
Paul Bakkerf6198c12012-05-16 08:02:29 +00002271 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 * Init temps and window size
2273 */
2274 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2276 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002277 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 memset( W, 0, sizeof( W ) );
2279
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002280 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
2282 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2283 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2284
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002285#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2287 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002288#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002289
Paul Bakker5121ce52009-01-03 21:22:43 +00002290 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2292 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002294
2295 /*
Paul Bakker50546922012-05-19 08:40:49 +00002296 * Compensate for negative A (and correct at the end)
2297 */
2298 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002299 if( neg )
2300 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002302 Apos.s = 1;
2303 A = &Apos;
2304 }
2305
2306 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002307 * If 1st call, pre-compute R^2 mod N
2308 */
2309 if( _RR == NULL || _RR->p == NULL )
2310 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2312 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2313 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002314
2315 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 }
2318 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
2321 /*
2322 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2323 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2325 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002326 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002328
Gilles Peskine4e91d472020-06-04 20:55:15 +02002329 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002330
2331 /*
2332 * X = R^2 * R^-1 mod N = R mod N
2333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002335 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
2337 if( wsize > 1 )
2338 {
2339 /*
2340 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2341 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002342 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2345 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
2347 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002348 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002349
Paul Bakker5121ce52009-01-03 21:22:43 +00002350 /*
2351 * W[i] = W[i - 1] * W[1]
2352 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002353 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002354 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2356 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Gilles Peskine4e91d472020-06-04 20:55:15 +02002358 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002359 }
2360 }
2361
2362 nblimbs = E->n;
2363 bufsize = 0;
2364 nbits = 0;
2365 wbits = 0;
2366 state = 0;
2367
2368 while( 1 )
2369 {
2370 if( bufsize == 0 )
2371 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002372 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002373 break;
2374
Paul Bakker0d7702c2013-10-29 16:18:35 +01002375 nblimbs--;
2376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002377 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002378 }
2379
2380 bufsize--;
2381
2382 ei = (E->p[nblimbs] >> bufsize) & 1;
2383
2384 /*
2385 * skip leading 0s
2386 */
2387 if( ei == 0 && state == 0 )
2388 continue;
2389
2390 if( ei == 0 && state == 1 )
2391 {
2392 /*
2393 * out of window, square X
2394 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002395 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 continue;
2397 }
2398
2399 /*
2400 * add ei to current window
2401 */
2402 state = 2;
2403
2404 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002405 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002406
2407 if( nbits == wsize )
2408 {
2409 /*
2410 * X = X^wsize R^-1 mod N
2411 */
2412 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002413 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002414
2415 /*
2416 * X = X * W[wbits] R^-1 mod N
2417 */
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002418 MBEDTLS_MPI_CHK( mpi_select( &WW, W, 1 << wsize, wbits ) );
2419 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002420
2421 state--;
2422 nbits = 0;
2423 wbits = 0;
2424 }
2425 }
2426
2427 /*
2428 * process the remaining bits
2429 */
2430 for( i = 0; i < nbits; i++ )
2431 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002432 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
2434 wbits <<= 1;
2435
Paul Bakker66d5d072014-06-17 16:39:18 +02002436 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002437 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002438 }
2439
2440 /*
2441 * X = A^E * R * R^-1 mod N = A^E mod N
2442 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002443 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002444
Hanno Beckera4af1c42017-04-18 09:07:45 +01002445 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002446 {
2447 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002449 }
2450
Paul Bakker5121ce52009-01-03 21:22:43 +00002451cleanup:
2452
Paul Bakker66d5d072014-06-17 16:39:18 +02002453 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002454 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002457 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002458
Paul Bakker75a28602014-03-31 12:08:17 +02002459 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002460 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002461
2462 return( ret );
2463}
2464
Paul Bakker5121ce52009-01-03 21:22:43 +00002465/*
2466 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2467 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002469{
Janos Follath24eed8d2019-11-22 13:21:35 +00002470 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002471 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002472 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002473
Hanno Becker73d7d792018-12-11 10:35:51 +00002474 MPI_VALIDATE_RET( G != NULL );
2475 MPI_VALIDATE_RET( A != NULL );
2476 MPI_VALIDATE_RET( B != NULL );
2477
Alexander Ke8ad49f2019-08-16 16:16:07 +03002478 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2481 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 lz = mbedtls_mpi_lsb( &TA );
2484 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002485
Paul Bakker66d5d072014-06-17 16:39:18 +02002486 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002487 lz = lzt;
2488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2490 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002491
Paul Bakker5121ce52009-01-03 21:22:43 +00002492 TA.s = TB.s = 1;
2493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002495 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2497 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002500 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2502 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002503 }
2504 else
2505 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2507 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002508 }
2509 }
2510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2512 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513
2514cleanup:
2515
Alexander Ke8ad49f2019-08-16 16:16:07 +03002516 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002517
2518 return( ret );
2519}
2520
Gilles Peskine8f454702021-04-01 15:57:18 +02002521/* Fill X with n_bytes random bytes.
2522 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002523 * The ordering of the bytes returned from the RNG is suitable for
2524 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002525 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002526 * n_bytes must not be 0.
2527 */
2528static int mpi_fill_random_internal(
2529 mbedtls_mpi *X, size_t n_bytes,
2530 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2531{
2532 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2533 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2534 const size_t overhead = ( limbs * ciL ) - n_bytes;
2535
2536 if( X->n < limbs )
2537 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine8f454702021-04-01 15:57:18 +02002538
Gilles Peskinea16001e2021-04-13 21:55:35 +02002539 memset( X->p, 0, overhead );
2540 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine8f454702021-04-01 15:57:18 +02002541 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2542 mpi_bigendian_to_host( X->p, limbs );
2543
2544cleanup:
2545 return( ret );
2546}
2547
Paul Bakker33dc46b2014-04-30 16:11:39 +02002548/*
2549 * Fill X with size bytes of random.
2550 *
2551 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002552 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002553 * deterministic, eg for tests).
2554 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002555int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002556 int (*f_rng)(void *, unsigned char *, size_t),
2557 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002558{
Janos Follath24eed8d2019-11-22 13:21:35 +00002559 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002560 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002561
Hanno Becker8ce11a32018-12-19 16:18:52 +00002562 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002563 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002564
Hanno Beckerda1655a2017-10-18 14:21:44 +01002565 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002566 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002567 if( size == 0 )
2568 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002569
Gilles Peskine8f454702021-04-01 15:57:18 +02002570 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002571
2572cleanup:
2573 return( ret );
2574}
2575
Gilles Peskine4699fa42021-03-29 22:02:55 +02002576int mbedtls_mpi_random( mbedtls_mpi *X,
2577 mbedtls_mpi_sint min,
2578 const mbedtls_mpi *N,
2579 int (*f_rng)(void *, unsigned char *, size_t),
2580 void *p_rng )
2581{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002582 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002583 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002584 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002585 size_t n_bits = mbedtls_mpi_bitlen( N );
2586 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002587 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002588
Gilles Peskine9312ba52021-03-29 22:14:51 +02002589 if( min < 0 )
2590 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2591 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2592 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2593
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002594 /*
2595 * When min == 0, each try has at worst a probability 1/2 of failing
2596 * (the msb has a probability 1/2 of being 0, and then the result will
2597 * be < N), so after 30 tries failure probability is a most 2**(-30).
2598 *
2599 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002600 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002601 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002602 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002603 * a probability of failing that is almost 1/2.
2604 *
2605 * The probabilities are almost the same if min is nonzero but negligible
2606 * compared to N. This is always the case when N is crypto-sized, but
2607 * it's convenient to support small N for testing purposes. When N
2608 * is small, use a higher repeat count, otherwise the probability of
2609 * failure is macroscopic.
2610 */
Gilles Peskine11779072021-06-02 21:18:59 +02002611 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002612
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002613 mbedtls_mpi_init( &lower_bound );
2614
Gilles Peskine8f454702021-04-01 15:57:18 +02002615 /* Ensure that target MPI has exactly the same number of limbs
2616 * as the upper bound, even if the upper bound has leading zeros.
2617 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002618 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002619 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2620 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002621
Gilles Peskine4699fa42021-03-29 22:02:55 +02002622 /*
2623 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2624 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2625 * - use the same byte ordering;
2626 * - keep the leftmost n_bits bits of the generated octet string;
2627 * - try until result is in the desired range.
2628 * This also avoids any bias, which is especially important for ECDSA.
2629 */
2630 do
2631 {
Gilles Peskine8f454702021-04-01 15:57:18 +02002632 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002633 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2634
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002635 if( --count == 0 )
Gilles Peskine4699fa42021-03-29 22:02:55 +02002636 {
2637 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2638 goto cleanup;
2639 }
2640
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002641 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2642 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002643 }
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002644 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002645
2646cleanup:
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002647 mbedtls_mpi_free( &lower_bound );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002648 return( ret );
2649}
2650
Paul Bakker5121ce52009-01-03 21:22:43 +00002651/*
2652 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002655{
Janos Follath24eed8d2019-11-22 13:21:35 +00002656 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002658 MPI_VALIDATE_RET( X != NULL );
2659 MPI_VALIDATE_RET( A != NULL );
2660 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
Hanno Becker4bcb4912017-04-18 15:49:39 +01002662 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002663 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2666 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2667 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002672 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002674 goto cleanup;
2675 }
2676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2678 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2679 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2680 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2683 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2684 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2685 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002686
2687 do
2688 {
2689 while( ( TU.p[0] & 1 ) == 0 )
2690 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002692
2693 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2694 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2696 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002697 }
2698
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002699 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2700 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002701 }
2702
2703 while( ( TV.p[0] & 1 ) == 0 )
2704 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002705 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002706
2707 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2708 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002709 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2710 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002711 }
2712
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002713 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2714 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002715 }
2716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002717 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002718 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002719 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2720 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2721 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 }
2723 else
2724 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2726 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2727 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002728 }
2729 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002732 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2733 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002735 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2736 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002738 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002739
2740cleanup:
2741
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002742 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2743 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2744 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002745
2746 return( ret );
2747}
2748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002749#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002750
Paul Bakker5121ce52009-01-03 21:22:43 +00002751static const int small_prime[] =
2752{
2753 3, 5, 7, 11, 13, 17, 19, 23,
2754 29, 31, 37, 41, 43, 47, 53, 59,
2755 61, 67, 71, 73, 79, 83, 89, 97,
2756 101, 103, 107, 109, 113, 127, 131, 137,
2757 139, 149, 151, 157, 163, 167, 173, 179,
2758 181, 191, 193, 197, 199, 211, 223, 227,
2759 229, 233, 239, 241, 251, 257, 263, 269,
2760 271, 277, 281, 283, 293, 307, 311, 313,
2761 317, 331, 337, 347, 349, 353, 359, 367,
2762 373, 379, 383, 389, 397, 401, 409, 419,
2763 421, 431, 433, 439, 443, 449, 457, 461,
2764 463, 467, 479, 487, 491, 499, 503, 509,
2765 521, 523, 541, 547, 557, 563, 569, 571,
2766 577, 587, 593, 599, 601, 607, 613, 617,
2767 619, 631, 641, 643, 647, 653, 659, 661,
2768 673, 677, 683, 691, 701, 709, 719, 727,
2769 733, 739, 743, 751, 757, 761, 769, 773,
2770 787, 797, 809, 811, 821, 823, 827, 829,
2771 839, 853, 857, 859, 863, 877, 881, 883,
2772 887, 907, 911, 919, 929, 937, 941, 947,
2773 953, 967, 971, 977, 983, 991, 997, -103
2774};
2775
2776/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002777 * Small divisors test (X must be positive)
2778 *
2779 * Return values:
2780 * 0: no small factor (possible prime, more tests needed)
2781 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002782 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002783 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002784 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002786{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002787 int ret = 0;
2788 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002790
Paul Bakker5121ce52009-01-03 21:22:43 +00002791 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002792 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002793
2794 for( i = 0; small_prime[i] > 0; i++ )
2795 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002796 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002797 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002799 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002800
2801 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002802 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002803 }
2804
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002805cleanup:
2806 return( ret );
2807}
2808
2809/*
2810 * Miller-Rabin pseudo-primality test (HAC 4.24)
2811 */
Janos Follathda31fa12018-09-03 14:45:23 +01002812static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002813 int (*f_rng)(void *, unsigned char *, size_t),
2814 void *p_rng )
2815{
Pascal Junodb99183d2015-03-11 16:49:45 +01002816 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002817 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002818 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002819
Hanno Becker8ce11a32018-12-19 16:18:52 +00002820 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002821 MPI_VALIDATE_RET( f_rng != NULL );
2822
2823 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2824 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002826
Paul Bakker5121ce52009-01-03 21:22:43 +00002827 /*
2828 * W = |X| - 1
2829 * R = W >> lsb( W )
2830 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002831 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2832 s = mbedtls_mpi_lsb( &W );
2833 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2834 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002835
Janos Follathda31fa12018-09-03 14:45:23 +01002836 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002837 {
2838 /*
2839 * pick a random A, 1 < A < |X| - 1
2840 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002841 count = 0;
2842 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002843 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002844
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002845 j = mbedtls_mpi_bitlen( &A );
2846 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002847 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002848 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002849 }
2850
2851 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002852 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2853 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002854 }
2855
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002856 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2857 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002858
2859 /*
2860 * A = A^R mod |X|
2861 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002862 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002864 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2865 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002866 continue;
2867
2868 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002869 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002870 {
2871 /*
2872 * A = A * A mod |X|
2873 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002874 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2875 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002877 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002878 break;
2879
2880 j++;
2881 }
2882
2883 /*
2884 * not prime if A != |X| - 1 or A == 1
2885 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002886 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2887 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002888 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002889 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002890 break;
2891 }
2892 }
2893
2894cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002895 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2896 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002897 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002898
2899 return( ret );
2900}
2901
2902/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002903 * Pseudo-primality test: small factors, then Miller-Rabin
2904 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002905int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2906 int (*f_rng)(void *, unsigned char *, size_t),
2907 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002908{
Janos Follath24eed8d2019-11-22 13:21:35 +00002909 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002910 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002911 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002912 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002913
2914 XX.s = 1;
2915 XX.n = X->n;
2916 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002917
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002918 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2919 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2920 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002922 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002923 return( 0 );
2924
2925 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2926 {
2927 if( ret == 1 )
2928 return( 0 );
2929
2930 return( ret );
2931 }
2932
Janos Follathda31fa12018-09-03 14:45:23 +01002933 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002934}
2935
Janos Follatha0b67c22018-09-18 14:48:23 +01002936#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002937/*
2938 * Pseudo-primality test, error probability 2^-80
2939 */
2940int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2941 int (*f_rng)(void *, unsigned char *, size_t),
2942 void *p_rng )
2943{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002944 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002945 MPI_VALIDATE_RET( f_rng != NULL );
2946
Janos Follatha0b67c22018-09-18 14:48:23 +01002947 /*
2948 * In the past our key generation aimed for an error rate of at most
2949 * 2^-80. Since this function is deprecated, aim for the same certainty
2950 * here as well.
2951 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002952 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002953}
Janos Follatha0b67c22018-09-18 14:48:23 +01002954#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002955
2956/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002957 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002958 *
Janos Follathf301d232018-08-14 13:34:01 +01002959 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2960 * be either 1024 bits or 1536 bits long, and flags must contain
2961 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002962 */
Janos Follath7c025a92018-08-14 11:08:41 +01002963int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002964 int (*f_rng)(void *, unsigned char *, size_t),
2965 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002966{
Jethro Beekman66689272018-02-14 19:24:10 -08002967#ifdef MBEDTLS_HAVE_INT64
2968// ceil(2^63.5)
2969#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2970#else
2971// ceil(2^31.5)
2972#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2973#endif
2974 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002975 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002976 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002977 mbedtls_mpi_uint r;
2978 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002979
Hanno Becker8ce11a32018-12-19 16:18:52 +00002980 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002981 MPI_VALIDATE_RET( f_rng != NULL );
2982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002983 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2984 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002985
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002986 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002987
2988 n = BITS_TO_LIMBS( nbits );
2989
Janos Follathda31fa12018-09-03 14:45:23 +01002990 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2991 {
2992 /*
2993 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2994 */
2995 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2996 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2997 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2998 }
2999 else
3000 {
3001 /*
3002 * 2^-100 error probability, number of rounds computed based on HAC,
3003 * fact 4.48
3004 */
3005 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
3006 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
3007 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
3008 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
3009 }
3010
Jethro Beekman66689272018-02-14 19:24:10 -08003011 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003012 {
Jethro Beekman66689272018-02-14 19:24:10 -08003013 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
3014 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
3015 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
3016
3017 k = n * biL;
3018 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
3019 X->p[0] |= 1;
3020
Janos Follath7c025a92018-08-14 11:08:41 +01003021 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003022 {
Janos Follatha0b67c22018-09-18 14:48:23 +01003023 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08003024
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003025 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00003026 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003027 }
Jethro Beekman66689272018-02-14 19:24:10 -08003028 else
Paul Bakker5121ce52009-01-03 21:22:43 +00003029 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003030 /*
Jethro Beekman66689272018-02-14 19:24:10 -08003031 * An necessary condition for Y and X = 2Y + 1 to be prime
3032 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
3033 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01003034 */
Jethro Beekman66689272018-02-14 19:24:10 -08003035
3036 X->p[0] |= 2;
3037
3038 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
3039 if( r == 0 )
3040 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
3041 else if( r == 1 )
3042 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
3043
3044 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
3045 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
3046 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
3047
3048 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003049 {
Jethro Beekman66689272018-02-14 19:24:10 -08003050 /*
3051 * First, check small factors for X and Y
3052 * before doing Miller-Rabin on any of them
3053 */
3054 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
3055 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003056 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003057 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003058 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003059 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08003060 goto cleanup;
3061
3062 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
3063 goto cleanup;
3064
3065 /*
3066 * Next candidates. We want to preserve Y = (X-1) / 2 and
3067 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3068 * so up Y by 6 and X by 12.
3069 */
3070 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
3071 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003072 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003073 }
3074 }
3075
3076cleanup:
3077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003078 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00003079
3080 return( ret );
3081}
3082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003083#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003085#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003086
Paul Bakker23986e52011-04-24 08:57:21 +00003087#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003088
3089static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3090{
3091 { 693, 609, 21 },
3092 { 1764, 868, 28 },
3093 { 768454923, 542167814, 1 }
3094};
3095
Paul Bakker5121ce52009-01-03 21:22:43 +00003096/*
3097 * Checkup routine
3098 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003099int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00003100{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003101 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003102 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003104 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
3105 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003107 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003108 "EFE021C2645FD1DC586E69184AF4A31E" \
3109 "D5F53E93B5F123FA41680867BA110131" \
3110 "944FE7952E2517337780CB0DB80E61AA" \
3111 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003113 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003114 "B2E7EFD37075B9F03FF989C7C5051C20" \
3115 "34D2A323810251127E7BF8625A4F49A5" \
3116 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3117 "5B5C25763222FEFCCFC38B832366C29E" ) );
3118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003119 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003120 "0066A198186C18C10B2F5ED9B522752A" \
3121 "9830B69916E535C8F047518A889A43A5" \
3122 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003124 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003126 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003127 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3128 "9E857EA95A03512E2BAE7391688D264A" \
3129 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3130 "8001B72E848A38CAE1C65F78E56ABDEF" \
3131 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3132 "ECF677152EF804370C1A305CAF3B5BF1" \
3133 "30879B56C61DE584A0F53A2447A51E" ) );
3134
3135 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003136 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003138 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003139 {
3140 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003141 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003142
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003143 ret = 1;
3144 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003145 }
3146
3147 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003148 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003150 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &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 "256567336059E52CAE22925474705F39A94" ) );
3154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003155 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003156 "6613F26162223DF488E9CD48CC132C7A" \
3157 "0AC93C701B001B092E4E5B9F73BCD27B" \
3158 "9EE50D0657C77F374E903CDFA4C642" ) );
3159
3160 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003161 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003163 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3164 mbedtls_mpi_cmp_mpi( &Y, &V ) != 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_exp_mod( &X, &A, &E, &N, NULL ) );
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 "36E139AEA55215609D2816998ED020BB" \
3180 "BD96C37890F65171D948E9BC7CBAA4D9" \
3181 "325D24D6A3C12710F10A09FA08AB87" ) );
3182
3183 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003184 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003186 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003187 {
3188 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003189 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003190
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003191 ret = 1;
3192 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003193 }
3194
3195 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003196 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003198 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003200 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003201 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3202 "C3DBA76456363A10869622EAC2DD84EC" \
3203 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3204
3205 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003206 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003208 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003209 {
3210 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003211 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003212
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003213 ret = 1;
3214 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003215 }
3216
3217 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003218 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003219
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003220 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003221 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003222
Paul Bakker66d5d072014-06-17 16:39:18 +02003223 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003224 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003225 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3226 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003228 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003230 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003231 {
3232 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003233 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003234
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003235 ret = 1;
3236 goto cleanup;
3237 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003238 }
3239
3240 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003241 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003242
Paul Bakker5121ce52009-01-03 21:22:43 +00003243cleanup:
3244
3245 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003246 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003248 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3249 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003250
3251 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003252 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003253
3254 return( ret );
3255}
3256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003257#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003259#endif /* MBEDTLS_BIGNUM_C */