blob: 1a762a2d0035f295b50f62bba61e644bb7fa2f6b [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"
Hanno Beckeraef9cc42022-04-11 06:36:29 +010041#include "bignum_internal.h"
Janos Follath4614b9a2022-07-21 15:34:47 +010042#include "bignum_core.h"
Chris Jones4c5819c2021-03-03 17:45:34 +000043#include "bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050044#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000045#include "mbedtls/error.h"
Gabor Mezei22c9a6f2021-10-20 12:09:35 +020046#include "constant_time_internal.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000047
Dave Rodgman351c71b2021-12-06 17:50:53 +000048#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Gabor Mezei66669142022-08-03 12:52:26 +020061#define MPI_VALIDATE_RET( cond ) \
62 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
63#define MPI_VALIDATE( cond ) \
64 MBEDTLS_INTERNAL_VALIDATE( cond )
65
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010066#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
67
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050068/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050069static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
70{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050071 mbedtls_platform_zeroize( v, ciL * n );
72}
73
Paul Bakker5121ce52009-01-03 21:22:43 +000074/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000075 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000078{
Hanno Becker73d7d792018-12-11 10:35:51 +000079 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000080
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 X->s = 1;
82 X->n = 0;
83 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000084}
85
86/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Paul Bakker6c591fa2011-05-05 11:49:20 +000091 if( X == NULL )
92 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000093
Paul Bakker6c591fa2011-05-05 11:49:20 +000094 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000095 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +020096 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000098 }
99
Paul Bakker6c591fa2011-05-05 11:49:20 +0000100 X->s = 1;
101 X->n = 0;
102 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000103}
104
105/*
106 * Enlarge to the specified number of limbs
107 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000109{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000111 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200114 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000115
Paul Bakker5121ce52009-01-03 21:22:43 +0000116 if( X->n < nblimbs )
117 {
Simon Butcher29176892016-05-20 00:19:09 +0100118 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200119 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000120
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 if( X->p != NULL )
122 {
123 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200124 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 }
127
128 X->n = nblimbs;
129 X->p = p;
130 }
131
132 return( 0 );
133}
134
135/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100136 * Resize down as much as possible,
137 * while keeping at least the specified number of limbs
138 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100140{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100142 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000143 MPI_VALIDATE_RET( X != NULL );
144
145 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
146 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100148 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100151 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152
153 for( i = X->n - 1; i > 0; i-- )
154 if( X->p[i] != 0 )
155 break;
156 i++;
157
158 if( i < nblimbs )
159 i = nblimbs;
160
Simon Butcher29176892016-05-20 00:19:09 +0100161 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200162 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 if( X->p != NULL )
165 {
166 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200167 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100169 }
170
171 X->n = i;
172 X->p = p;
173
174 return( 0 );
175}
176
Gilles Peskineed32b572021-06-02 22:17:52 +0200177/* Resize X to have exactly n limbs and set it to 0. */
178static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
179{
180 if( limbs == 0 )
181 {
182 mbedtls_mpi_free( X );
183 return( 0 );
184 }
185 else if( X->n == limbs )
186 {
187 memset( X->p, 0, limbs * ciL );
188 X->s = 1;
189 return( 0 );
190 }
191 else
192 {
193 mbedtls_mpi_free( X );
194 return( mbedtls_mpi_grow( X, limbs ) );
195 }
196}
197
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100198/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200199 * Copy the contents of Y into X.
200 *
201 * This function is not constant-time. Leading zeros in Y may be removed.
202 *
203 * Ensure that X does not shrink. This is not guaranteed by the public API,
204 * but some code in the bignum module relies on this property, for example
205 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000206 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000208{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100209 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000210 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000211 MPI_VALIDATE_RET( X != NULL );
212 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000213
214 if( X == Y )
215 return( 0 );
216
Gilles Peskinedb420622020-01-20 21:12:50 +0100217 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200218 {
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200219 if( X->n != 0 )
220 {
221 X->s = 1;
222 memset( X->p, 0, X->n * ciL );
223 }
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200224 return( 0 );
225 }
226
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 for( i = Y->n - 1; i > 0; i-- )
228 if( Y->p[i] != 0 )
229 break;
230 i++;
231
232 X->s = Y->s;
233
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100234 if( X->n < i )
235 {
236 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
237 }
238 else
239 {
240 memset( X->p + i, 0, ( X->n - i ) * ciL );
241 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000242
Paul Bakker5121ce52009-01-03 21:22:43 +0000243 memcpy( X->p, Y->p, i * ciL );
244
245cleanup:
246
247 return( ret );
248}
249
250/*
251 * Swap the contents of X and Y
252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000254{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000256 MPI_VALIDATE( X != NULL );
257 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 memcpy( &T, X, sizeof( mbedtls_mpi ) );
260 memcpy( X, Y, sizeof( mbedtls_mpi ) );
261 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000262}
263
264/*
265 * Set value from integer
266 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000268{
Janos Follath24eed8d2019-11-22 13:21:35 +0000269 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000270 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000273 memset( X->p, 0, X->n * ciL );
274
275 X->p[0] = ( z < 0 ) ? -z : z;
276 X->s = ( z < 0 ) ? -1 : 1;
277
278cleanup:
279
280 return( ret );
281}
282
283/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000284 * Get a specific bit
285 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200286int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000287{
Hanno Becker73d7d792018-12-11 10:35:51 +0000288 MPI_VALIDATE_RET( X != NULL );
289
Paul Bakker2f5947e2011-05-18 15:47:11 +0000290 if( X->n * biL <= pos )
291 return( 0 );
292
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200293 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000294}
295
296/*
297 * Set a bit to a specific value of 0 or 1
298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000300{
301 int ret = 0;
302 size_t off = pos / biL;
303 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000304 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000305
306 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200308
Paul Bakker2f5947e2011-05-18 15:47:11 +0000309 if( X->n * biL <= pos )
310 {
311 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200312 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200314 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000315 }
316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
318 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000319
320cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200321
Paul Bakker2f5947e2011-05-18 15:47:11 +0000322 return( ret );
323}
324
325/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200326 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000329{
Paul Bakker23986e52011-04-24 08:57:21 +0000330 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000331 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000332
333 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000334 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000335 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
336 return( count );
337
338 return( 0 );
339}
340
341/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200342 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000343 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200344size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000345{
Gabor Mezei89e31462022-08-12 15:36:56 +0200346 return( mbedtls_mpi_core_bitlen( X->p, X->n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000347}
348
349/*
350 * Return the total size in bytes
351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000353{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200354 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000355}
356
357/*
358 * Convert an ASCII character to digit value
359 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000361{
362 *d = 255;
363
364 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
365 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
366 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 if( *d >= (mbedtls_mpi_uint) radix )
369 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000370
371 return( 0 );
372}
373
374/*
375 * Import from an ASCII string
376 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000378{
Janos Follath24eed8d2019-11-22 13:21:35 +0000379 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000380 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200381 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 mbedtls_mpi_uint d;
383 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000384 MPI_VALIDATE_RET( X != NULL );
385 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000386
387 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000388 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000391
Gilles Peskine7cba8592021-06-08 18:32:34 +0200392 if( s[0] == 0 )
393 {
394 mbedtls_mpi_free( X );
395 return( 0 );
396 }
397
Gilles Peskine80f56732021-04-03 18:26:13 +0200398 if( s[0] == '-' )
399 {
400 ++s;
401 sign = -1;
402 }
403
Paul Bakkerff60ee62010-03-16 21:09:09 +0000404 slen = strlen( s );
405
Paul Bakker5121ce52009-01-03 21:22:43 +0000406 if( radix == 16 )
407 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100408 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200409 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
410
Paul Bakkerff60ee62010-03-16 21:09:09 +0000411 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
414 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000415
Paul Bakker23986e52011-04-24 08:57:21 +0000416 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000417 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200419 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000420 }
421 }
422 else
423 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000425
Paul Bakkerff60ee62010-03-16 21:09:09 +0000426 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000427 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
429 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200430 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000431 }
432 }
433
Gilles Peskine80f56732021-04-03 18:26:13 +0200434 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
435 X->s = -1;
436
Paul Bakker5121ce52009-01-03 21:22:43 +0000437cleanup:
438
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
441 return( ret );
442}
443
444/*
Ron Eldora16fa292018-11-20 14:07:01 +0200445 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000446 */
Ron Eldora16fa292018-11-20 14:07:01 +0200447static int mpi_write_hlp( mbedtls_mpi *X, int radix,
448 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000449{
Janos Follath24eed8d2019-11-22 13:21:35 +0000450 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200452 size_t length = 0;
453 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
Ron Eldora16fa292018-11-20 14:07:01 +0200455 do
456 {
457 if( length >= buflen )
458 {
459 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
460 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000461
Ron Eldora16fa292018-11-20 14:07:01 +0200462 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
463 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
464 /*
465 * Write the residue in the current position, as an ASCII character.
466 */
467 if( r < 0xA )
468 *(--p_end) = (char)( '0' + r );
469 else
470 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Ron Eldora16fa292018-11-20 14:07:01 +0200472 length++;
473 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000474
Ron Eldora16fa292018-11-20 14:07:01 +0200475 memmove( *p, p_end, length );
476 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000477
478cleanup:
479
480 return( ret );
481}
482
483/*
484 * Export into an ASCII string
485 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100486int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
487 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000488{
Paul Bakker23986e52011-04-24 08:57:21 +0000489 int ret = 0;
490 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000491 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000493 MPI_VALIDATE_RET( X != NULL );
494 MPI_VALIDATE_RET( olen != NULL );
495 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000496
497 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000498 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Hanno Becker23cfea02019-02-04 09:45:07 +0000500 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
501 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
502 * `n`. If radix > 4, this might be a strict
503 * overapproximation of the number of
504 * radix-adic digits needed to present `n`. */
505 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
506 * present `n`. */
507
Janos Follath80470622019-03-06 13:43:02 +0000508 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000509 n += 1; /* Compensate for the divisions above, which round down `n`
510 * in case it's not even. */
511 n += 1; /* Potential '-'-sign. */
512 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
513 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100515 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000516 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100517 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100521 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000523
524 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000525 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000526 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000527 buflen--;
528 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
530 if( radix == 16 )
531 {
Paul Bakker23986e52011-04-24 08:57:21 +0000532 int c;
533 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000534
Paul Bakker23986e52011-04-24 08:57:21 +0000535 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000536 {
Paul Bakker23986e52011-04-24 08:57:21 +0000537 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000538 {
Paul Bakker23986e52011-04-24 08:57:21 +0000539 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000540
Paul Bakker6c343d72014-07-10 14:36:19 +0200541 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000542 continue;
543
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000544 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000545 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000546 k = 1;
547 }
548 }
549 }
550 else
551 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000553
554 if( T.s == -1 )
555 T.s = 1;
556
Ron Eldora16fa292018-11-20 14:07:01 +0200557 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000558 }
559
560 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100561 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563cleanup:
564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
567 return( ret );
568}
569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000571/*
572 * Read X from an opened file
573 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000575{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000577 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000579 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000580 * Buffer should have space for (short) label and decimal formatted MPI,
581 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000582 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Hanno Becker73d7d792018-12-11 10:35:51 +0000585 MPI_VALIDATE_RET( X != NULL );
586 MPI_VALIDATE_RET( fin != NULL );
587
588 if( radix < 2 || radix > 16 )
589 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
590
Paul Bakker5121ce52009-01-03 21:22:43 +0000591 memset( s, 0, sizeof( s ) );
592 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
595 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000596 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000598
Hanno Beckerb2034b72017-04-26 11:46:46 +0100599 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
600 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000601
602 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100603 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 if( mpi_get_digit( &d, radix, *p ) != 0 )
605 break;
606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000608}
609
610/*
611 * Write X into an opened file (or stdout if fout == NULL)
612 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000614{
Janos Follath24eed8d2019-11-22 13:21:35 +0000615 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000616 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000617 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000618 * Buffer should have space for (short) label and decimal formatted MPI,
619 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000620 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000622 MPI_VALIDATE_RET( X != NULL );
623
624 if( radix < 2 || radix > 16 )
625 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000626
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100627 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000628
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100629 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
631 if( p == NULL ) p = "";
632
633 plen = strlen( p );
634 slen = strlen( s );
635 s[slen++] = '\r';
636 s[slen++] = '\n';
637
638 if( fout != NULL )
639 {
640 if( fwrite( p, 1, plen, fout ) != plen ||
641 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 }
644 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647cleanup:
648
649 return( ret );
650}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
653/*
Janos Follatha778a942019-02-13 10:28:28 +0000654 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100655 *
656 * This function is guaranteed to return an MPI with exactly the necessary
657 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000658 */
659int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
660 const unsigned char *buf, size_t buflen )
661{
Janos Follath24eed8d2019-11-22 13:21:35 +0000662 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000663 size_t const limbs = CHARS_TO_LIMBS( buflen );
664
665 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +0200666 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000667
Janos Follath5f016652022-07-22 16:18:41 +0100668 MBEDTLS_MPI_CHK( mbedtls_mpi_core_read_le( X->p, X->n, buf, buflen ) );
Janos Follatha778a942019-02-13 10:28:28 +0000669
670cleanup:
671
Janos Follath171a7ef2019-02-15 16:17:45 +0000672 /*
673 * This function is also used to import keys. However, wiping the buffers
674 * upon failure is not necessary because failure only can happen before any
675 * input is copied.
676 */
Janos Follatha778a942019-02-13 10:28:28 +0000677 return( ret );
678}
679
680/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100682 *
683 * This function is guaranteed to return an MPI with exactly the necessary
684 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000685 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000687{
Janos Follath24eed8d2019-11-22 13:21:35 +0000688 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath5f016652022-07-22 16:18:41 +0100689 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
Hanno Becker8ce11a32018-12-19 16:18:52 +0000691 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000692 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
693
Hanno Becker073c1992017-10-17 15:17:27 +0100694 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +0200695 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000696
Janos Follath5f016652022-07-22 16:18:41 +0100697 MBEDTLS_MPI_CHK( mbedtls_mpi_core_read_be( X->p, X->n, buf, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699cleanup:
700
Janos Follath171a7ef2019-02-15 16:17:45 +0000701 /*
702 * This function is also used to import keys. However, wiping the buffers
703 * upon failure is not necessary because failure only can happen before any
704 * input is copied.
705 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000706 return( ret );
707}
708
709/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000710 * Export X into unsigned binary data, little endian
711 */
712int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
713 unsigned char *buf, size_t buflen )
714{
Janos Follath5f016652022-07-22 16:18:41 +0100715 return( mbedtls_mpi_core_write_le( X->p, X->n, buf, buflen) );
Janos Follathe344d0f2019-02-19 16:17:40 +0000716}
717
718/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000719 * Export X into unsigned binary data, big endian
720 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100721int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
722 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000723{
Janos Follath5f016652022-07-22 16:18:41 +0100724 return( mbedtls_mpi_core_write_be( X->p, X->n, buf, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000725}
726
727/*
728 * Left-shift: X <<= count
729 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000731{
Janos Follath24eed8d2019-11-22 13:21:35 +0000732 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000733 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000735 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000736
737 v0 = count / (biL );
738 t1 = count & (biL - 1);
739
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200740 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000741
Paul Bakkerf9688572011-05-05 10:00:45 +0000742 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000744
745 ret = 0;
746
747 /*
748 * shift by count / limb_size
749 */
750 if( v0 > 0 )
751 {
Paul Bakker23986e52011-04-24 08:57:21 +0000752 for( i = X->n; i > v0; i-- )
753 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000754
Paul Bakker23986e52011-04-24 08:57:21 +0000755 for( ; i > 0; i-- )
756 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000757 }
758
759 /*
760 * shift by count % limb_size
761 */
762 if( t1 > 0 )
763 {
764 for( i = v0; i < X->n; i++ )
765 {
766 r1 = X->p[i] >> (biL - t1);
767 X->p[i] <<= t1;
768 X->p[i] |= r0;
769 r0 = r1;
770 }
771 }
772
773cleanup:
774
775 return( ret );
776}
777
778/*
779 * Right-shift: X >>= count
780 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000782{
Paul Bakker23986e52011-04-24 08:57:21 +0000783 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200784 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000785 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000786
787 v0 = count / biL;
788 v1 = count & (biL - 1);
789
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100790 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200791 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100792
Paul Bakker5121ce52009-01-03 21:22:43 +0000793 /*
794 * shift by count / limb_size
795 */
796 if( v0 > 0 )
797 {
798 for( i = 0; i < X->n - v0; i++ )
799 X->p[i] = X->p[i + v0];
800
801 for( ; i < X->n; i++ )
802 X->p[i] = 0;
803 }
804
805 /*
806 * shift by count % limb_size
807 */
808 if( v1 > 0 )
809 {
Paul Bakker23986e52011-04-24 08:57:21 +0000810 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000811 {
Paul Bakker23986e52011-04-24 08:57:21 +0000812 r1 = X->p[i - 1] << (biL - v1);
813 X->p[i - 1] >>= v1;
814 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815 r0 = r1;
816 }
817 }
818
819 return( 0 );
820}
821
822/*
823 * Compare unsigned values
824 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000826{
Paul Bakker23986e52011-04-24 08:57:21 +0000827 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000828 MPI_VALIDATE_RET( X != NULL );
829 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000830
Paul Bakker23986e52011-04-24 08:57:21 +0000831 for( i = X->n; i > 0; i-- )
832 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 break;
834
Paul Bakker23986e52011-04-24 08:57:21 +0000835 for( j = Y->n; j > 0; j-- )
836 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000837 break;
838
Paul Bakker23986e52011-04-24 08:57:21 +0000839 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000840 return( 0 );
841
842 if( i > j ) return( 1 );
843 if( j > i ) return( -1 );
844
Paul Bakker23986e52011-04-24 08:57:21 +0000845 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000846 {
Paul Bakker23986e52011-04-24 08:57:21 +0000847 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
848 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000849 }
850
851 return( 0 );
852}
853
854/*
855 * Compare signed values
856 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000858{
Paul Bakker23986e52011-04-24 08:57:21 +0000859 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000860 MPI_VALIDATE_RET( X != NULL );
861 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000862
Paul Bakker23986e52011-04-24 08:57:21 +0000863 for( i = X->n; i > 0; i-- )
864 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000865 break;
866
Paul Bakker23986e52011-04-24 08:57:21 +0000867 for( j = Y->n; j > 0; j-- )
868 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000869 break;
870
Paul Bakker23986e52011-04-24 08:57:21 +0000871 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872 return( 0 );
873
874 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000875 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000876
877 if( X->s > 0 && Y->s < 0 ) return( 1 );
878 if( Y->s > 0 && X->s < 0 ) return( -1 );
879
Paul Bakker23986e52011-04-24 08:57:21 +0000880 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000881 {
Paul Bakker23986e52011-04-24 08:57:21 +0000882 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
883 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 }
885
886 return( 0 );
887}
888
Janos Follathee6abce2019-09-05 14:47:19 +0100889/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000890 * Compare signed values
891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000893{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 mbedtls_mpi Y;
895 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +0000896 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000897
898 *p = ( z < 0 ) ? -z : z;
899 Y.s = ( z < 0 ) ? -1 : 1;
900 Y.n = 1;
901 Y.p = p;
902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000904}
905
906/*
907 * Unsigned addition: X = |A| + |B| (HAC 14.7)
908 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200909int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000910{
Janos Follath24eed8d2019-11-22 13:21:35 +0000911 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000912 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100913 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000914 MPI_VALIDATE_RET( X != NULL );
915 MPI_VALIDATE_RET( A != NULL );
916 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
918 if( X == B )
919 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000921 }
922
923 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200925
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000926 /*
927 * X should always be positive as a result of unsigned additions.
928 */
929 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000930
Paul Bakker23986e52011-04-24 08:57:21 +0000931 for( j = B->n; j > 0; j-- )
932 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 break;
934
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000936
937 o = B->p; p = X->p; c = 0;
938
Janos Follath6c922682015-10-30 17:43:11 +0100939 /*
940 * tmp is used because it might happen that p == o
941 */
Paul Bakker23986e52011-04-24 08:57:21 +0000942 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 {
Janos Follath6c922682015-10-30 17:43:11 +0100944 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000945 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100946 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000947 }
948
949 while( c != 0 )
950 {
951 if( i >= X->n )
952 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 p = X->p + i;
955 }
956
Paul Bakker2d319fd2012-09-16 21:34:26 +0000957 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000958 }
959
960cleanup:
961
962 return( ret );
963}
964
Gilles Peskine09ec10a2020-06-09 10:39:38 +0200965/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200966 * Helper for mbedtls_mpi subtraction.
967 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200968 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200969 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200970 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200971 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200972 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200973 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200974 * \param n Number of limbs of \p d, \p l and \p r.
975 * \param[out] d The result of the subtraction.
976 * \param[in] l The left operand.
977 * \param[in] r The right operand.
978 *
979 * \return 1 if `l < r`.
980 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +0000981 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200982static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
983 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200984 const mbedtls_mpi_uint *l,
985 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +0000986{
Paul Bakker23986e52011-04-24 08:57:21 +0000987 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200988 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +0000989
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200990 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000991 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200992 z = ( l[i] < c ); t = l[i] - c;
993 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +0000994 }
995
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200996 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +0000997}
998
999/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001000 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001002int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001003{
Janos Follath24eed8d2019-11-22 13:21:35 +00001004 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001005 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001006 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001007 MPI_VALIDATE_RET( X != NULL );
1008 MPI_VALIDATE_RET( A != NULL );
1009 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001010
Paul Bakker23986e52011-04-24 08:57:21 +00001011 for( n = B->n; n > 0; n-- )
1012 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001013 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001014 if( n > A->n )
1015 {
1016 /* B >= (2^ciL)^n > A */
1017 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1018 goto cleanup;
1019 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001020
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001021 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1022
1023 /* Set the high limbs of X to match A. Don't touch the lower limbs
1024 * because X might be aliased to B, and we must not overwrite the
1025 * significant digits of B. */
1026 if( A->n > n )
1027 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1028 if( X->n > A->n )
1029 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1030
1031 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001032 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001033 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001034 /* Propagate the carry to the first nonzero limb of X. */
1035 for( ; n < X->n && X->p[n] == 0; n++ )
1036 --X->p[n];
1037 /* If we ran out of space for the carry, it means that the result
1038 * is negative. */
1039 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001040 {
1041 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1042 goto cleanup;
1043 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001044 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001045 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001046
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001047 /* X should always be positive as a result of unsigned subtractions. */
1048 X->s = 1;
1049
Paul Bakker5121ce52009-01-03 21:22:43 +00001050cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 return( ret );
1052}
1053
1054/*
1055 * Signed addition: X = A + B
1056 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001058{
Hanno Becker73d7d792018-12-11 10:35:51 +00001059 int ret, s;
1060 MPI_VALIDATE_RET( X != NULL );
1061 MPI_VALIDATE_RET( A != NULL );
1062 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001063
Hanno Becker73d7d792018-12-11 10:35:51 +00001064 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001065 if( A->s * B->s < 0 )
1066 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001067 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001068 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 X->s = s;
1071 }
1072 else
1073 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 X->s = -s;
1076 }
1077 }
1078 else
1079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 X->s = s;
1082 }
1083
1084cleanup:
1085
1086 return( ret );
1087}
1088
1089/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001090 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001093{
Hanno Becker73d7d792018-12-11 10:35:51 +00001094 int ret, s;
1095 MPI_VALIDATE_RET( X != NULL );
1096 MPI_VALIDATE_RET( A != NULL );
1097 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001098
Hanno Becker73d7d792018-12-11 10:35:51 +00001099 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 if( A->s * B->s > 0 )
1101 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001103 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001104 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001105 X->s = s;
1106 }
1107 else
1108 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 X->s = -s;
1111 }
1112 }
1113 else
1114 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001116 X->s = s;
1117 }
1118
1119cleanup:
1120
1121 return( ret );
1122}
1123
1124/*
1125 * Signed addition: X = A + b
1126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001128{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001129 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001131 MPI_VALIDATE_RET( X != NULL );
1132 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133
1134 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001135 B.s = ( b < 0 ) ? -1 : 1;
1136 B.n = 1;
1137 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001138
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001139 return( mbedtls_mpi_add_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001140}
1141
1142/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001143 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001145int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001146{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001147 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001148 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001149 MPI_VALIDATE_RET( X != NULL );
1150 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001151
1152 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001153 B.s = ( b < 0 ) ? -1 : 1;
1154 B.n = 1;
1155 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001156
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001157 return( mbedtls_mpi_sub_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001158}
1159
Hanno Becker284d7782022-04-11 09:19:24 +01001160mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len,
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001161 const mbedtls_mpi_uint *s, size_t s_len,
1162 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001163{
Hanno Beckere7f14a32022-04-06 06:11:26 +01001164 mbedtls_mpi_uint c = 0; /* carry */
Hanno Becker5d4ceeb2022-04-11 09:46:47 +01001165 size_t excess_len = d_len - s_len;
Hanno Beckerdefe5692022-04-06 06:12:09 +01001166
Hanno Becker63eb28c2022-04-06 11:30:51 +01001167 size_t steps_x8 = s_len / 8;
1168 size_t steps_x1 = s_len & 7;
1169
1170 while( steps_x8-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 {
Hanno Beckereacf3b92022-04-06 11:25:22 +01001172 MULADDC_X8_INIT
1173 MULADDC_X8_CORE
1174 MULADDC_X8_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001175 }
1176
Hanno Becker63eb28c2022-04-06 11:30:51 +01001177 while( steps_x1-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001178 {
Hanno Beckereacf3b92022-04-06 11:25:22 +01001179 MULADDC_X1_INIT
1180 MULADDC_X1_CORE
1181 MULADDC_X1_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001182 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
Hanno Becker284d7782022-04-11 09:19:24 +01001184 while( excess_len-- )
Gilles Peskine8e464c42020-07-24 00:08:38 +02001185 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001186 *d += c; c = ( *d < c ); d++;
1187 }
Hanno Beckerdefe5692022-04-06 06:12:09 +01001188
1189 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001190}
1191
1192/*
1193 * Baseline multiplication: X = A * B (HAC 14.12)
1194 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001196{
Janos Follath24eed8d2019-11-22 13:21:35 +00001197 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001198 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001199 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001200 int result_is_zero = 0;
Hanno Becker73d7d792018-12-11 10:35:51 +00001201 MPI_VALIDATE_RET( X != NULL );
1202 MPI_VALIDATE_RET( A != NULL );
1203 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1208 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
Hanno Beckerda763de2022-04-13 06:50:02 +01001210 for( i = A->n; i > 0; i-- )
1211 if( A->p[i - 1] != 0 )
1212 break;
1213 if( i == 0 )
1214 result_is_zero = 1;
1215
1216 for( j = B->n; j > 0; j-- )
1217 if( B->p[j - 1] != 0 )
1218 break;
1219 if( j == 0 )
1220 result_is_zero = 1;
1221
1222 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
Hanno Becker1772e052022-04-13 06:51:40 +01001225 for( size_t k = 0; k < j; k++ )
Hanno Beckerfee261a2022-04-06 06:20:22 +01001226 {
1227 /* We know that there cannot be any carry-out since we're
1228 * iterating from bottom to top. */
Hanno Beckerda763de2022-04-13 06:50:02 +01001229 (void) mbedtls_mpi_core_mla( X->p + k, i + 1,
1230 A->p, i,
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001231 B->p[k] );
Hanno Beckerfee261a2022-04-06 06:20:22 +01001232 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001233
Hanno Beckerda763de2022-04-13 06:50:02 +01001234 /* If the result is 0, we don't shortcut the operation, which reduces
1235 * but does not eliminate side channels leaking the zero-ness. We do
1236 * need to take care to set the sign bit properly since the library does
1237 * not fully support an MPI object with a value of 0 and s == -1. */
1238 if( result_is_zero )
1239 X->s = 1;
1240 else
1241 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001242
1243cleanup:
1244
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001246
1247 return( ret );
1248}
1249
1250/*
1251 * Baseline multiplication: X = A * b
1252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001254{
Hanno Becker73d7d792018-12-11 10:35:51 +00001255 MPI_VALIDATE_RET( X != NULL );
1256 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001257
Hanno Becker35771312022-04-14 11:52:11 +01001258 size_t n = A->n;
1259 while( n > 0 && A->p[n - 1] == 0 )
1260 --n;
1261
Hanno Becker74a11a32022-04-06 06:27:00 +01001262 /* The general method below doesn't work if b==0. */
Hanno Becker35771312022-04-14 11:52:11 +01001263 if( b == 0 || n == 0 )
Paul Elliott986b55a2021-04-20 21:46:29 +01001264 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001265
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001266 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001267 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001268 /* In general, A * b requires 1 limb more than b. If
1269 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1270 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001271 * copy() will take care of the growth if needed. However, experimentally,
1272 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001273 * calls to calloc() in ECP code, presumably because it reuses the
1274 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001275 * grow to its final size.
1276 *
1277 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1278 * A,X can be the same. */
Hanno Becker35771312022-04-14 11:52:11 +01001279 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001280 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Hanno Becker35771312022-04-14 11:52:11 +01001281 mbedtls_mpi_core_mla( X->p, X->n, A->p, n, b - 1 );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001282
1283cleanup:
1284 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001285}
1286
1287/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001288 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1289 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001290 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001291static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1292 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001293{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001294#if defined(MBEDTLS_HAVE_UDBL)
1295 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001296#else
Simon Butcher9803d072016-01-03 00:24:34 +00001297 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1298 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001299 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1300 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001301 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001302#endif
1303
Simon Butcher15b15d12015-11-26 19:35:03 +00001304 /*
1305 * Check for overflow
1306 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001307 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001308 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001309 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001310
Simon Butcherf5ba0452015-12-27 23:01:55 +00001311 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001312 }
1313
1314#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001315 dividend = (mbedtls_t_udbl) u1 << biL;
1316 dividend |= (mbedtls_t_udbl) u0;
1317 quotient = dividend / d;
1318 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1319 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1320
1321 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001322 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001323
1324 return (mbedtls_mpi_uint) quotient;
1325#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001326
1327 /*
1328 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1329 * Vol. 2 - Seminumerical Algorithms, Knuth
1330 */
1331
1332 /*
1333 * Normalize the divisor, d, and dividend, u0, u1
1334 */
Janos Follath4670f882022-07-21 18:25:42 +01001335 s = mbedtls_mpi_core_clz( d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001336 d = d << s;
1337
1338 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001339 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001340 u0 = u0 << s;
1341
1342 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001343 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001344
1345 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001346 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001347
1348 /*
1349 * Find the first quotient and remainder
1350 */
1351 q1 = u1 / d1;
1352 r0 = u1 - d1 * q1;
1353
1354 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1355 {
1356 q1 -= 1;
1357 r0 += d1;
1358
1359 if ( r0 >= radix ) break;
1360 }
1361
Simon Butcherf5ba0452015-12-27 23:01:55 +00001362 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001363 q0 = rAX / d1;
1364 r0 = rAX - q0 * d1;
1365
1366 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1367 {
1368 q0 -= 1;
1369 r0 += d1;
1370
1371 if ( r0 >= radix ) break;
1372 }
1373
1374 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001375 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001376
1377 quotient = q1 * radix + q0;
1378
1379 return quotient;
1380#endif
1381}
1382
1383/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001385 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001386int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1387 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388{
Janos Follath24eed8d2019-11-22 13:21:35 +00001389 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001390 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001392 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001393 MPI_VALIDATE_RET( A != NULL );
1394 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1397 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001400 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001401 /*
1402 * Avoid dynamic memory allocations for constant-size T2.
1403 *
1404 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1405 * so nobody increase the size of the MPI and we're safe to use an on-stack
1406 * buffer.
1407 */
Alexander K35d6d462019-10-31 14:46:45 +03001408 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001409 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1410 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1415 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416 return( 0 );
1417 }
1418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001419 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1420 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421 X.s = Y.s = 1;
1422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1424 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001425 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001426
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001427 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001428 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001429 {
1430 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001431 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1432 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 }
1434 else k = 0;
1435
1436 n = X.n - 1;
1437 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001441 {
1442 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001444 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001445 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001446
1447 for( i = n; i > t ; i-- )
1448 {
1449 if( X.p[i] >= Y.p[t] )
1450 Z.p[i - t - 1] = ~0;
1451 else
1452 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001453 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1454 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001455 }
1456
Alexander K35d6d462019-10-31 14:46:45 +03001457 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1458 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1459 T2.p[2] = X.p[i];
1460
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 Z.p[i - t - 1]++;
1462 do
1463 {
1464 Z.p[i - t - 1]--;
1465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001467 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001468 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001470 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1474 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1475 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001478 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001479 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1480 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1481 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 Z.p[i - t - 1]--;
1483 }
1484 }
1485
1486 if( Q != NULL )
1487 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489 Q->s = A->s * B->s;
1490 }
1491
1492 if( R != NULL )
1493 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001495 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001498 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001499 R->s = 1;
1500 }
1501
1502cleanup:
1503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001505 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001506 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507
1508 return( ret );
1509}
1510
1511/*
1512 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001513 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001514int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1515 const mbedtls_mpi *A,
1516 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001517{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001518 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001520 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521
1522 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001523 B.s = ( b < 0 ) ? -1 : 1;
1524 B.n = 1;
1525 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001527 return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001528}
1529
1530/*
1531 * Modulo: R = A mod B
1532 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001534{
Janos Follath24eed8d2019-11-22 13:21:35 +00001535 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001536 MPI_VALIDATE_RET( R != NULL );
1537 MPI_VALIDATE_RET( A != NULL );
1538 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1541 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1546 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1549 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
1551cleanup:
1552
1553 return( ret );
1554}
1555
1556/*
1557 * Modulo: r = A mod b
1558 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001559int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001560{
Paul Bakker23986e52011-04-24 08:57:21 +00001561 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001563 MPI_VALIDATE_RET( r != NULL );
1564 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001565
1566 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001568
1569 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001570 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
1572 /*
1573 * handle trivial cases
1574 */
Gilles Peskineae25bb02022-06-09 19:32:46 +02001575 if( b == 1 || A->n == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 {
1577 *r = 0;
1578 return( 0 );
1579 }
1580
1581 if( b == 2 )
1582 {
1583 *r = A->p[0] & 1;
1584 return( 0 );
1585 }
1586
1587 /*
1588 * general case
1589 */
Paul Bakker23986e52011-04-24 08:57:21 +00001590 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001591 {
Paul Bakker23986e52011-04-24 08:57:21 +00001592 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001593 y = ( y << biH ) | ( x >> biH );
1594 z = y / b;
1595 y -= z * b;
1596
1597 x <<= biH;
1598 y = ( y << biH ) | ( x >> biH );
1599 z = y / b;
1600 y -= z * b;
1601 }
1602
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001603 /*
1604 * If A is negative, then the current y represents a negative value.
1605 * Flipping it to the positive side.
1606 */
1607 if( A->s < 0 && y != 0 )
1608 y = b - y;
1609
Paul Bakker5121ce52009-01-03 21:22:43 +00001610 *r = y;
1611
1612 return( 0 );
1613}
1614
1615/*
1616 * Fast Montgomery initialization (thanks to Tom St Denis)
1617 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001619{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001621 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001622
1623 x = m0;
1624 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001625
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001626 for( i = biL; i >= 8; i /= 2 )
1627 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001628
1629 *mm = ~x + 1;
1630}
1631
Gilles Peskine2a82f722020-06-04 15:00:49 +02001632/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1633 *
1634 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02001635 * It must have at least as many limbs as N
1636 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02001637 * On successful completion, A contains the result of
1638 * the multiplication A * B * R^-1 mod N where
1639 * R = (2^ciL)^n.
1640 * \param[in] B One of the numbers to multiply.
1641 * It must be nonzero and must not have more limbs than N
1642 * (B->n <= N->n).
1643 * \param[in] N The modulo. N must be odd.
1644 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1645 * This is -N^-1 mod 2^ciL.
1646 * \param[in,out] T A bignum for temporary storage.
Hanno Beckere1417022022-04-06 06:45:45 +01001647 * It must be at least twice the limb size of N plus 1
1648 * (T->n >= 2 * N->n + 1).
Gilles Peskine2a82f722020-06-04 15:00:49 +02001649 * Its initial content is unused and
1650 * its final content is indeterminate.
1651 * Note that unlike the usual convention in the library
1652 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001654static 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 +02001655 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001656{
Hanno Becker0235f752022-04-12 10:54:46 +01001657 size_t n, m;
1658 mbedtls_mpi_uint *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
1660 memset( T->p, 0, T->n * ciL );
1661
1662 d = T->p;
1663 n = N->n;
1664 m = ( B->n < n ) ? B->n : n;
1665
Hanno Becker0235f752022-04-12 10:54:46 +01001666 for( size_t i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001667 {
Hanno Becker0235f752022-04-12 10:54:46 +01001668 mbedtls_mpi_uint u0, u1;
1669
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 /*
1671 * T = (T + u0*B + u1*N) / 2^biL
1672 */
1673 u0 = A->p[i];
1674 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1675
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001676 (void) mbedtls_mpi_core_mla( d, n + 2,
1677 B->p, m,
1678 u0 );
1679 (void) mbedtls_mpi_core_mla( d, n + 2,
1680 N->p, n,
1681 u1 );
Hanno Beckere1417022022-04-06 06:45:45 +01001682 d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001683 }
1684
Gilles Peskine221626f2020-06-08 22:37:50 +02001685 /* At this point, d is either the desired result or the desired result
1686 * plus N. We now potentially subtract N, avoiding leaking whether the
1687 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001688
Gilles Peskine221626f2020-06-08 22:37:50 +02001689 /* Copy the n least significant limbs of d to A, so that
1690 * A = d if d < N (recall that N has n limbs). */
1691 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001692 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02001693 * do the calculation without using conditional tests. */
1694 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02001695 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001696 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02001697 /* If d0 < N then d < (2^biL)^n
1698 * so d[n] == 0 and we want to keep A as it is.
1699 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1700 * so d[n] == 1 and we want to set A to the result of the subtraction
1701 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1702 * This exactly corresponds to a conditional assignment. */
Gabor Mezei90437e32021-10-20 11:59:27 +02001703 mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704}
1705
1706/*
1707 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001708 *
1709 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001710 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001711static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1712 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001713{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 mbedtls_mpi_uint z = 1;
1715 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001716
Paul Bakker8ddb6452013-02-27 14:56:33 +01001717 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001718 U.p = &z;
1719
Gilles Peskine4e91d472020-06-04 20:55:15 +02001720 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721}
1722
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001723/**
1724 * Select an MPI from a table without leaking the index.
1725 *
1726 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1727 * reads the entire table in order to avoid leaking the value of idx to an
1728 * attacker able to observe memory access patterns.
1729 *
1730 * \param[out] R Where to write the selected MPI.
1731 * \param[in] T The table to read from.
1732 * \param[in] T_size The number of elements in the table.
1733 * \param[in] idx The index of the element to select;
1734 * this must satisfy 0 <= idx < T_size.
1735 *
1736 * \return \c 0 on success, or a negative error code.
1737 */
1738static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
1739{
1740 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1741
1742 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001743 {
1744 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
Gabor Mezei90437e32021-10-20 11:59:27 +02001745 (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001746 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001747
1748cleanup:
1749 return( ret );
1750}
1751
Paul Bakker5121ce52009-01-03 21:22:43 +00001752/*
1753 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1754 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001755int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1756 const mbedtls_mpi *E, const mbedtls_mpi *N,
Yuto Takano538a0cb2021-07-14 10:20:09 +01001757 mbedtls_mpi *prec_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001758{
Janos Follath24eed8d2019-11-22 13:21:35 +00001759 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001760 size_t wbits, wsize, one = 1;
1761 size_t i, j, nblimbs;
1762 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001764 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001765 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001766
Hanno Becker73d7d792018-12-11 10:35:51 +00001767 MPI_VALIDATE_RET( X != NULL );
1768 MPI_VALIDATE_RET( A != NULL );
1769 MPI_VALIDATE_RET( E != NULL );
1770 MPI_VALIDATE_RET( N != NULL );
1771
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001772 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001773 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001774
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001775 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1776 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001777
Chris Jones9246d042020-11-25 15:12:39 +00001778 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
1779 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
1780 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1781
Paul Bakkerf6198c12012-05-16 08:02:29 +00001782 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 * Init temps and window size
1784 */
1785 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1787 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001788 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789 memset( W, 0, sizeof( W ) );
1790
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001791 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001792
1793 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1794 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1795
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001796#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1798 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001799#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001800
Paul Bakker5121ce52009-01-03 21:22:43 +00001801 j = N->n + 1;
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001802 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
1803 * and mpi_montred() calls later. Here we ensure that W[1] and X are
1804 * large enough, and later we'll grow other W[i] to the same length.
1805 * They must not be shrunk midway through this function!
1806 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1808 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1809 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
1811 /*
Paul Bakker50546922012-05-19 08:40:49 +00001812 * Compensate for negative A (and correct at the end)
1813 */
1814 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001815 if( neg )
1816 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001818 Apos.s = 1;
1819 A = &Apos;
1820 }
1821
1822 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001823 * If 1st call, pre-compute R^2 mod N
1824 */
Yuto Takano538a0cb2021-07-14 10:20:09 +01001825 if( prec_RR == NULL || prec_RR->p == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00001826 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1828 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1829 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001830
Yuto Takano538a0cb2021-07-14 10:20:09 +01001831 if( prec_RR != NULL )
1832 memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 }
1834 else
Yuto Takano538a0cb2021-07-14 10:20:09 +01001835 memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
1837 /*
1838 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1839 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001841 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001843 /* This should be a no-op because W[1] is already that large before
1844 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
1845 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine2aa3f162021-06-15 21:22:48 +02001846 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001847 }
Paul Bakkerc2024f42014-01-23 20:38:35 +01001848 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001851 /* Note that this is safe because W[1] always has at least N->n limbs
1852 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001853 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
1855 /*
1856 * X = R^2 * R^-1 mod N = R mod N
1857 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02001859 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
1861 if( wsize > 1 )
1862 {
1863 /*
1864 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1865 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001866 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1869 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001870
1871 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02001872 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001873
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 /*
1875 * W[i] = W[i - 1] * W[1]
1876 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001877 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
Gilles Peskine4e91d472020-06-04 20:55:15 +02001882 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883 }
1884 }
1885
1886 nblimbs = E->n;
1887 bufsize = 0;
1888 nbits = 0;
1889 wbits = 0;
1890 state = 0;
1891
1892 while( 1 )
1893 {
1894 if( bufsize == 0 )
1895 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001896 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 break;
1898
Paul Bakker0d7702c2013-10-29 16:18:35 +01001899 nblimbs--;
1900
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 }
1903
1904 bufsize--;
1905
1906 ei = (E->p[nblimbs] >> bufsize) & 1;
1907
1908 /*
1909 * skip leading 0s
1910 */
1911 if( ei == 0 && state == 0 )
1912 continue;
1913
1914 if( ei == 0 && state == 1 )
1915 {
1916 /*
1917 * out of window, square X
1918 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001919 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 continue;
1921 }
1922
1923 /*
1924 * add ei to current window
1925 */
1926 state = 2;
1927
1928 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001929 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
1931 if( nbits == wsize )
1932 {
1933 /*
1934 * X = X^wsize R^-1 mod N
1935 */
1936 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02001937 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
1939 /*
1940 * X = X * W[wbits] R^-1 mod N
1941 */
Manuel Pégourié-Gonnarde22176e2021-06-10 09:34:00 +02001942 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001943 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
1945 state--;
1946 nbits = 0;
1947 wbits = 0;
1948 }
1949 }
1950
1951 /*
1952 * process the remaining bits
1953 */
1954 for( i = 0; i < nbits; i++ )
1955 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02001956 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957
1958 wbits <<= 1;
1959
Paul Bakker66d5d072014-06-17 16:39:18 +02001960 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02001961 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 }
1963
1964 /*
1965 * X = A^E * R * R^-1 mod N = A^E mod N
1966 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001967 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
Hanno Beckera4af1c42017-04-18 09:07:45 +01001969 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001970 {
1971 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001973 }
1974
Paul Bakker5121ce52009-01-03 21:22:43 +00001975cleanup:
1976
Paul Bakker66d5d072014-06-17 16:39:18 +02001977 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001981 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001982
Yuto Takano538a0cb2021-07-14 10:20:09 +01001983 if( prec_RR == NULL || prec_RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
1986 return( ret );
1987}
1988
Paul Bakker5121ce52009-01-03 21:22:43 +00001989/*
1990 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1991 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001993{
Janos Follath24eed8d2019-11-22 13:21:35 +00001994 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001995 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03001996 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001997
Hanno Becker73d7d792018-12-11 10:35:51 +00001998 MPI_VALIDATE_RET( G != NULL );
1999 MPI_VALIDATE_RET( A != NULL );
2000 MPI_VALIDATE_RET( B != NULL );
2001
Alexander Ke8ad49f2019-08-16 16:16:07 +03002002 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002004 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2005 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 lz = mbedtls_mpi_lsb( &TA );
2008 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002009
Gilles Peskine27253bc2021-06-09 13:26:43 +02002010 /* The loop below gives the correct result when A==0 but not when B==0.
2011 * So have a special case for B==0. Leverage the fact that we just
2012 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2013 * slightly more efficient than cmp_int(). */
2014 if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2015 {
2016 ret = mbedtls_mpi_copy( G, A );
2017 goto cleanup;
2018 }
2019
Paul Bakker66d5d072014-06-17 16:39:18 +02002020 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002021 lz = lzt;
2022
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 TA.s = TB.s = 1;
2024
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002025 /* We mostly follow the procedure described in HAC 14.54, but with some
2026 * minor differences:
2027 * - Sequences of multiplications or divisions by 2 are grouped into a
2028 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002029 * - The procedure in HAC assumes that 0 < TB <= TA.
2030 * - The condition TB <= TA is not actually necessary for correctness.
2031 * TA and TB have symmetric roles except for the loop termination
2032 * condition, and the shifts at the beginning of the loop body
2033 * remove any significance from the ordering of TA vs TB before
2034 * the shifts.
2035 * - If TA = 0, the loop goes through 0 iterations and the result is
2036 * correctly TB.
2037 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002038 *
2039 * For the correctness proof below, decompose the original values of
2040 * A and B as
2041 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2042 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2043 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2044 * and gcd(A',B') is odd or 0.
2045 *
2046 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2047 * The code maintains the following invariant:
2048 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002049 */
2050
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002051 /* Proof that the loop terminates:
2052 * At each iteration, either the right-shift by 1 is made on a nonzero
2053 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2054 * by at least 1, or the right-shift by 1 is made on zero and then
2055 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2056 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2057 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002059 {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002060 /* Divisions by 2 preserve the invariant (I). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2062 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002063
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002064 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2065 * TA-TB is even so the division by 2 has an integer result.
2066 * Invariant (I) is preserved since any odd divisor of both TA and TB
2067 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08002068 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002069 * divides TA.
2070 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002072 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2074 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002075 }
2076 else
2077 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2079 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002080 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002081 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002082 }
2083
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002084 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2085 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2086 * - If there was at least one loop iteration, then one of TA or TB is odd,
2087 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2088 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2089 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002090 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002091 */
2092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2094 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095
2096cleanup:
2097
Alexander Ke8ad49f2019-08-16 16:16:07 +03002098 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099
2100 return( ret );
2101}
2102
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002103/* Fill X with n_bytes random bytes.
2104 * X must already have room for those bytes.
Gilles Peskineafb2bd22021-06-03 11:51:09 +02002105 * The ordering of the bytes returned from the RNG is suitable for
2106 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskineebe9b6a2021-04-13 21:55:35 +02002107 * The size and sign of X are unchanged.
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002108 * n_bytes must not be 0.
2109 */
2110static int mpi_fill_random_internal(
2111 mbedtls_mpi *X, size_t n_bytes,
2112 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2113{
2114 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2115 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2116 const size_t overhead = ( limbs * ciL ) - n_bytes;
2117
2118 if( X->n < limbs )
2119 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002120
Gilles Peskineebe9b6a2021-04-13 21:55:35 +02002121 memset( X->p, 0, overhead );
2122 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002123 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
Janos Follath4670f882022-07-21 18:25:42 +01002124 mbedtls_mpi_core_bigendian_to_host( X->p, limbs );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002125
2126cleanup:
2127 return( ret );
2128}
2129
Paul Bakker33dc46b2014-04-30 16:11:39 +02002130/*
2131 * Fill X with size bytes of random.
2132 *
2133 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002134 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002135 * deterministic, eg for tests).
2136 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002137int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002138 int (*f_rng)(void *, unsigned char *, size_t),
2139 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002140{
Janos Follath24eed8d2019-11-22 13:21:35 +00002141 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002142 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002143
Hanno Becker8ce11a32018-12-19 16:18:52 +00002144 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002145 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002146
Hanno Beckerda1655a2017-10-18 14:21:44 +01002147 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +02002148 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002149 if( size == 0 )
2150 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002151
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002152 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002153
2154cleanup:
2155 return( ret );
2156}
2157
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002158int mbedtls_mpi_random( mbedtls_mpi *X,
2159 mbedtls_mpi_sint min,
2160 const mbedtls_mpi *N,
2161 int (*f_rng)(void *, unsigned char *, size_t),
2162 void *p_rng )
2163{
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002164 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee5381682021-04-13 21:23:25 +02002165 int count;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002166 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002167 size_t n_bits = mbedtls_mpi_bitlen( N );
2168 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002169 mbedtls_mpi lower_bound;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002170
Gilles Peskine1e918f42021-03-29 22:14:51 +02002171 if( min < 0 )
2172 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2173 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2174 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2175
Gilles Peskinee5381682021-04-13 21:23:25 +02002176 /*
2177 * When min == 0, each try has at worst a probability 1/2 of failing
2178 * (the msb has a probability 1/2 of being 0, and then the result will
2179 * be < N), so after 30 tries failure probability is a most 2**(-30).
2180 *
2181 * When N is just below a power of 2, as is the case when generating
Gilles Peskinee842e582021-04-15 11:45:19 +02002182 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee5381682021-04-13 21:23:25 +02002183 * overwhelming probability. When N is just above a power of 2,
Gilles Peskinee842e582021-04-15 11:45:19 +02002184 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee5381682021-04-13 21:23:25 +02002185 * a probability of failing that is almost 1/2.
2186 *
2187 * The probabilities are almost the same if min is nonzero but negligible
2188 * compared to N. This is always the case when N is crypto-sized, but
2189 * it's convenient to support small N for testing purposes. When N
2190 * is small, use a higher repeat count, otherwise the probability of
2191 * failure is macroscopic.
2192 */
Gilles Peskine87823d72021-06-02 21:18:59 +02002193 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee5381682021-04-13 21:23:25 +02002194
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002195 mbedtls_mpi_init( &lower_bound );
2196
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002197 /* Ensure that target MPI has exactly the same number of limbs
2198 * as the upper bound, even if the upper bound has leading zeros.
2199 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskineed32b572021-06-02 22:17:52 +02002200 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002201 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2202 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002203
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002204 /*
2205 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2206 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2207 * - use the same byte ordering;
2208 * - keep the leftmost n_bits bits of the generated octet string;
2209 * - try until result is in the desired range.
2210 * This also avoids any bias, which is especially important for ECDSA.
2211 */
2212 do
2213 {
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002214 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002215 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2216
Gilles Peskinee5381682021-04-13 21:23:25 +02002217 if( --count == 0 )
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002218 {
2219 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2220 goto cleanup;
2221 }
2222
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002223 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2224 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002225 }
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002226 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002227
2228cleanup:
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002229 mbedtls_mpi_free( &lower_bound );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002230 return( ret );
2231}
2232
Paul Bakker5121ce52009-01-03 21:22:43 +00002233/*
2234 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2235 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002237{
Janos Follath24eed8d2019-11-22 13:21:35 +00002238 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002240 MPI_VALIDATE_RET( X != NULL );
2241 MPI_VALIDATE_RET( A != NULL );
2242 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002243
Hanno Becker4bcb4912017-04-18 15:49:39 +01002244 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002245 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2248 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2249 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002254 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002255 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002256 goto cleanup;
2257 }
2258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2260 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2261 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2262 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2265 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2266 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2267 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
2269 do
2270 {
2271 while( ( TU.p[0] & 1 ) == 0 )
2272 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
2275 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2276 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2278 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 }
2280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2282 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 }
2284
2285 while( ( TV.p[0] & 1 ) == 0 )
2286 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002288
2289 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2290 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2292 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 }
2294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2296 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297 }
2298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002300 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2302 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2303 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 }
2305 else
2306 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2308 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2309 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310 }
2311 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2315 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2318 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002321
2322cleanup:
2323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2325 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2326 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327
2328 return( ret );
2329}
2330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002332
Paul Bakker5121ce52009-01-03 21:22:43 +00002333static const int small_prime[] =
2334{
2335 3, 5, 7, 11, 13, 17, 19, 23,
2336 29, 31, 37, 41, 43, 47, 53, 59,
2337 61, 67, 71, 73, 79, 83, 89, 97,
2338 101, 103, 107, 109, 113, 127, 131, 137,
2339 139, 149, 151, 157, 163, 167, 173, 179,
2340 181, 191, 193, 197, 199, 211, 223, 227,
2341 229, 233, 239, 241, 251, 257, 263, 269,
2342 271, 277, 281, 283, 293, 307, 311, 313,
2343 317, 331, 337, 347, 349, 353, 359, 367,
2344 373, 379, 383, 389, 397, 401, 409, 419,
2345 421, 431, 433, 439, 443, 449, 457, 461,
2346 463, 467, 479, 487, 491, 499, 503, 509,
2347 521, 523, 541, 547, 557, 563, 569, 571,
2348 577, 587, 593, 599, 601, 607, 613, 617,
2349 619, 631, 641, 643, 647, 653, 659, 661,
2350 673, 677, 683, 691, 701, 709, 719, 727,
2351 733, 739, 743, 751, 757, 761, 769, 773,
2352 787, 797, 809, 811, 821, 823, 827, 829,
2353 839, 853, 857, 859, 863, 877, 881, 883,
2354 887, 907, 911, 919, 929, 937, 941, 947,
2355 953, 967, 971, 977, 983, 991, 997, -103
2356};
2357
2358/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002359 * Small divisors test (X must be positive)
2360 *
2361 * Return values:
2362 * 0: no small factor (possible prime, more tests needed)
2363 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002365 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002366 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002368{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002369 int ret = 0;
2370 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
Paul Bakker5121ce52009-01-03 21:22:43 +00002373 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
2376 for( i = 0; small_prime[i] > 0; i++ )
2377 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002379 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
2383 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002385 }
2386
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002387cleanup:
2388 return( ret );
2389}
2390
2391/*
2392 * Miller-Rabin pseudo-primality test (HAC 4.24)
2393 */
Janos Follathda31fa12018-09-03 14:45:23 +01002394static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002395 int (*f_rng)(void *, unsigned char *, size_t),
2396 void *p_rng )
2397{
Pascal Junodb99183d2015-03-11 16:49:45 +01002398 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002399 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002401
Hanno Becker8ce11a32018-12-19 16:18:52 +00002402 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002403 MPI_VALIDATE_RET( f_rng != NULL );
2404
2405 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2406 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002408
Paul Bakker5121ce52009-01-03 21:22:43 +00002409 /*
2410 * W = |X| - 1
2411 * R = W >> lsb( W )
2412 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2414 s = mbedtls_mpi_lsb( &W );
2415 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2416 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
Janos Follathda31fa12018-09-03 14:45:23 +01002418 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002419 {
2420 /*
2421 * pick a random A, 1 < A < |X| - 1
2422 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002423 count = 0;
2424 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002425 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002426
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002427 j = mbedtls_mpi_bitlen( &A );
2428 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002429 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002430 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002431 }
2432
2433 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002434 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2435 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002436 }
2437
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002438 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2439 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002440
2441 /*
2442 * A = A^R mod |X|
2443 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002444 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2447 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 continue;
2449
2450 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002452 {
2453 /*
2454 * A = A * A mod |X|
2455 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2457 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002460 break;
2461
2462 j++;
2463 }
2464
2465 /*
2466 * not prime if A != |X| - 1 or A == 1
2467 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2469 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002472 break;
2473 }
2474 }
2475
2476cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002477 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2478 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002479 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002480
2481 return( ret );
2482}
2483
2484/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002485 * Pseudo-primality test: small factors, then Miller-Rabin
2486 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002487int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2488 int (*f_rng)(void *, unsigned char *, size_t),
2489 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002490{
Janos Follath24eed8d2019-11-22 13:21:35 +00002491 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002493 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002494 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002495
2496 XX.s = 1;
2497 XX.n = X->n;
2498 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2501 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2502 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002505 return( 0 );
2506
2507 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2508 {
2509 if( ret == 1 )
2510 return( 0 );
2511
2512 return( ret );
2513 }
2514
Janos Follathda31fa12018-09-03 14:45:23 +01002515 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002516}
2517
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002518/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002519 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002520 *
Janos Follathf301d232018-08-14 13:34:01 +01002521 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2522 * be either 1024 bits or 1536 bits long, and flags must contain
2523 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002524 */
Janos Follath7c025a92018-08-14 11:08:41 +01002525int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002526 int (*f_rng)(void *, unsigned char *, size_t),
2527 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002528{
Jethro Beekman66689272018-02-14 19:24:10 -08002529#ifdef MBEDTLS_HAVE_INT64
2530// ceil(2^63.5)
2531#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2532#else
2533// ceil(2^31.5)
2534#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2535#endif
2536 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002537 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002538 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002539 mbedtls_mpi_uint r;
2540 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002541
Hanno Becker8ce11a32018-12-19 16:18:52 +00002542 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002543 MPI_VALIDATE_RET( f_rng != NULL );
2544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2546 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
2550 n = BITS_TO_LIMBS( nbits );
2551
Janos Follathda31fa12018-09-03 14:45:23 +01002552 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2553 {
2554 /*
2555 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2556 */
2557 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2558 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2559 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2560 }
2561 else
2562 {
2563 /*
2564 * 2^-100 error probability, number of rounds computed based on HAC,
2565 * fact 4.48
2566 */
2567 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2568 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2569 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2570 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2571 }
2572
Jethro Beekman66689272018-02-14 19:24:10 -08002573 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002574 {
Jethro Beekman66689272018-02-14 19:24:10 -08002575 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2576 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2577 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2578
2579 k = n * biL;
2580 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2581 X->p[0] |= 1;
2582
Janos Follath7c025a92018-08-14 11:08:41 +01002583 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002584 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002585 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002588 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002589 }
Jethro Beekman66689272018-02-14 19:24:10 -08002590 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002591 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002592 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002593 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002594 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2595 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002596 */
Jethro Beekman66689272018-02-14 19:24:10 -08002597
2598 X->p[0] |= 2;
2599
2600 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2601 if( r == 0 )
2602 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2603 else if( r == 1 )
2604 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2605
2606 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2607 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2608 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2609
2610 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002611 {
Jethro Beekman66689272018-02-14 19:24:10 -08002612 /*
2613 * First, check small factors for X and Y
2614 * before doing Miller-Rabin on any of them
2615 */
2616 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2617 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002618 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002619 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002620 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002621 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002622 goto cleanup;
2623
2624 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2625 goto cleanup;
2626
2627 /*
2628 * Next candidates. We want to preserve Y = (X-1) / 2 and
2629 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2630 * so up Y by 6 and X by 12.
2631 */
2632 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2633 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002634 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002635 }
2636 }
2637
2638cleanup:
2639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002640 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002641
2642 return( ret );
2643}
2644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002645#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002648
Paul Bakker23986e52011-04-24 08:57:21 +00002649#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002650
2651static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2652{
2653 { 693, 609, 21 },
2654 { 1764, 868, 28 },
2655 { 768454923, 542167814, 1 }
2656};
2657
Paul Bakker5121ce52009-01-03 21:22:43 +00002658/*
2659 * Checkup routine
2660 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002662{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002663 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002664 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002666 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2667 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002670 "EFE021C2645FD1DC586E69184AF4A31E" \
2671 "D5F53E93B5F123FA41680867BA110131" \
2672 "944FE7952E2517337780CB0DB80E61AA" \
2673 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2674
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002675 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002676 "B2E7EFD37075B9F03FF989C7C5051C20" \
2677 "34D2A323810251127E7BF8625A4F49A5" \
2678 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2679 "5B5C25763222FEFCCFC38B832366C29E" ) );
2680
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002681 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002682 "0066A198186C18C10B2F5ED9B522752A" \
2683 "9830B69916E535C8F047518A889A43A5" \
2684 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2685
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002686 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002688 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002689 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2690 "9E857EA95A03512E2BAE7391688D264A" \
2691 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2692 "8001B72E848A38CAE1C65F78E56ABDEF" \
2693 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2694 "ECF677152EF804370C1A305CAF3B5BF1" \
2695 "30879B56C61DE584A0F53A2447A51E" ) );
2696
2697 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002699
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002700 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002701 {
2702 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002703 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002704
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002705 ret = 1;
2706 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002707 }
2708
2709 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002710 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002712 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002714 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002715 "256567336059E52CAE22925474705F39A94" ) );
2716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002717 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002718 "6613F26162223DF488E9CD48CC132C7A" \
2719 "0AC93C701B001B092E4E5B9F73BCD27B" \
2720 "9EE50D0657C77F374E903CDFA4C642" ) );
2721
2722 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002723 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2726 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002727 {
2728 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002729 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002730
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002731 ret = 1;
2732 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002733 }
2734
2735 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002736 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002738 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002740 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002741 "36E139AEA55215609D2816998ED020BB" \
2742 "BD96C37890F65171D948E9BC7CBAA4D9" \
2743 "325D24D6A3C12710F10A09FA08AB87" ) );
2744
2745 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002746 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002747
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002748 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002749 {
2750 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002751 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002752
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002753 ret = 1;
2754 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002755 }
2756
2757 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002758 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002760 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002761
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002762 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002763 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2764 "C3DBA76456363A10869622EAC2DD84EC" \
2765 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2766
2767 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002770 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002771 {
2772 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002773 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002774
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002775 ret = 1;
2776 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002777 }
2778
2779 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002781
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002782 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002784
Paul Bakker66d5d072014-06-17 16:39:18 +02002785 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002786 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002787 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2788 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002790 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002792 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002793 {
2794 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002796
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002797 ret = 1;
2798 goto cleanup;
2799 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002800 }
2801
2802 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002804
Paul Bakker5121ce52009-01-03 21:22:43 +00002805cleanup:
2806
2807 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02002808 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002810 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2811 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002812
2813 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002814 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002815
2816 return( ret );
2817}
2818
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002819#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002820
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002821#endif /* MBEDTLS_BIGNUM_C */