blob: b3e2755254651b136aba1620fabfe52123cc8d7d [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
Simon Butcher15b15d12015-11-26 19:35:03 +000019
Paul Bakker5121ce52009-01-03 21:22:43 +000020/*
Simon Butcher15b15d12015-11-26 19:35:03 +000021 * The following sources were referenced in the design of this Multi-precision
22 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000023 *
Simon Butcher15b15d12015-11-26 19:35:03 +000024 * [1] Handbook of Applied Cryptography - 1997
25 * Menezes, van Oorschot and Vanstone
26 *
27 * [2] Multi-Precision Math
28 * Tom St Denis
29 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30 *
31 * [3] GNU Multi-Precision Arithmetic Library
32 * https://gmplib.org/manual/index.html
33 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000034 */
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Gilles Peskinedb09ef62020-06-03 01:43:33 +020036#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/bignum.h"
41#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050042#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000043#include "mbedtls/error.h"
gabor-mezei-arm96584dd2021-09-27 12:15:19 +020044#include "constant_time.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Rich Evans00ab4702015-02-06 13:43:58 +000046#include <string.h>
47
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020050#else
Rich Evans00ab4702015-02-06 13:43:58 +000051#include <stdio.h>
52#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020054#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020056#endif
57
Hanno Becker73d7d792018-12-11 10:35:51 +000058#define MPI_VALIDATE_RET( cond ) \
59 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
60#define MPI_VALIDATE( cond ) \
61 MBEDTLS_INTERNAL_VALIDATE( cond )
62
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000064#define biL (ciL << 3) /* bits in limb */
65#define biH (ciL << 2) /* half limb size */
66
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010067#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
68
Paul Bakker5121ce52009-01-03 21:22:43 +000069/*
70 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020071 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000072 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020073#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
74#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000075
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050076/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050077static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
78{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050079 mbedtls_platform_zeroize( v, ciL * n );
80}
81
Paul Bakker5121ce52009-01-03 21:22:43 +000082/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000083 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000086{
Hanno Becker73d7d792018-12-11 10:35:51 +000087 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000088
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 X->s = 1;
90 X->n = 0;
91 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000092}
93
94/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000095 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000096 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000098{
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 if( X == NULL )
100 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000101
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000103 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200104 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 }
107
Paul Bakker6c591fa2011-05-05 11:49:20 +0000108 X->s = 1;
109 X->n = 0;
110 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000111}
112
113/*
114 * Enlarge to the specified number of limbs
115 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000117{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000119 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200122 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000123
Paul Bakker5121ce52009-01-03 21:22:43 +0000124 if( X->n < nblimbs )
125 {
Simon Butcher29176892016-05-20 00:19:09 +0100126 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200127 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000128
Paul Bakker5121ce52009-01-03 21:22:43 +0000129 if( X->p != NULL )
130 {
131 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200132 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 }
135
136 X->n = nblimbs;
137 X->p = p;
138 }
139
140 return( 0 );
141}
142
143/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100144 * Resize down as much as possible,
145 * while keeping at least the specified number of limbs
146 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000151 MPI_VALIDATE_RET( X != NULL );
152
153 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
154 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100156 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100157 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100159 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100160
161 for( i = X->n - 1; i > 0; i-- )
162 if( X->p[i] != 0 )
163 break;
164 i++;
165
166 if( i < nblimbs )
167 i = nblimbs;
168
Simon Butcher29176892016-05-20 00:19:09 +0100169 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200170 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100172 if( X->p != NULL )
173 {
174 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200175 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100177 }
178
179 X->n = i;
180 X->p = p;
181
182 return( 0 );
183}
184
Gilles Peskine3130ce22021-06-02 22:17:52 +0200185/* Resize X to have exactly n limbs and set it to 0. */
186static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
187{
188 if( limbs == 0 )
189 {
190 mbedtls_mpi_free( X );
191 return( 0 );
192 }
193 else if( X->n == limbs )
194 {
195 memset( X->p, 0, limbs * ciL );
196 X->s = 1;
197 return( 0 );
198 }
199 else
200 {
201 mbedtls_mpi_free( X );
202 return( mbedtls_mpi_grow( X, limbs ) );
203 }
204}
205
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100206/*
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200207 * Copy the contents of Y into X.
208 *
209 * This function is not constant-time. Leading zeros in Y may be removed.
210 *
211 * Ensure that X does not shrink. This is not guaranteed by the public API,
212 * but some code in the bignum module relies on this property, for example
213 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000214 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000216{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100217 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000218 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000219 MPI_VALIDATE_RET( X != NULL );
220 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221
222 if( X == Y )
223 return( 0 );
224
Gilles Peskinedb420622020-01-20 21:12:50 +0100225 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200226 {
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200227 if( X->n != 0 )
228 {
229 X->s = 1;
230 memset( X->p, 0, X->n * ciL );
231 }
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200232 return( 0 );
233 }
234
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 for( i = Y->n - 1; i > 0; i-- )
236 if( Y->p[i] != 0 )
237 break;
238 i++;
239
240 X->s = Y->s;
241
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100242 if( X->n < i )
243 {
244 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
245 }
246 else
247 {
248 memset( X->p + i, 0, ( X->n - i ) * ciL );
249 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000250
Paul Bakker5121ce52009-01-03 21:22:43 +0000251 memcpy( X->p, Y->p, i * ciL );
252
253cleanup:
254
255 return( ret );
256}
257
258/*
259 * Swap the contents of X and Y
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000262{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000264 MPI_VALIDATE( X != NULL );
265 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 memcpy( &T, X, sizeof( mbedtls_mpi ) );
268 memcpy( X, Y, sizeof( mbedtls_mpi ) );
269 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000270}
271
272/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100273 * Conditionally swap X and Y, without leaking information
274 * about whether the swap was made or not.
275 * Here it is not ok to simply swap the pointers, which whould lead to
276 * different memory access patterns when X and Y are used afterwards.
277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100279{
280 int ret, s;
281 size_t i;
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200282 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200290 /* MSVC has a warning about unary minus on unsigned integer types,
291 * but this is well-defined and precisely what we want to do here. */
292#if defined(_MSC_VER)
293#pragma warning( push )
294#pragma warning( disable : 4146 )
295#endif
296
Pascal Junodb99183d2015-03-11 16:49:45 +0100297 /* make sure swap is 0 or 1 in a time-constant manner */
Manuel Pégourié-Gonnardc94b6b02021-06-17 13:25:03 +0200298 swap = (swap | (unsigned char)-swap) >> (sizeof( swap ) * 8 - 1);
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200299 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200300 limb_mask = -swap;
301
302#if defined(_MSC_VER)
303#pragma warning( pop )
304#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
307 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100308
309 s = X->s;
gabor-mezei-arme41e3e82021-09-28 16:14:47 +0200310 X->s = mbedtls_cf_cond_select_sign( X->s, Y->s, swap );
311 Y->s = mbedtls_cf_cond_select_sign( Y->s, s, swap );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100312
313
314 for( i = 0; i < X->n; i++ )
315 {
316 tmp = X->p[i];
Manuel Pégourié-Gonnard464fe6a2021-06-03 10:54:01 +0200317 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
318 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100319 }
320
321cleanup:
322 return( ret );
323}
324
325/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000326 * Set value from integer
327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000329{
Janos Follath24eed8d2019-11-22 13:21:35 +0000330 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000331 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000334 memset( X->p, 0, X->n * ciL );
335
336 X->p[0] = ( z < 0 ) ? -z : z;
337 X->s = ( z < 0 ) ? -1 : 1;
338
339cleanup:
340
341 return( ret );
342}
343
344/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000345 * Get a specific bit
346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348{
Hanno Becker73d7d792018-12-11 10:35:51 +0000349 MPI_VALIDATE_RET( X != NULL );
350
Paul Bakker2f5947e2011-05-18 15:47:11 +0000351 if( X->n * biL <= pos )
352 return( 0 );
353
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200354 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000355}
356
Gilles Peskine11cdb052018-11-20 16:47:47 +0100357/* Get a specific byte, without range checks. */
358#define GET_BYTE( X, i ) \
359 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361/*
362 * Set a bit to a specific value of 0 or 1
363 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200364int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365{
366 int ret = 0;
367 size_t off = pos / biL;
368 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000369 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000370
371 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 if( X->n * biL <= pos )
375 {
376 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200377 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000380 }
381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
383 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000384
385cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200386
Paul Bakker2f5947e2011-05-18 15:47:11 +0000387 return( ret );
388}
389
390/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200391 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000392 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000394{
Paul Bakker23986e52011-04-24 08:57:21 +0000395 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000396 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000397
398 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000399 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
401 return( count );
402
403 return( 0 );
404}
405
406/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000407 * Count leading zero bits in a given integer
408 */
409static size_t mbedtls_clz( const mbedtls_mpi_uint x )
410{
411 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100412 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000413
414 for( j = 0; j < biL; j++ )
415 {
416 if( x & mask ) break;
417
418 mask >>= 1;
419 }
420
421 return j;
422}
423
424/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200425 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000426 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200427size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000428{
Paul Bakker23986e52011-04-24 08:57:21 +0000429 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200431 if( X->n == 0 )
432 return( 0 );
433
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 for( i = X->n - 1; i > 0; i-- )
435 if( X->p[i] != 0 )
436 break;
437
Simon Butcher15b15d12015-11-26 19:35:03 +0000438 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
Paul Bakker23986e52011-04-24 08:57:21 +0000440 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000441}
442
443/*
444 * Return the total size in bytes
445 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000447{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200448 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449}
450
451/*
452 * Convert an ASCII character to digit value
453 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000455{
456 *d = 255;
457
458 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
459 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
460 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 if( *d >= (mbedtls_mpi_uint) radix )
463 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
465 return( 0 );
466}
467
468/*
469 * Import from an ASCII string
470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000472{
Janos Follath24eed8d2019-11-22 13:21:35 +0000473 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000474 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200475 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 mbedtls_mpi_uint d;
477 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000478 MPI_VALIDATE_RET( X != NULL );
479 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
481 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000482 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
Gilles Peskined4876132021-06-08 18:32:34 +0200486 if( s[0] == 0 )
487 {
488 mbedtls_mpi_free( X );
489 return( 0 );
490 }
491
Gilles Peskine80f56732021-04-03 18:26:13 +0200492 if( s[0] == '-' )
493 {
494 ++s;
495 sign = -1;
496 }
497
Paul Bakkerff60ee62010-03-16 21:09:09 +0000498 slen = strlen( s );
499
Paul Bakker5121ce52009-01-03 21:22:43 +0000500 if( radix == 16 )
501 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100502 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200503 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
504
Paul Bakkerff60ee62010-03-16 21:09:09 +0000505 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
508 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
Paul Bakker23986e52011-04-24 08:57:21 +0000510 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000511 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200513 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514 }
515 }
516 else
517 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
Paul Bakkerff60ee62010-03-16 21:09:09 +0000520 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000521 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
523 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200524 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525 }
526 }
527
Gilles Peskine80f56732021-04-03 18:26:13 +0200528 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
529 X->s = -1;
530
Paul Bakker5121ce52009-01-03 21:22:43 +0000531cleanup:
532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000534
535 return( ret );
536}
537
538/*
Ron Eldora16fa292018-11-20 14:07:01 +0200539 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000540 */
Ron Eldora16fa292018-11-20 14:07:01 +0200541static int mpi_write_hlp( mbedtls_mpi *X, int radix,
542 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000543{
Janos Follath24eed8d2019-11-22 13:21:35 +0000544 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200546 size_t length = 0;
547 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000548
Ron Eldora16fa292018-11-20 14:07:01 +0200549 do
550 {
551 if( length >= buflen )
552 {
553 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
554 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Ron Eldora16fa292018-11-20 14:07:01 +0200556 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
557 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
558 /*
559 * Write the residue in the current position, as an ASCII character.
560 */
561 if( r < 0xA )
562 *(--p_end) = (char)( '0' + r );
563 else
564 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
Ron Eldora16fa292018-11-20 14:07:01 +0200566 length++;
567 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000568
Ron Eldora16fa292018-11-20 14:07:01 +0200569 memmove( *p, p_end, length );
570 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000571
572cleanup:
573
574 return( ret );
575}
576
577/*
578 * Export into an ASCII string
579 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100580int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
581 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000582{
Paul Bakker23986e52011-04-24 08:57:21 +0000583 int ret = 0;
584 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000585 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000587 MPI_VALIDATE_RET( X != NULL );
588 MPI_VALIDATE_RET( olen != NULL );
589 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000590
591 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000592 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000593
Hanno Becker23cfea02019-02-04 09:45:07 +0000594 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
595 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
596 * `n`. If radix > 4, this might be a strict
597 * overapproximation of the number of
598 * radix-adic digits needed to present `n`. */
599 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
600 * present `n`. */
601
Janos Follath80470622019-03-06 13:43:02 +0000602 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000603 n += 1; /* Compensate for the divisions above, which round down `n`
604 * in case it's not even. */
605 n += 1; /* Potential '-'-sign. */
606 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
607 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100609 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000610 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100611 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 }
614
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100615 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
618 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000619 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000620 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000621 buflen--;
622 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
624 if( radix == 16 )
625 {
Paul Bakker23986e52011-04-24 08:57:21 +0000626 int c;
627 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000628
Paul Bakker23986e52011-04-24 08:57:21 +0000629 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000630 {
Paul Bakker23986e52011-04-24 08:57:21 +0000631 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 {
Paul Bakker23986e52011-04-24 08:57:21 +0000633 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000634
Paul Bakker6c343d72014-07-10 14:36:19 +0200635 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000636 continue;
637
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000638 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000639 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000640 k = 1;
641 }
642 }
643 }
644 else
645 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000647
648 if( T.s == -1 )
649 T.s = 1;
650
Ron Eldora16fa292018-11-20 14:07:01 +0200651 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000652 }
653
654 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100655 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
657cleanup:
658
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000660
661 return( ret );
662}
663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000665/*
666 * Read X from an opened file
667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000669{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000671 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000672 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000673 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000674 * Buffer should have space for (short) label and decimal formatted MPI,
675 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000676 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
Hanno Becker73d7d792018-12-11 10:35:51 +0000679 MPI_VALIDATE_RET( X != NULL );
680 MPI_VALIDATE_RET( fin != NULL );
681
682 if( radix < 2 || radix > 16 )
683 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
684
Paul Bakker5121ce52009-01-03 21:22:43 +0000685 memset( s, 0, sizeof( s ) );
686 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000688
689 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000690 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000692
Hanno Beckerb2034b72017-04-26 11:46:46 +0100693 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
694 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
696 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100697 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000698 if( mpi_get_digit( &d, radix, *p ) != 0 )
699 break;
700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000702}
703
704/*
705 * Write X into an opened file (or stdout if fout == NULL)
706 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000708{
Janos Follath24eed8d2019-11-22 13:21:35 +0000709 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000710 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000711 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000712 * Buffer should have space for (short) label and decimal formatted MPI,
713 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000714 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000716 MPI_VALIDATE_RET( X != NULL );
717
718 if( radix < 2 || radix > 16 )
719 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100721 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000722
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100723 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
725 if( p == NULL ) p = "";
726
727 plen = strlen( p );
728 slen = strlen( s );
729 s[slen++] = '\r';
730 s[slen++] = '\n';
731
732 if( fout != NULL )
733 {
734 if( fwrite( p, 1, plen, fout ) != plen ||
735 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000737 }
738 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000740
741cleanup:
742
743 return( ret );
744}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000746
Hanno Beckerda1655a2017-10-18 14:21:44 +0100747
748/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
749 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000750
751static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
752{
753 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100754 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000755 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100756
757 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
758 {
759 tmp <<= CHAR_BIT;
760 tmp |= (mbedtls_mpi_uint) *x_ptr;
761 }
762
Hanno Beckerf8720072018-11-08 11:53:49 +0000763 return( tmp );
764}
765
766static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
767{
768#if defined(__BYTE_ORDER__)
769
770/* Nothing to do on bigendian systems. */
771#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
772 return( x );
773#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
774
775#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
776
777/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000778#if defined(__GNUC__) && defined(__GNUC_PREREQ)
779#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000780#define have_bswap
781#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000782#endif
783
784#if defined(__clang__) && defined(__has_builtin)
785#if __has_builtin(__builtin_bswap32) && \
786 __has_builtin(__builtin_bswap64)
787#define have_bswap
788#endif
789#endif
790
Hanno Beckerf8720072018-11-08 11:53:49 +0000791#if defined(have_bswap)
792 /* The compiler is hopefully able to statically evaluate this! */
793 switch( sizeof(mbedtls_mpi_uint) )
794 {
795 case 4:
796 return( __builtin_bswap32(x) );
797 case 8:
798 return( __builtin_bswap64(x) );
799 }
800#endif
801#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
802#endif /* __BYTE_ORDER__ */
803
804 /* Fall back to C-based reordering if we don't know the byte order
805 * or we couldn't use a compiler-specific builtin. */
806 return( mpi_uint_bigendian_to_host_c( x ) );
807}
808
Hanno Becker2be8a552018-10-25 12:40:09 +0100809static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100810{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100811 mbedtls_mpi_uint *cur_limb_left;
812 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100813 if( limbs == 0 )
814 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100815
816 /*
817 * Traverse limbs and
818 * - adapt byte-order in each limb
819 * - swap the limbs themselves.
820 * For that, simultaneously traverse the limbs from left to right
821 * and from right to left, as long as the left index is not bigger
822 * than the right index (it's not a problem if limbs is odd and the
823 * indices coincide in the last iteration).
824 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100825 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
826 cur_limb_left <= cur_limb_right;
827 cur_limb_left++, cur_limb_right-- )
828 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000829 mbedtls_mpi_uint tmp;
830 /* Note that if cur_limb_left == cur_limb_right,
831 * this code effectively swaps the bytes only once. */
832 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
833 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
834 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100835 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100836}
837
Paul Bakker5121ce52009-01-03 21:22:43 +0000838/*
Janos Follatha778a942019-02-13 10:28:28 +0000839 * Import X from unsigned binary data, little endian
840 */
841int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
842 const unsigned char *buf, size_t buflen )
843{
Janos Follath24eed8d2019-11-22 13:21:35 +0000844 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000845 size_t i;
846 size_t const limbs = CHARS_TO_LIMBS( buflen );
847
848 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200849 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000850
851 for( i = 0; i < buflen; i++ )
852 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
853
854cleanup:
855
Janos Follath171a7ef2019-02-15 16:17:45 +0000856 /*
857 * This function is also used to import keys. However, wiping the buffers
858 * upon failure is not necessary because failure only can happen before any
859 * input is copied.
860 */
Janos Follatha778a942019-02-13 10:28:28 +0000861 return( ret );
862}
863
864/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000865 * Import X from unsigned binary data, big endian
866 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000868{
Janos Follath24eed8d2019-11-22 13:21:35 +0000869 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100870 size_t const limbs = CHARS_TO_LIMBS( buflen );
871 size_t const overhead = ( limbs * ciL ) - buflen;
872 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000873
Hanno Becker8ce11a32018-12-19 16:18:52 +0000874 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000875 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
876
Hanno Becker073c1992017-10-17 15:17:27 +0100877 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200878 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000879
Gilles Peskine3130ce22021-06-02 22:17:52 +0200880 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000881 * even if buflen is 0. */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200882 if( buflen != 0 )
Hanno Becker0e810b92019-01-03 17:13:11 +0000883 {
884 Xp = (unsigned char*) X->p;
885 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100886
Hanno Becker0e810b92019-01-03 17:13:11 +0000887 mpi_bigendian_to_host( X->p, limbs );
888 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000889
890cleanup:
891
Janos Follath171a7ef2019-02-15 16:17:45 +0000892 /*
893 * This function is also used to import keys. However, wiping the buffers
894 * upon failure is not necessary because failure only can happen before any
895 * input is copied.
896 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000897 return( ret );
898}
899
900/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000901 * Export X into unsigned binary data, little endian
902 */
903int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
904 unsigned char *buf, size_t buflen )
905{
906 size_t stored_bytes = X->n * ciL;
907 size_t bytes_to_copy;
908 size_t i;
909
910 if( stored_bytes < buflen )
911 {
912 bytes_to_copy = stored_bytes;
913 }
914 else
915 {
916 bytes_to_copy = buflen;
917
918 /* The output buffer is smaller than the allocated size of X.
919 * However X may fit if its leading bytes are zero. */
920 for( i = bytes_to_copy; i < stored_bytes; i++ )
921 {
922 if( GET_BYTE( X, i ) != 0 )
923 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
924 }
925 }
926
927 for( i = 0; i < bytes_to_copy; i++ )
928 buf[i] = GET_BYTE( X, i );
929
930 if( stored_bytes < buflen )
931 {
932 /* Write trailing 0 bytes */
933 memset( buf + stored_bytes, 0, buflen - stored_bytes );
934 }
935
936 return( 0 );
937}
938
939/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000940 * Export X into unsigned binary data, big endian
941 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100942int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
943 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000944{
Hanno Becker73d7d792018-12-11 10:35:51 +0000945 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100946 size_t bytes_to_copy;
947 unsigned char *p;
948 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000949
Hanno Becker73d7d792018-12-11 10:35:51 +0000950 MPI_VALIDATE_RET( X != NULL );
951 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
952
953 stored_bytes = X->n * ciL;
954
Gilles Peskine11cdb052018-11-20 16:47:47 +0100955 if( stored_bytes < buflen )
956 {
957 /* There is enough space in the output buffer. Write initial
958 * null bytes and record the position at which to start
959 * writing the significant bytes. In this case, the execution
960 * trace of this function does not depend on the value of the
961 * number. */
962 bytes_to_copy = stored_bytes;
963 p = buf + buflen - stored_bytes;
964 memset( buf, 0, buflen - stored_bytes );
965 }
966 else
967 {
968 /* The output buffer is smaller than the allocated size of X.
969 * However X may fit if its leading bytes are zero. */
970 bytes_to_copy = buflen;
971 p = buf;
972 for( i = bytes_to_copy; i < stored_bytes; i++ )
973 {
974 if( GET_BYTE( X, i ) != 0 )
975 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
976 }
977 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
Gilles Peskine11cdb052018-11-20 16:47:47 +0100979 for( i = 0; i < bytes_to_copy; i++ )
980 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000981
982 return( 0 );
983}
984
985/*
986 * Left-shift: X <<= count
987 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200988int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000989{
Janos Follath24eed8d2019-11-22 13:21:35 +0000990 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000991 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000993 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000994
995 v0 = count / (biL );
996 t1 = count & (biL - 1);
997
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200998 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000999
Paul Bakkerf9688572011-05-05 10:00:45 +00001000 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001002
1003 ret = 0;
1004
1005 /*
1006 * shift by count / limb_size
1007 */
1008 if( v0 > 0 )
1009 {
Paul Bakker23986e52011-04-24 08:57:21 +00001010 for( i = X->n; i > v0; i-- )
1011 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001012
Paul Bakker23986e52011-04-24 08:57:21 +00001013 for( ; i > 0; i-- )
1014 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001015 }
1016
1017 /*
1018 * shift by count % limb_size
1019 */
1020 if( t1 > 0 )
1021 {
1022 for( i = v0; i < X->n; i++ )
1023 {
1024 r1 = X->p[i] >> (biL - t1);
1025 X->p[i] <<= t1;
1026 X->p[i] |= r0;
1027 r0 = r1;
1028 }
1029 }
1030
1031cleanup:
1032
1033 return( ret );
1034}
1035
1036/*
1037 * Right-shift: X >>= count
1038 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001040{
Paul Bakker23986e52011-04-24 08:57:21 +00001041 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001043 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001044
1045 v0 = count / biL;
1046 v1 = count & (biL - 1);
1047
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001048 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001050
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 /*
1052 * shift by count / limb_size
1053 */
1054 if( v0 > 0 )
1055 {
1056 for( i = 0; i < X->n - v0; i++ )
1057 X->p[i] = X->p[i + v0];
1058
1059 for( ; i < X->n; i++ )
1060 X->p[i] = 0;
1061 }
1062
1063 /*
1064 * shift by count % limb_size
1065 */
1066 if( v1 > 0 )
1067 {
Paul Bakker23986e52011-04-24 08:57:21 +00001068 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 {
Paul Bakker23986e52011-04-24 08:57:21 +00001070 r1 = X->p[i - 1] << (biL - v1);
1071 X->p[i - 1] >>= v1;
1072 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 r0 = r1;
1074 }
1075 }
1076
1077 return( 0 );
1078}
1079
1080/*
1081 * Compare unsigned values
1082 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001084{
Paul Bakker23986e52011-04-24 08:57:21 +00001085 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001086 MPI_VALIDATE_RET( X != NULL );
1087 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001088
Paul Bakker23986e52011-04-24 08:57:21 +00001089 for( i = X->n; i > 0; i-- )
1090 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 break;
1092
Paul Bakker23986e52011-04-24 08:57:21 +00001093 for( j = Y->n; j > 0; j-- )
1094 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 break;
1096
Paul Bakker23986e52011-04-24 08:57:21 +00001097 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 return( 0 );
1099
1100 if( i > j ) return( 1 );
1101 if( j > i ) return( -1 );
1102
Paul Bakker23986e52011-04-24 08:57:21 +00001103 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001104 {
Paul Bakker23986e52011-04-24 08:57:21 +00001105 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1106 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001107 }
1108
1109 return( 0 );
1110}
1111
1112/*
1113 * Compare signed values
1114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001116{
Paul Bakker23986e52011-04-24 08:57:21 +00001117 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001118 MPI_VALIDATE_RET( X != NULL );
1119 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001120
Paul Bakker23986e52011-04-24 08:57:21 +00001121 for( i = X->n; i > 0; i-- )
1122 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001123 break;
1124
Paul Bakker23986e52011-04-24 08:57:21 +00001125 for( j = Y->n; j > 0; j-- )
1126 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001127 break;
1128
Paul Bakker23986e52011-04-24 08:57:21 +00001129 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 return( 0 );
1131
1132 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001133 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001134
1135 if( X->s > 0 && Y->s < 0 ) return( 1 );
1136 if( Y->s > 0 && X->s < 0 ) return( -1 );
1137
Paul Bakker23986e52011-04-24 08:57:21 +00001138 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 {
Paul Bakker23986e52011-04-24 08:57:21 +00001140 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1141 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001142 }
1143
1144 return( 0 );
1145}
1146
Janos Follathee6abce2019-09-05 14:47:19 +01001147/*
1148 * Compare signed values in constant time
1149 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001150int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1151 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001152{
1153 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001154 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001155 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001156
1157 MPI_VALIDATE_RET( X != NULL );
1158 MPI_VALIDATE_RET( Y != NULL );
1159 MPI_VALIDATE_RET( ret != NULL );
1160
1161 if( X->n != Y->n )
1162 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1163
1164 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001165 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1166 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001167 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001168 X_is_negative = ( X->s & 2 ) >> 1;
1169 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001170
1171 /*
1172 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001173 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1174 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001175 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001176 cond = ( X_is_negative ^ Y_is_negative );
1177 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001178
1179 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001180 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001181 * need to go through the loop. Record if we have the result already.
1182 */
Janos Follathee6abce2019-09-05 14:47:19 +01001183 done = cond;
1184
1185 for( i = X->n; i > 0; i-- )
1186 {
1187 /*
Janos Follath30702422019-11-05 12:24:52 +00001188 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1189 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001190 *
1191 * Again even if we can make a decision, we just mark the result and
1192 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001193 */
gabor-mezei-arme41e3e82021-09-28 16:14:47 +02001194 cond = mbedtls_cf_mpi_uint_lt( Y->p[i - 1], X->p[i - 1] );
Janos Follath30702422019-11-05 12:24:52 +00001195 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001196 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001197
1198 /*
Janos Follath30702422019-11-05 12:24:52 +00001199 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1200 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001201 *
1202 * Again even if we can make a decision, we just mark the result and
1203 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001204 */
gabor-mezei-arme41e3e82021-09-28 16:14:47 +02001205 cond = mbedtls_cf_mpi_uint_lt( X->p[i - 1], Y->p[i - 1] );
Janos Follath30702422019-11-05 12:24:52 +00001206 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001207 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001208 }
1209
1210 return( 0 );
1211}
1212
Paul Bakker5121ce52009-01-03 21:22:43 +00001213/*
1214 * Compare signed values
1215 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001217{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218 mbedtls_mpi Y;
1219 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001220 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001221
1222 *p = ( z < 0 ) ? -z : z;
1223 Y.s = ( z < 0 ) ? -1 : 1;
1224 Y.n = 1;
1225 Y.p = p;
1226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001228}
1229
1230/*
1231 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001234{
Janos Follath24eed8d2019-11-22 13:21:35 +00001235 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001236 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001237 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001238 MPI_VALIDATE_RET( X != NULL );
1239 MPI_VALIDATE_RET( A != NULL );
1240 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241
1242 if( X == B )
1243 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001244 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001245 }
1246
1247 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001249
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001250 /*
1251 * X should always be positive as a result of unsigned additions.
1252 */
1253 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001254
Paul Bakker23986e52011-04-24 08:57:21 +00001255 for( j = B->n; j > 0; j-- )
1256 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001257 break;
1258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001260
1261 o = B->p; p = X->p; c = 0;
1262
Janos Follath6c922682015-10-30 17:43:11 +01001263 /*
1264 * tmp is used because it might happen that p == o
1265 */
Paul Bakker23986e52011-04-24 08:57:21 +00001266 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001267 {
Janos Follath6c922682015-10-30 17:43:11 +01001268 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001269 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001270 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001271 }
1272
1273 while( c != 0 )
1274 {
1275 if( i >= X->n )
1276 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001278 p = X->p + i;
1279 }
1280
Paul Bakker2d319fd2012-09-16 21:34:26 +00001281 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001282 }
1283
1284cleanup:
1285
1286 return( ret );
1287}
1288
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001289/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001290 * Helper for mbedtls_mpi subtraction.
1291 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001292 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001293 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001294 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001295 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001296 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001297 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001298 * \param n Number of limbs of \p d, \p l and \p r.
1299 * \param[out] d The result of the subtraction.
1300 * \param[in] l The left operand.
1301 * \param[in] r The right operand.
1302 *
1303 * \return 1 if `l < r`.
1304 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001305 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001306static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1307 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001308 const mbedtls_mpi_uint *l,
1309 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001310{
Paul Bakker23986e52011-04-24 08:57:21 +00001311 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001312 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001313
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001314 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001315 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001316 z = ( l[i] < c ); t = l[i] - c;
1317 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001318 }
1319
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001320 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001321}
1322
1323/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001324 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001327{
Janos Follath24eed8d2019-11-22 13:21:35 +00001328 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001329 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001330 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001331 MPI_VALIDATE_RET( X != NULL );
1332 MPI_VALIDATE_RET( A != NULL );
1333 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334
Paul Bakker23986e52011-04-24 08:57:21 +00001335 for( n = B->n; n > 0; n-- )
1336 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001338 if( n > A->n )
1339 {
1340 /* B >= (2^ciL)^n > A */
1341 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1342 goto cleanup;
1343 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001345 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1346
1347 /* Set the high limbs of X to match A. Don't touch the lower limbs
1348 * because X might be aliased to B, and we must not overwrite the
1349 * significant digits of B. */
1350 if( A->n > n )
1351 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1352 if( X->n > A->n )
1353 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1354
1355 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001356 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001357 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001358 /* Propagate the carry to the first nonzero limb of X. */
1359 for( ; n < X->n && X->p[n] == 0; n++ )
1360 --X->p[n];
1361 /* If we ran out of space for the carry, it means that the result
1362 * is negative. */
1363 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001364 {
1365 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1366 goto cleanup;
1367 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001368 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001369 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001370
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001371 /* X should always be positive as a result of unsigned subtractions. */
1372 X->s = 1;
1373
Paul Bakker5121ce52009-01-03 21:22:43 +00001374cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 return( ret );
1376}
1377
1378/*
1379 * Signed addition: X = A + B
1380 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001382{
Hanno Becker73d7d792018-12-11 10:35:51 +00001383 int ret, s;
1384 MPI_VALIDATE_RET( X != NULL );
1385 MPI_VALIDATE_RET( A != NULL );
1386 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001387
Hanno Becker73d7d792018-12-11 10:35:51 +00001388 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 if( A->s * B->s < 0 )
1390 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001392 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001394 X->s = s;
1395 }
1396 else
1397 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 X->s = -s;
1400 }
1401 }
1402 else
1403 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001404 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 X->s = s;
1406 }
1407
1408cleanup:
1409
1410 return( ret );
1411}
1412
1413/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001414 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001417{
Hanno Becker73d7d792018-12-11 10:35:51 +00001418 int ret, s;
1419 MPI_VALIDATE_RET( X != NULL );
1420 MPI_VALIDATE_RET( A != NULL );
1421 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001422
Hanno Becker73d7d792018-12-11 10:35:51 +00001423 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001424 if( A->s * B->s > 0 )
1425 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001427 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001429 X->s = s;
1430 }
1431 else
1432 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001433 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 X->s = -s;
1435 }
1436 }
1437 else
1438 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 X->s = s;
1441 }
1442
1443cleanup:
1444
1445 return( ret );
1446}
1447
1448/*
1449 * Signed addition: X = A + b
1450 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001452{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001453 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001454 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001455 MPI_VALIDATE_RET( X != NULL );
1456 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001457
1458 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001459 B.s = ( b < 0 ) ? -1 : 1;
1460 B.n = 1;
1461 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001462
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001463 return( mbedtls_mpi_add_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001464}
1465
1466/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001467 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001468 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001470{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001471 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001473 MPI_VALIDATE_RET( X != NULL );
1474 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
1476 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001477 B.s = ( b < 0 ) ? -1 : 1;
1478 B.n = 1;
1479 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001481 return( mbedtls_mpi_sub_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482}
1483
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001484/** Helper for mbedtls_mpi multiplication.
1485 *
1486 * Add \p b * \p s to \p d.
1487 *
1488 * \param i The number of limbs of \p s.
1489 * \param[in] s A bignum to multiply, of size \p i.
1490 * It may overlap with \p d, but only if
1491 * \p d <= \p s.
1492 * Its leading limb must not be \c 0.
1493 * \param[in,out] d The bignum to add to.
1494 * It must be sufficiently large to store the
1495 * result of the multiplication. This means
1496 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1497 * is not known a priori.
1498 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001499 */
1500static
1501#if defined(__APPLE__) && defined(__arm__)
1502/*
1503 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1504 * appears to need this to prevent bad ARM code generation at -O3.
1505 */
1506__attribute__ ((noinline))
1507#endif
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001508void mpi_mul_hlp( size_t i,
1509 const mbedtls_mpi_uint *s,
1510 mbedtls_mpi_uint *d,
1511 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001512{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001514
1515#if defined(MULADDC_HUIT)
1516 for( ; i >= 8; i -= 8 )
1517 {
1518 MULADDC_INIT
1519 MULADDC_HUIT
1520 MULADDC_STOP
1521 }
1522
1523 for( ; i > 0; i-- )
1524 {
1525 MULADDC_INIT
1526 MULADDC_CORE
1527 MULADDC_STOP
1528 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001529#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001530 for( ; i >= 16; i -= 16 )
1531 {
1532 MULADDC_INIT
1533 MULADDC_CORE MULADDC_CORE
1534 MULADDC_CORE MULADDC_CORE
1535 MULADDC_CORE MULADDC_CORE
1536 MULADDC_CORE MULADDC_CORE
1537
1538 MULADDC_CORE MULADDC_CORE
1539 MULADDC_CORE MULADDC_CORE
1540 MULADDC_CORE MULADDC_CORE
1541 MULADDC_CORE MULADDC_CORE
1542 MULADDC_STOP
1543 }
1544
1545 for( ; i >= 8; i -= 8 )
1546 {
1547 MULADDC_INIT
1548 MULADDC_CORE MULADDC_CORE
1549 MULADDC_CORE MULADDC_CORE
1550
1551 MULADDC_CORE MULADDC_CORE
1552 MULADDC_CORE MULADDC_CORE
1553 MULADDC_STOP
1554 }
1555
1556 for( ; i > 0; i-- )
1557 {
1558 MULADDC_INIT
1559 MULADDC_CORE
1560 MULADDC_STOP
1561 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001562#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001563
1564 t++;
1565
Gilles Peskine8e464c42020-07-24 00:08:38 +02001566 while( c != 0 )
1567 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001568 *d += c; c = ( *d < c ); d++;
1569 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001570}
1571
1572/*
1573 * Baseline multiplication: X = A * B (HAC 14.12)
1574 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001575int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001576{
Janos Follath24eed8d2019-11-22 13:21:35 +00001577 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001578 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 mbedtls_mpi TA, TB;
Gilles Peskined65b5002021-06-15 21:44:32 +02001580 int result_is_zero = 0;
Hanno Becker73d7d792018-12-11 10:35:51 +00001581 MPI_VALIDATE_RET( X != NULL );
1582 MPI_VALIDATE_RET( A != NULL );
1583 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001587 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1588 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001589
Paul Bakker23986e52011-04-24 08:57:21 +00001590 for( i = A->n; i > 0; i-- )
1591 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001592 break;
Gilles Peskine38a384d2021-06-17 14:35:25 +02001593 if( i == 0 )
Gilles Peskined65b5002021-06-15 21:44:32 +02001594 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001595
Paul Bakker23986e52011-04-24 08:57:21 +00001596 for( j = B->n; j > 0; j-- )
1597 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001598 break;
Gilles Peskine38a384d2021-06-17 14:35:25 +02001599 if( j == 0 )
Gilles Peskined65b5002021-06-15 21:44:32 +02001600 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1603 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001605 for( ; j > 0; j-- )
1606 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001607
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001608 /* If the result is 0, we don't shortcut the operation, which reduces
1609 * but does not eliminate side channels leaking the zero-ness. We do
1610 * need to take care to set the sign bit properly since the library does
1611 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskined65b5002021-06-15 21:44:32 +02001612 if( result_is_zero )
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001613 X->s = 1;
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001614 else
1615 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001616
1617cleanup:
1618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
1621 return( ret );
1622}
1623
1624/*
1625 * Baseline multiplication: X = A * b
1626 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001628{
Hanno Becker73d7d792018-12-11 10:35:51 +00001629 MPI_VALIDATE_RET( X != NULL );
1630 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001632 /* mpi_mul_hlp can't deal with a leading 0. */
1633 size_t n = A->n;
1634 while( n > 0 && A->p[n - 1] == 0 )
1635 --n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001636
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001637 /* The general method below doesn't work if n==0 or b==0. By chance
1638 * calculating the result is trivial in those cases. */
1639 if( b == 0 || n == 0 )
1640 {
Paul Elliott986b55a2021-04-20 21:46:29 +01001641 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001642 }
1643
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001644 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001645 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001646 /* In general, A * b requires 1 limb more than b. If
1647 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1648 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001649 * copy() will take care of the growth if needed. However, experimentally,
1650 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001651 * calls to calloc() in ECP code, presumably because it reuses the
1652 * same mpi for a while and this way the mpi is more likely to directly
1653 * grow to its final size. */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001654 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
1655 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1656 mpi_mul_hlp( n, A->p, X->p, b - 1 );
1657
1658cleanup:
1659 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001660}
1661
1662/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001663 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1664 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001665 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001666static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1667 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001668{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001669#if defined(MBEDTLS_HAVE_UDBL)
1670 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001671#else
Simon Butcher9803d072016-01-03 00:24:34 +00001672 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1673 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001674 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1675 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001676 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001677#endif
1678
Simon Butcher15b15d12015-11-26 19:35:03 +00001679 /*
1680 * Check for overflow
1681 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001682 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001683 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001684 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001685
Simon Butcherf5ba0452015-12-27 23:01:55 +00001686 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001687 }
1688
1689#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001690 dividend = (mbedtls_t_udbl) u1 << biL;
1691 dividend |= (mbedtls_t_udbl) u0;
1692 quotient = dividend / d;
1693 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1694 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1695
1696 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001697 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001698
1699 return (mbedtls_mpi_uint) quotient;
1700#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001701
1702 /*
1703 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1704 * Vol. 2 - Seminumerical Algorithms, Knuth
1705 */
1706
1707 /*
1708 * Normalize the divisor, d, and dividend, u0, u1
1709 */
1710 s = mbedtls_clz( d );
1711 d = d << s;
1712
1713 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001714 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001715 u0 = u0 << s;
1716
1717 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001718 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001719
1720 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001721 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001722
1723 /*
1724 * Find the first quotient and remainder
1725 */
1726 q1 = u1 / d1;
1727 r0 = u1 - d1 * q1;
1728
1729 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1730 {
1731 q1 -= 1;
1732 r0 += d1;
1733
1734 if ( r0 >= radix ) break;
1735 }
1736
Simon Butcherf5ba0452015-12-27 23:01:55 +00001737 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001738 q0 = rAX / d1;
1739 r0 = rAX - q0 * d1;
1740
1741 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1742 {
1743 q0 -= 1;
1744 r0 += d1;
1745
1746 if ( r0 >= radix ) break;
1747 }
1748
1749 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001750 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001751
1752 quotient = q1 * radix + q0;
1753
1754 return quotient;
1755#endif
1756}
1757
1758/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001761int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1762 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001763{
Janos Follath24eed8d2019-11-22 13:21:35 +00001764 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001765 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001766 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001767 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001768 MPI_VALIDATE_RET( A != NULL );
1769 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001771 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1772 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001775 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001776 /*
1777 * Avoid dynamic memory allocations for constant-size T2.
1778 *
1779 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1780 * so nobody increase the size of the MPI and we're safe to use an on-stack
1781 * buffer.
1782 */
Alexander K35d6d462019-10-31 14:46:45 +03001783 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001784 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1785 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001788 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1790 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001791 return( 0 );
1792 }
1793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1795 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796 X.s = Y.s = 1;
1797
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001798 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1799 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001800 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001802 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001803 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001804 {
1805 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1807 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808 }
1809 else k = 0;
1810
1811 n = X.n - 1;
1812 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001816 {
1817 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
1822 for( i = n; i > t ; i-- )
1823 {
1824 if( X.p[i] >= Y.p[t] )
1825 Z.p[i - t - 1] = ~0;
1826 else
1827 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001828 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1829 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 }
1831
Alexander K35d6d462019-10-31 14:46:45 +03001832 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1833 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1834 T2.p[2] = X.p[i];
1835
Paul Bakker5121ce52009-01-03 21:22:43 +00001836 Z.p[i - t - 1]++;
1837 do
1838 {
1839 Z.p[i - t - 1]--;
1840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001842 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001847
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1849 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1850 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1856 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857 Z.p[i - t - 1]--;
1858 }
1859 }
1860
1861 if( Q != NULL )
1862 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 Q->s = A->s * B->s;
1865 }
1866
1867 if( R != NULL )
1868 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001870 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001872
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 R->s = 1;
1875 }
1876
1877cleanup:
1878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001880 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001881 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
1883 return( ret );
1884}
1885
1886/*
1887 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001888 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001889int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1890 const mbedtls_mpi *A,
1891 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001892{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001893 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001895 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
1897 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001898 B.s = ( b < 0 ) ? -1 : 1;
1899 B.n = 1;
1900 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001901
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001902 return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001903}
1904
1905/*
1906 * Modulo: R = A mod B
1907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001908int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001909{
Janos Follath24eed8d2019-11-22 13:21:35 +00001910 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001911 MPI_VALIDATE_RET( R != NULL );
1912 MPI_VALIDATE_RET( A != NULL );
1913 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1916 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001917
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001918 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001920 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1921 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1924 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001925
1926cleanup:
1927
1928 return( ret );
1929}
1930
1931/*
1932 * Modulo: r = A mod b
1933 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001935{
Paul Bakker23986e52011-04-24 08:57:21 +00001936 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001938 MPI_VALIDATE_RET( r != NULL );
1939 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
1941 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
1944 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946
1947 /*
1948 * handle trivial cases
1949 */
1950 if( b == 1 )
1951 {
1952 *r = 0;
1953 return( 0 );
1954 }
1955
1956 if( b == 2 )
1957 {
1958 *r = A->p[0] & 1;
1959 return( 0 );
1960 }
1961
1962 /*
1963 * general case
1964 */
Paul Bakker23986e52011-04-24 08:57:21 +00001965 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001966 {
Paul Bakker23986e52011-04-24 08:57:21 +00001967 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001968 y = ( y << biH ) | ( x >> biH );
1969 z = y / b;
1970 y -= z * b;
1971
1972 x <<= biH;
1973 y = ( y << biH ) | ( x >> biH );
1974 z = y / b;
1975 y -= z * b;
1976 }
1977
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001978 /*
1979 * If A is negative, then the current y represents a negative value.
1980 * Flipping it to the positive side.
1981 */
1982 if( A->s < 0 && y != 0 )
1983 y = b - y;
1984
Paul Bakker5121ce52009-01-03 21:22:43 +00001985 *r = y;
1986
1987 return( 0 );
1988}
1989
1990/*
1991 * Fast Montgomery initialization (thanks to Tom St Denis)
1992 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001994{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001996 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001997
1998 x = m0;
1999 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002001 for( i = biL; i >= 8; i /= 2 )
2002 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
2004 *mm = ~x + 1;
2005}
2006
Gilles Peskine2a82f722020-06-04 15:00:49 +02002007/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2008 *
2009 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002010 * It must have at least as many limbs as N
2011 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002012 * On successful completion, A contains the result of
2013 * the multiplication A * B * R^-1 mod N where
2014 * R = (2^ciL)^n.
2015 * \param[in] B One of the numbers to multiply.
2016 * It must be nonzero and must not have more limbs than N
2017 * (B->n <= N->n).
2018 * \param[in] N The modulo. N must be odd.
2019 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2020 * This is -N^-1 mod 2^ciL.
2021 * \param[in,out] T A bignum for temporary storage.
2022 * It must be at least twice the limb size of N plus 2
2023 * (T->n >= 2 * (N->n + 1)).
2024 * Its initial content is unused and
2025 * its final content is indeterminate.
2026 * Note that unlike the usual convention in the library
2027 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002028 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002029static 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 +02002030 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002031{
Paul Bakker23986e52011-04-24 08:57:21 +00002032 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
2035 memset( T->p, 0, T->n * ciL );
2036
2037 d = T->p;
2038 n = N->n;
2039 m = ( B->n < n ) ? B->n : n;
2040
2041 for( i = 0; i < n; i++ )
2042 {
2043 /*
2044 * T = (T + u0*B + u1*N) / 2^biL
2045 */
2046 u0 = A->p[i];
2047 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2048
2049 mpi_mul_hlp( m, B->p, d, u0 );
2050 mpi_mul_hlp( n, N->p, d, u1 );
2051
2052 *d++ = u0; d[n + 1] = 0;
2053 }
2054
Gilles Peskine221626f2020-06-08 22:37:50 +02002055 /* At this point, d is either the desired result or the desired result
2056 * plus N. We now potentially subtract N, avoiding leaking whether the
2057 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
Gilles Peskine221626f2020-06-08 22:37:50 +02002059 /* Copy the n least significant limbs of d to A, so that
2060 * A = d if d < N (recall that N has n limbs). */
2061 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002062 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002063 * do the calculation without using conditional tests. */
2064 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002065 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02002066 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02002067 /* If d0 < N then d < (2^biL)^n
2068 * so d[n] == 0 and we want to keep A as it is.
2069 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2070 * so d[n] == 1 and we want to set A to the result of the subtraction
2071 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2072 * This exactly corresponds to a conditional assignment. */
gabor-mezei-arme41e3e82021-09-28 16:14:47 +02002073 mbedtls_cf_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002074}
2075
2076/*
2077 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002078 *
2079 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002080 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002081static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2082 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002083{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 mbedtls_mpi_uint z = 1;
2085 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
Paul Bakker8ddb6452013-02-27 14:56:33 +01002087 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002088 U.p = &z;
2089
Gilles Peskine4e91d472020-06-04 20:55:15 +02002090 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002091}
2092
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002093/**
2094 * Select an MPI from a table without leaking the index.
2095 *
2096 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2097 * reads the entire table in order to avoid leaking the value of idx to an
2098 * attacker able to observe memory access patterns.
2099 *
2100 * \param[out] R Where to write the selected MPI.
2101 * \param[in] T The table to read from.
2102 * \param[in] T_size The number of elements in the table.
2103 * \param[in] idx The index of the element to select;
2104 * this must satisfy 0 <= idx < T_size.
2105 *
2106 * \return \c 0 on success, or a negative error code.
2107 */
2108static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2109{
2110 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2111
2112 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002113 {
2114 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
gabor-mezei-arme41e3e82021-09-28 16:14:47 +02002115 (unsigned char) mbedtls_cf_size_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002116 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002117
2118cleanup:
2119 return( ret );
2120}
2121
Paul Bakker5121ce52009-01-03 21:22:43 +00002122/*
2123 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2124 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002125int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2126 const mbedtls_mpi *E, const mbedtls_mpi *N,
Yuto Takano284857e2021-07-14 10:20:09 +01002127 mbedtls_mpi *prec_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002128{
Janos Follath24eed8d2019-11-22 13:21:35 +00002129 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002130 size_t wbits, wsize, one = 1;
2131 size_t i, j, nblimbs;
2132 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002134 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002135 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002136
Hanno Becker73d7d792018-12-11 10:35:51 +00002137 MPI_VALIDATE_RET( X != NULL );
2138 MPI_VALIDATE_RET( A != NULL );
2139 MPI_VALIDATE_RET( E != NULL );
2140 MPI_VALIDATE_RET( N != NULL );
2141
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002142 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002143 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2146 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002147
Chris Jones9246d042020-11-25 15:12:39 +00002148 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2149 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2150 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2151
Paul Bakkerf6198c12012-05-16 08:02:29 +00002152 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002153 * Init temps and window size
2154 */
2155 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2157 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002158 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002159 memset( W, 0, sizeof( W ) );
2160
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002161 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002162
2163 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2164 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2165
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002166#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2168 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002169#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002170
Paul Bakker5121ce52009-01-03 21:22:43 +00002171 j = N->n + 1;
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002172 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2173 * and mpi_montred() calls later. Here we ensure that W[1] and X are
2174 * large enough, and later we'll grow other W[i] to the same length.
2175 * They must not be shrunk midway through this function!
2176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2178 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2179 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180
2181 /*
Paul Bakker50546922012-05-19 08:40:49 +00002182 * Compensate for negative A (and correct at the end)
2183 */
2184 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002185 if( neg )
2186 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002188 Apos.s = 1;
2189 A = &Apos;
2190 }
2191
2192 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002193 * If 1st call, pre-compute R^2 mod N
2194 */
Yuto Takano284857e2021-07-14 10:20:09 +01002195 if( prec_RR == NULL || prec_RR->p == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00002196 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2198 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
Yuto Takano284857e2021-07-14 10:20:09 +01002201 if( prec_RR != NULL )
2202 memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002203 }
2204 else
Yuto Takano284857e2021-07-14 10:20:09 +01002205 memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002206
2207 /*
2208 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2209 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002211 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002212 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002213 /* This should be a no-op because W[1] is already that large before
2214 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2215 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine0759cad2021-06-15 21:22:48 +02002216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002217 }
Paul Bakkerc2024f42014-01-23 20:38:35 +01002218 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002221 /* Note that this is safe because W[1] always has at least N->n limbs
2222 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002223 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002224
2225 /*
2226 * X = R^2 * R^-1 mod N = R mod N
2227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002229 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002230
2231 if( wsize > 1 )
2232 {
2233 /*
2234 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2235 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002236 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2239 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240
2241 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002242 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002243
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 /*
2245 * W[i] = W[i - 1] * W[1]
2246 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002247 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002248 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2250 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002251
Gilles Peskine4e91d472020-06-04 20:55:15 +02002252 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 }
2254 }
2255
2256 nblimbs = E->n;
2257 bufsize = 0;
2258 nbits = 0;
2259 wbits = 0;
2260 state = 0;
2261
2262 while( 1 )
2263 {
2264 if( bufsize == 0 )
2265 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002266 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 break;
2268
Paul Bakker0d7702c2013-10-29 16:18:35 +01002269 nblimbs--;
2270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 }
2273
2274 bufsize--;
2275
2276 ei = (E->p[nblimbs] >> bufsize) & 1;
2277
2278 /*
2279 * skip leading 0s
2280 */
2281 if( ei == 0 && state == 0 )
2282 continue;
2283
2284 if( ei == 0 && state == 1 )
2285 {
2286 /*
2287 * out of window, square X
2288 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002289 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002290 continue;
2291 }
2292
2293 /*
2294 * add ei to current window
2295 */
2296 state = 2;
2297
2298 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002299 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002300
2301 if( nbits == wsize )
2302 {
2303 /*
2304 * X = X^wsize R^-1 mod N
2305 */
2306 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002307 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
2309 /*
2310 * X = X * W[wbits] R^-1 mod N
2311 */
Manuel Pégourié-Gonnard0b3bde52021-06-10 09:34:00 +02002312 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002313 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002314
2315 state--;
2316 nbits = 0;
2317 wbits = 0;
2318 }
2319 }
2320
2321 /*
2322 * process the remaining bits
2323 */
2324 for( i = 0; i < nbits; i++ )
2325 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002326 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327
2328 wbits <<= 1;
2329
Paul Bakker66d5d072014-06-17 16:39:18 +02002330 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002331 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 }
2333
2334 /*
2335 * X = A^E * R * R^-1 mod N = A^E mod N
2336 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002337 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
Hanno Beckera4af1c42017-04-18 09:07:45 +01002339 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002340 {
2341 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002343 }
2344
Paul Bakker5121ce52009-01-03 21:22:43 +00002345cleanup:
2346
Paul Bakker66d5d072014-06-17 16:39:18 +02002347 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002351 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002352
Yuto Takano284857e2021-07-14 10:20:09 +01002353 if( prec_RR == NULL || prec_RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
2356 return( ret );
2357}
2358
Paul Bakker5121ce52009-01-03 21:22:43 +00002359/*
2360 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2361 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002363{
Janos Follath24eed8d2019-11-22 13:21:35 +00002364 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002365 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002366 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
Hanno Becker73d7d792018-12-11 10:35:51 +00002368 MPI_VALIDATE_RET( G != NULL );
2369 MPI_VALIDATE_RET( A != NULL );
2370 MPI_VALIDATE_RET( B != NULL );
2371
Alexander Ke8ad49f2019-08-16 16:16:07 +03002372 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2375 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002377 lz = mbedtls_mpi_lsb( &TA );
2378 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002379
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002380 /* The loop below gives the correct result when A==0 but not when B==0.
2381 * So have a special case for B==0. Leverage the fact that we just
2382 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2383 * slightly more efficient than cmp_int(). */
2384 if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2385 {
2386 ret = mbedtls_mpi_copy( G, A );
2387 goto cleanup;
2388 }
2389
Paul Bakker66d5d072014-06-17 16:39:18 +02002390 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002391 lz = lzt;
2392
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 TA.s = TB.s = 1;
2394
Gilles Peskineea9aa142021-06-16 13:42:04 +02002395 /* We mostly follow the procedure described in HAC 14.54, but with some
2396 * minor differences:
2397 * - Sequences of multiplications or divisions by 2 are grouped into a
2398 * single shift operation.
Gilles Peskine37d690c2021-06-21 18:58:39 +02002399 * - The procedure in HAC assumes that 0 < TB <= TA.
2400 * - The condition TB <= TA is not actually necessary for correctness.
2401 * TA and TB have symmetric roles except for the loop termination
2402 * condition, and the shifts at the beginning of the loop body
2403 * remove any significance from the ordering of TA vs TB before
2404 * the shifts.
2405 * - If TA = 0, the loop goes through 0 iterations and the result is
2406 * correctly TB.
2407 * - The case TB = 0 was short-circuited above.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002408 *
2409 * For the correctness proof below, decompose the original values of
2410 * A and B as
2411 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2412 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2413 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2414 * and gcd(A',B') is odd or 0.
2415 *
2416 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2417 * The code maintains the following invariant:
2418 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine6537bdb2021-06-15 22:09:39 +02002419 */
2420
Gilles Peskineea9aa142021-06-16 13:42:04 +02002421 /* Proof that the loop terminates:
2422 * At each iteration, either the right-shift by 1 is made on a nonzero
2423 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2424 * by at least 1, or the right-shift by 1 is made on zero and then
2425 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2426 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2427 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002428 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002429 {
Gilles Peskineea9aa142021-06-16 13:42:04 +02002430 /* Divisions by 2 preserve the invariant (I). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2432 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Gilles Peskineea9aa142021-06-16 13:42:04 +02002434 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2435 * TA-TB is even so the division by 2 has an integer result.
2436 * Invariant (I) is preserved since any odd divisor of both TA and TB
2437 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2438 * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
2439 * divides TA.
2440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002442 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2444 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002445 }
2446 else
2447 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2449 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002450 }
Gilles Peskineea9aa142021-06-16 13:42:04 +02002451 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002452 }
2453
Gilles Peskineea9aa142021-06-16 13:42:04 +02002454 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2455 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2456 * - If there was at least one loop iteration, then one of TA or TB is odd,
2457 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2458 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2459 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskineb798b352021-06-21 11:40:38 +02002460 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002461 */
2462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2464 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002465
2466cleanup:
2467
Alexander Ke8ad49f2019-08-16 16:16:07 +03002468 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002469
2470 return( ret );
2471}
2472
Gilles Peskine8f454702021-04-01 15:57:18 +02002473/* Fill X with n_bytes random bytes.
2474 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002475 * The ordering of the bytes returned from the RNG is suitable for
2476 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002477 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002478 * n_bytes must not be 0.
2479 */
2480static int mpi_fill_random_internal(
2481 mbedtls_mpi *X, size_t n_bytes,
2482 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2483{
2484 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2485 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2486 const size_t overhead = ( limbs * ciL ) - n_bytes;
2487
2488 if( X->n < limbs )
2489 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine8f454702021-04-01 15:57:18 +02002490
Gilles Peskinea16001e2021-04-13 21:55:35 +02002491 memset( X->p, 0, overhead );
2492 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine8f454702021-04-01 15:57:18 +02002493 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2494 mpi_bigendian_to_host( X->p, limbs );
2495
2496cleanup:
2497 return( ret );
2498}
2499
Paul Bakker33dc46b2014-04-30 16:11:39 +02002500/*
2501 * Fill X with size bytes of random.
2502 *
2503 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002504 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002505 * deterministic, eg for tests).
2506 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002508 int (*f_rng)(void *, unsigned char *, size_t),
2509 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002510{
Janos Follath24eed8d2019-11-22 13:21:35 +00002511 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002512 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002513
Hanno Becker8ce11a32018-12-19 16:18:52 +00002514 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002515 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002516
Hanno Beckerda1655a2017-10-18 14:21:44 +01002517 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002518 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002519 if( size == 0 )
2520 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002521
Gilles Peskine8f454702021-04-01 15:57:18 +02002522 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002523
2524cleanup:
2525 return( ret );
2526}
2527
Gilles Peskine4699fa42021-03-29 22:02:55 +02002528int mbedtls_mpi_random( mbedtls_mpi *X,
2529 mbedtls_mpi_sint min,
2530 const mbedtls_mpi *N,
2531 int (*f_rng)(void *, unsigned char *, size_t),
2532 void *p_rng )
2533{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002534 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002535 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002536 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002537 size_t n_bits = mbedtls_mpi_bitlen( N );
2538 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002539 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002540
Gilles Peskine9312ba52021-03-29 22:14:51 +02002541 if( min < 0 )
2542 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2543 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2544 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2545
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002546 /*
2547 * When min == 0, each try has at worst a probability 1/2 of failing
2548 * (the msb has a probability 1/2 of being 0, and then the result will
2549 * be < N), so after 30 tries failure probability is a most 2**(-30).
2550 *
2551 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002552 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002553 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002554 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002555 * a probability of failing that is almost 1/2.
2556 *
2557 * The probabilities are almost the same if min is nonzero but negligible
2558 * compared to N. This is always the case when N is crypto-sized, but
2559 * it's convenient to support small N for testing purposes. When N
2560 * is small, use a higher repeat count, otherwise the probability of
2561 * failure is macroscopic.
2562 */
Gilles Peskine11779072021-06-02 21:18:59 +02002563 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002564
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002565 mbedtls_mpi_init( &lower_bound );
2566
Gilles Peskine8f454702021-04-01 15:57:18 +02002567 /* Ensure that target MPI has exactly the same number of limbs
2568 * as the upper bound, even if the upper bound has leading zeros.
2569 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002570 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002571 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2572 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002573
Gilles Peskine4699fa42021-03-29 22:02:55 +02002574 /*
2575 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2576 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2577 * - use the same byte ordering;
2578 * - keep the leftmost n_bits bits of the generated octet string;
2579 * - try until result is in the desired range.
2580 * This also avoids any bias, which is especially important for ECDSA.
2581 */
2582 do
2583 {
Gilles Peskine8f454702021-04-01 15:57:18 +02002584 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002585 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2586
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002587 if( --count == 0 )
Gilles Peskine4699fa42021-03-29 22:02:55 +02002588 {
2589 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2590 goto cleanup;
2591 }
2592
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002593 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2594 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002595 }
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002596 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002597
2598cleanup:
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002599 mbedtls_mpi_free( &lower_bound );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002600 return( ret );
2601}
2602
Paul Bakker5121ce52009-01-03 21:22:43 +00002603/*
2604 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2605 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002607{
Janos Follath24eed8d2019-11-22 13:21:35 +00002608 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002609 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002610 MPI_VALIDATE_RET( X != NULL );
2611 MPI_VALIDATE_RET( A != NULL );
2612 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002613
Hanno Becker4bcb4912017-04-18 15:49:39 +01002614 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2618 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2619 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002621 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002622
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002623 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002624 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002625 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002626 goto cleanup;
2627 }
2628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2630 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2631 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2632 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2635 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2636 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2637 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002638
2639 do
2640 {
2641 while( ( TU.p[0] & 1 ) == 0 )
2642 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002644
2645 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2646 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2648 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002649 }
2650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002651 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2652 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002653 }
2654
2655 while( ( TV.p[0] & 1 ) == 0 )
2656 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002658
2659 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2660 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2662 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002663 }
2664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2666 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002667 }
2668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002670 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2672 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2673 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002674 }
2675 else
2676 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2678 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2679 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002680 }
2681 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2685 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2688 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002691
2692cleanup:
2693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2695 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2696 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002697
2698 return( ret );
2699}
2700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002702
Paul Bakker5121ce52009-01-03 21:22:43 +00002703static const int small_prime[] =
2704{
2705 3, 5, 7, 11, 13, 17, 19, 23,
2706 29, 31, 37, 41, 43, 47, 53, 59,
2707 61, 67, 71, 73, 79, 83, 89, 97,
2708 101, 103, 107, 109, 113, 127, 131, 137,
2709 139, 149, 151, 157, 163, 167, 173, 179,
2710 181, 191, 193, 197, 199, 211, 223, 227,
2711 229, 233, 239, 241, 251, 257, 263, 269,
2712 271, 277, 281, 283, 293, 307, 311, 313,
2713 317, 331, 337, 347, 349, 353, 359, 367,
2714 373, 379, 383, 389, 397, 401, 409, 419,
2715 421, 431, 433, 439, 443, 449, 457, 461,
2716 463, 467, 479, 487, 491, 499, 503, 509,
2717 521, 523, 541, 547, 557, 563, 569, 571,
2718 577, 587, 593, 599, 601, 607, 613, 617,
2719 619, 631, 641, 643, 647, 653, 659, 661,
2720 673, 677, 683, 691, 701, 709, 719, 727,
2721 733, 739, 743, 751, 757, 761, 769, 773,
2722 787, 797, 809, 811, 821, 823, 827, 829,
2723 839, 853, 857, 859, 863, 877, 881, 883,
2724 887, 907, 911, 919, 929, 937, 941, 947,
2725 953, 967, 971, 977, 983, 991, 997, -103
2726};
2727
2728/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002729 * Small divisors test (X must be positive)
2730 *
2731 * Return values:
2732 * 0: no small factor (possible prime, more tests needed)
2733 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002734 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002735 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002736 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002737static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002738{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002739 int ret = 0;
2740 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002741 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002742
Paul Bakker5121ce52009-01-03 21:22:43 +00002743 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002745
2746 for( i = 0; small_prime[i] > 0; i++ )
2747 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002748 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002749 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002751 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002752
2753 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002755 }
2756
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002757cleanup:
2758 return( ret );
2759}
2760
2761/*
2762 * Miller-Rabin pseudo-primality test (HAC 4.24)
2763 */
Janos Follathda31fa12018-09-03 14:45:23 +01002764static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002765 int (*f_rng)(void *, unsigned char *, size_t),
2766 void *p_rng )
2767{
Pascal Junodb99183d2015-03-11 16:49:45 +01002768 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002769 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002770 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002771
Hanno Becker8ce11a32018-12-19 16:18:52 +00002772 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002773 MPI_VALIDATE_RET( f_rng != NULL );
2774
2775 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2776 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002777 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002778
Paul Bakker5121ce52009-01-03 21:22:43 +00002779 /*
2780 * W = |X| - 1
2781 * R = W >> lsb( W )
2782 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2784 s = mbedtls_mpi_lsb( &W );
2785 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2786 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002787
Janos Follathda31fa12018-09-03 14:45:23 +01002788 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002789 {
2790 /*
2791 * pick a random A, 1 < A < |X| - 1
2792 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002793 count = 0;
2794 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002795 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002796
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002797 j = mbedtls_mpi_bitlen( &A );
2798 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002799 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002800 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002801 }
2802
2803 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002804 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2805 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002806 }
2807
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002808 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2809 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002810
2811 /*
2812 * A = A^R mod |X|
2813 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002814 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002816 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2817 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002818 continue;
2819
2820 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002821 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002822 {
2823 /*
2824 * A = A * A mod |X|
2825 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002826 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2827 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002828
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002829 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002830 break;
2831
2832 j++;
2833 }
2834
2835 /*
2836 * not prime if A != |X| - 1 or A == 1
2837 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002838 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2839 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002840 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002841 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002842 break;
2843 }
2844 }
2845
2846cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002847 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2848 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002849 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002850
2851 return( ret );
2852}
2853
2854/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002855 * Pseudo-primality test: small factors, then Miller-Rabin
2856 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002857int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2858 int (*f_rng)(void *, unsigned char *, size_t),
2859 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002860{
Janos Follath24eed8d2019-11-22 13:21:35 +00002861 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002862 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002863 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002864 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002865
2866 XX.s = 1;
2867 XX.n = X->n;
2868 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002870 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2871 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2872 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002874 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002875 return( 0 );
2876
2877 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2878 {
2879 if( ret == 1 )
2880 return( 0 );
2881
2882 return( ret );
2883 }
2884
Janos Follathda31fa12018-09-03 14:45:23 +01002885 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002886}
2887
Janos Follatha0b67c22018-09-18 14:48:23 +01002888#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002889/*
2890 * Pseudo-primality test, error probability 2^-80
2891 */
2892int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2893 int (*f_rng)(void *, unsigned char *, size_t),
2894 void *p_rng )
2895{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002896 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002897 MPI_VALIDATE_RET( f_rng != NULL );
2898
Janos Follatha0b67c22018-09-18 14:48:23 +01002899 /*
2900 * In the past our key generation aimed for an error rate of at most
2901 * 2^-80. Since this function is deprecated, aim for the same certainty
2902 * here as well.
2903 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002904 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002905}
Janos Follatha0b67c22018-09-18 14:48:23 +01002906#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002907
2908/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002909 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002910 *
Janos Follathf301d232018-08-14 13:34:01 +01002911 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2912 * be either 1024 bits or 1536 bits long, and flags must contain
2913 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002914 */
Janos Follath7c025a92018-08-14 11:08:41 +01002915int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002916 int (*f_rng)(void *, unsigned char *, size_t),
2917 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002918{
Jethro Beekman66689272018-02-14 19:24:10 -08002919#ifdef MBEDTLS_HAVE_INT64
2920// ceil(2^63.5)
2921#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2922#else
2923// ceil(2^31.5)
2924#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2925#endif
2926 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002927 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002928 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002929 mbedtls_mpi_uint r;
2930 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002931
Hanno Becker8ce11a32018-12-19 16:18:52 +00002932 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002933 MPI_VALIDATE_RET( f_rng != NULL );
2934
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002935 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2936 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002938 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002939
2940 n = BITS_TO_LIMBS( nbits );
2941
Janos Follathda31fa12018-09-03 14:45:23 +01002942 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2943 {
2944 /*
2945 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2946 */
2947 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2948 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2949 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2950 }
2951 else
2952 {
2953 /*
2954 * 2^-100 error probability, number of rounds computed based on HAC,
2955 * fact 4.48
2956 */
2957 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2958 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2959 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2960 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2961 }
2962
Jethro Beekman66689272018-02-14 19:24:10 -08002963 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002964 {
Jethro Beekman66689272018-02-14 19:24:10 -08002965 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2966 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2967 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2968
2969 k = n * biL;
2970 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2971 X->p[0] |= 1;
2972
Janos Follath7c025a92018-08-14 11:08:41 +01002973 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002974 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002975 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002977 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002978 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002979 }
Jethro Beekman66689272018-02-14 19:24:10 -08002980 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002981 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002982 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002983 * An necessary condition for Y and X = 2Y + 1 to be prime
2984 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2985 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002986 */
Jethro Beekman66689272018-02-14 19:24:10 -08002987
2988 X->p[0] |= 2;
2989
2990 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2991 if( r == 0 )
2992 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2993 else if( r == 1 )
2994 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2995
2996 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2997 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2998 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2999
3000 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003001 {
Jethro Beekman66689272018-02-14 19:24:10 -08003002 /*
3003 * First, check small factors for X and Y
3004 * before doing Miller-Rabin on any of them
3005 */
3006 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
3007 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003008 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003009 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003010 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003011 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08003012 goto cleanup;
3013
3014 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
3015 goto cleanup;
3016
3017 /*
3018 * Next candidates. We want to preserve Y = (X-1) / 2 and
3019 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3020 * so up Y by 6 and X by 12.
3021 */
3022 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
3023 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003024 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003025 }
3026 }
3027
3028cleanup:
3029
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003030 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00003031
3032 return( ret );
3033}
3034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003035#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003036
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003037#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003038
Paul Bakker23986e52011-04-24 08:57:21 +00003039#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003040
3041static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3042{
3043 { 693, 609, 21 },
3044 { 1764, 868, 28 },
3045 { 768454923, 542167814, 1 }
3046};
3047
Paul Bakker5121ce52009-01-03 21:22:43 +00003048/*
3049 * Checkup routine
3050 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003051int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00003052{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003053 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003054 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003055
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003056 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
3057 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003059 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003060 "EFE021C2645FD1DC586E69184AF4A31E" \
3061 "D5F53E93B5F123FA41680867BA110131" \
3062 "944FE7952E2517337780CB0DB80E61AA" \
3063 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003065 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003066 "B2E7EFD37075B9F03FF989C7C5051C20" \
3067 "34D2A323810251127E7BF8625A4F49A5" \
3068 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3069 "5B5C25763222FEFCCFC38B832366C29E" ) );
3070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003071 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003072 "0066A198186C18C10B2F5ED9B522752A" \
3073 "9830B69916E535C8F047518A889A43A5" \
3074 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003076 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003078 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003079 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3080 "9E857EA95A03512E2BAE7391688D264A" \
3081 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3082 "8001B72E848A38CAE1C65F78E56ABDEF" \
3083 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3084 "ECF677152EF804370C1A305CAF3B5BF1" \
3085 "30879B56C61DE584A0F53A2447A51E" ) );
3086
3087 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003088 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003090 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003091 {
3092 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003093 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003094
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003095 ret = 1;
3096 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003097 }
3098
3099 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003100 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003102 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003104 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003105 "256567336059E52CAE22925474705F39A94" ) );
3106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003107 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003108 "6613F26162223DF488E9CD48CC132C7A" \
3109 "0AC93C701B001B092E4E5B9F73BCD27B" \
3110 "9EE50D0657C77F374E903CDFA4C642" ) );
3111
3112 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003113 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003114
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003115 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3116 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003117 {
3118 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003119 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003120
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003121 ret = 1;
3122 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003123 }
3124
3125 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003126 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003128 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003130 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003131 "36E139AEA55215609D2816998ED020BB" \
3132 "BD96C37890F65171D948E9BC7CBAA4D9" \
3133 "325D24D6A3C12710F10A09FA08AB87" ) );
3134
3135 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003136 mbedtls_printf( " MPI test #3 (exp_mod): " );
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_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003152 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003153 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3154 "C3DBA76456363A10869622EAC2DD84EC" \
3155 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3156
3157 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003158 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003160 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003161 {
3162 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003163 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003164
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003165 ret = 1;
3166 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003167 }
3168
3169 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003170 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003171
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003172 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003173 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003174
Paul Bakker66d5d072014-06-17 16:39:18 +02003175 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003177 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3178 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003180 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003182 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003183 {
3184 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003185 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003186
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003187 ret = 1;
3188 goto cleanup;
3189 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003190 }
3191
3192 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003193 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003194
Paul Bakker5121ce52009-01-03 21:22:43 +00003195cleanup:
3196
3197 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003198 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003200 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3201 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003202
3203 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003204 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003205
3206 return( ret );
3207}
3208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003209#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003211#endif /* MBEDTLS_BIGNUM_C */