blob: 870365dd6b300882aab7449c897ff8fa9052452b [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
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010061#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
62
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050063/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050064static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
65{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050066 mbedtls_platform_zeroize( v, ciL * n );
67}
68
Paul Bakker5121ce52009-01-03 21:22:43 +000069/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000070 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000071 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000073{
Hanno Becker73d7d792018-12-11 10:35:51 +000074 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000075
Paul Bakker6c591fa2011-05-05 11:49:20 +000076 X->s = 1;
77 X->n = 0;
78 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000079}
80
81/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000083 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000085{
Paul Bakker6c591fa2011-05-05 11:49:20 +000086 if( X == NULL )
87 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000088
Paul Bakker6c591fa2011-05-05 11:49:20 +000089 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000090 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +020091 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000093 }
94
Paul Bakker6c591fa2011-05-05 11:49:20 +000095 X->s = 1;
96 X->n = 0;
97 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000098}
99
100/*
101 * Enlarge to the specified number of limbs
102 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000104{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000106 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200109 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000110
Paul Bakker5121ce52009-01-03 21:22:43 +0000111 if( X->n < nblimbs )
112 {
Simon Butcher29176892016-05-20 00:19:09 +0100113 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200114 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000115
Paul Bakker5121ce52009-01-03 21:22:43 +0000116 if( X->p != NULL )
117 {
118 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200119 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 }
122
123 X->n = nblimbs;
124 X->p = p;
125 }
126
127 return( 0 );
128}
129
130/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100131 * Resize down as much as possible,
132 * while keeping at least the specified number of limbs
133 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100135{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100137 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000138 MPI_VALIDATE_RET( X != NULL );
139
140 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
141 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100142
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100143 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100144 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100146 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147
148 for( i = X->n - 1; i > 0; i-- )
149 if( X->p[i] != 0 )
150 break;
151 i++;
152
153 if( i < nblimbs )
154 i = nblimbs;
155
Simon Butcher29176892016-05-20 00:19:09 +0100156 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200157 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100158
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159 if( X->p != NULL )
160 {
161 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200162 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 }
165
166 X->n = i;
167 X->p = p;
168
169 return( 0 );
170}
171
Gilles Peskineed32b572021-06-02 22:17:52 +0200172/* Resize X to have exactly n limbs and set it to 0. */
173static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
174{
175 if( limbs == 0 )
176 {
177 mbedtls_mpi_free( X );
178 return( 0 );
179 }
180 else if( X->n == limbs )
181 {
182 memset( X->p, 0, limbs * ciL );
183 X->s = 1;
184 return( 0 );
185 }
186 else
187 {
188 mbedtls_mpi_free( X );
189 return( mbedtls_mpi_grow( X, limbs ) );
190 }
191}
192
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100193/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200194 * Copy the contents of Y into X.
195 *
196 * This function is not constant-time. Leading zeros in Y may be removed.
197 *
198 * Ensure that X does not shrink. This is not guaranteed by the public API,
199 * but some code in the bignum module relies on this property, for example
200 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000201 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000203{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100204 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000205 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000206 MPI_VALIDATE_RET( X != NULL );
207 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
209 if( X == Y )
210 return( 0 );
211
Gilles Peskinedb420622020-01-20 21:12:50 +0100212 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200213 {
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200214 if( X->n != 0 )
215 {
216 X->s = 1;
217 memset( X->p, 0, X->n * ciL );
218 }
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200219 return( 0 );
220 }
221
Paul Bakker5121ce52009-01-03 21:22:43 +0000222 for( i = Y->n - 1; i > 0; i-- )
223 if( Y->p[i] != 0 )
224 break;
225 i++;
226
227 X->s = Y->s;
228
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100229 if( X->n < i )
230 {
231 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
232 }
233 else
234 {
235 memset( X->p + i, 0, ( X->n - i ) * ciL );
236 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000237
Paul Bakker5121ce52009-01-03 21:22:43 +0000238 memcpy( X->p, Y->p, i * ciL );
239
240cleanup:
241
242 return( ret );
243}
244
245/*
246 * Swap the contents of X and Y
247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000249{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000251 MPI_VALIDATE( X != NULL );
252 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 memcpy( &T, X, sizeof( mbedtls_mpi ) );
255 memcpy( X, Y, sizeof( mbedtls_mpi ) );
256 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000257}
258
259/*
260 * Set value from integer
261 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000263{
Janos Follath24eed8d2019-11-22 13:21:35 +0000264 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000265 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000268 memset( X->p, 0, X->n * ciL );
269
270 X->p[0] = ( z < 0 ) ? -z : z;
271 X->s = ( z < 0 ) ? -1 : 1;
272
273cleanup:
274
275 return( ret );
276}
277
278/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000279 * Get a specific bit
280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000282{
Hanno Becker73d7d792018-12-11 10:35:51 +0000283 MPI_VALIDATE_RET( X != NULL );
284
Paul Bakker2f5947e2011-05-18 15:47:11 +0000285 if( X->n * biL <= pos )
286 return( 0 );
287
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200288 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000289}
290
Gilles Peskine11cdb052018-11-20 16:47:47 +0100291/* Get a specific byte, without range checks. */
292#define GET_BYTE( X, i ) \
293 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
294
Paul Bakker2f5947e2011-05-18 15:47:11 +0000295/*
296 * Set a bit to a specific value of 0 or 1
297 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000299{
300 int ret = 0;
301 size_t off = pos / biL;
302 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000303 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000304
305 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200307
Paul Bakker2f5947e2011-05-18 15:47:11 +0000308 if( X->n * biL <= pos )
309 {
310 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200311 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000314 }
315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
317 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000318
319cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200320
Paul Bakker2f5947e2011-05-18 15:47:11 +0000321 return( ret );
322}
323
324/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200325 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000328{
Paul Bakker23986e52011-04-24 08:57:21 +0000329 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000330 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000331
332 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000333 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000334 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
335 return( count );
336
337 return( 0 );
338}
339
340/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000341 * Count leading zero bits in a given integer
342 */
343static size_t mbedtls_clz( const mbedtls_mpi_uint x )
344{
345 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100346 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000347
348 for( j = 0; j < biL; j++ )
349 {
350 if( x & mask ) break;
351
352 mask >>= 1;
353 }
354
355 return j;
356}
357
358/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200359 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000360 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200361size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000362{
Paul Bakker23986e52011-04-24 08:57:21 +0000363 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000364
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200365 if( X->n == 0 )
366 return( 0 );
367
Paul Bakker5121ce52009-01-03 21:22:43 +0000368 for( i = X->n - 1; i > 0; i-- )
369 if( X->p[i] != 0 )
370 break;
371
Simon Butcher15b15d12015-11-26 19:35:03 +0000372 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000373
Paul Bakker23986e52011-04-24 08:57:21 +0000374 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000375}
376
377/*
378 * Return the total size in bytes
379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200382 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000383}
384
385/*
386 * Convert an ASCII character to digit value
387 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000389{
390 *d = 255;
391
392 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
393 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
394 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396 if( *d >= (mbedtls_mpi_uint) radix )
397 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
399 return( 0 );
400}
401
402/*
403 * Import from an ASCII string
404 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000406{
Janos Follath24eed8d2019-11-22 13:21:35 +0000407 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000408 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200409 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410 mbedtls_mpi_uint d;
411 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000412 MPI_VALIDATE_RET( X != NULL );
413 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000414
415 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000416 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000419
Gilles Peskine7cba8592021-06-08 18:32:34 +0200420 if( s[0] == 0 )
421 {
422 mbedtls_mpi_free( X );
423 return( 0 );
424 }
425
Gilles Peskine80f56732021-04-03 18:26:13 +0200426 if( s[0] == '-' )
427 {
428 ++s;
429 sign = -1;
430 }
431
Paul Bakkerff60ee62010-03-16 21:09:09 +0000432 slen = strlen( s );
433
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 if( radix == 16 )
435 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100436 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200437 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
438
Paul Bakkerff60ee62010-03-16 21:09:09 +0000439 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
442 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000443
Paul Bakker23986e52011-04-24 08:57:21 +0000444 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200447 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000448 }
449 }
450 else
451 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
Paul Bakkerff60ee62010-03-16 21:09:09 +0000454 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000455 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
457 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200458 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000459 }
460 }
461
Gilles Peskine80f56732021-04-03 18:26:13 +0200462 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
463 X->s = -1;
464
Paul Bakker5121ce52009-01-03 21:22:43 +0000465cleanup:
466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 return( ret );
470}
471
472/*
Ron Eldora16fa292018-11-20 14:07:01 +0200473 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 */
Ron Eldora16fa292018-11-20 14:07:01 +0200475static int mpi_write_hlp( mbedtls_mpi *X, int radix,
476 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000477{
Janos Follath24eed8d2019-11-22 13:21:35 +0000478 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200480 size_t length = 0;
481 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000482
Ron Eldora16fa292018-11-20 14:07:01 +0200483 do
484 {
485 if( length >= buflen )
486 {
487 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
488 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
Ron Eldora16fa292018-11-20 14:07:01 +0200490 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
491 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
492 /*
493 * Write the residue in the current position, as an ASCII character.
494 */
495 if( r < 0xA )
496 *(--p_end) = (char)( '0' + r );
497 else
498 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Ron Eldora16fa292018-11-20 14:07:01 +0200500 length++;
501 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000502
Ron Eldora16fa292018-11-20 14:07:01 +0200503 memmove( *p, p_end, length );
504 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
506cleanup:
507
508 return( ret );
509}
510
511/*
512 * Export into an ASCII string
513 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100514int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
515 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000516{
Paul Bakker23986e52011-04-24 08:57:21 +0000517 int ret = 0;
518 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000521 MPI_VALIDATE_RET( X != NULL );
522 MPI_VALIDATE_RET( olen != NULL );
523 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000524
525 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000526 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000527
Hanno Becker23cfea02019-02-04 09:45:07 +0000528 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
529 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
530 * `n`. If radix > 4, this might be a strict
531 * overapproximation of the number of
532 * radix-adic digits needed to present `n`. */
533 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
534 * present `n`. */
535
Janos Follath80470622019-03-06 13:43:02 +0000536 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000537 n += 1; /* Compensate for the divisions above, which round down `n`
538 * in case it's not even. */
539 n += 1; /* Potential '-'-sign. */
540 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
541 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100543 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000544 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100545 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547 }
548
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100549 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
552 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000553 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000554 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000555 buflen--;
556 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
558 if( radix == 16 )
559 {
Paul Bakker23986e52011-04-24 08:57:21 +0000560 int c;
561 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
Paul Bakker23986e52011-04-24 08:57:21 +0000563 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 {
Paul Bakker23986e52011-04-24 08:57:21 +0000565 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000566 {
Paul Bakker23986e52011-04-24 08:57:21 +0000567 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000568
Paul Bakker6c343d72014-07-10 14:36:19 +0200569 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000570 continue;
571
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000572 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000573 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 k = 1;
575 }
576 }
577 }
578 else
579 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000581
582 if( T.s == -1 )
583 T.s = 1;
584
Ron Eldora16fa292018-11-20 14:07:01 +0200585 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000586 }
587
588 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100589 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000590
591cleanup:
592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
595 return( ret );
596}
597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000599/*
600 * Read X from an opened file
601 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000603{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000605 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000606 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000607 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000608 * Buffer should have space for (short) label and decimal formatted MPI,
609 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000610 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000612
Hanno Becker73d7d792018-12-11 10:35:51 +0000613 MPI_VALIDATE_RET( X != NULL );
614 MPI_VALIDATE_RET( fin != NULL );
615
616 if( radix < 2 || radix > 16 )
617 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
618
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 memset( s, 0, sizeof( s ) );
620 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000622
623 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000624 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000626
Hanno Beckerb2034b72017-04-26 11:46:46 +0100627 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
628 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000629
630 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100631 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 if( mpi_get_digit( &d, radix, *p ) != 0 )
633 break;
634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000636}
637
638/*
639 * Write X into an opened file (or stdout if fout == NULL)
640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000642{
Janos Follath24eed8d2019-11-22 13:21:35 +0000643 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000644 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000645 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000646 * Buffer should have space for (short) label and decimal formatted MPI,
647 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000648 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000650 MPI_VALIDATE_RET( X != NULL );
651
652 if( radix < 2 || radix > 16 )
653 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100655 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100657 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
659 if( p == NULL ) p = "";
660
661 plen = strlen( p );
662 slen = strlen( s );
663 s[slen++] = '\r';
664 s[slen++] = '\n';
665
666 if( fout != NULL )
667 {
668 if( fwrite( p, 1, plen, fout ) != plen ||
669 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671 }
672 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000674
675cleanup:
676
677 return( ret );
678}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
Hanno Beckerda1655a2017-10-18 14:21:44 +0100681
682/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
683 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000684
685static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
686{
687 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100688 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000689 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100690
691 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
692 {
693 tmp <<= CHAR_BIT;
694 tmp |= (mbedtls_mpi_uint) *x_ptr;
695 }
696
Hanno Beckerf8720072018-11-08 11:53:49 +0000697 return( tmp );
698}
699
700static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
701{
702#if defined(__BYTE_ORDER__)
703
704/* Nothing to do on bigendian systems. */
705#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
706 return( x );
707#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
708
709#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
710
711/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000712#if defined(__GNUC__) && defined(__GNUC_PREREQ)
713#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000714#define have_bswap
715#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000716#endif
717
718#if defined(__clang__) && defined(__has_builtin)
719#if __has_builtin(__builtin_bswap32) && \
720 __has_builtin(__builtin_bswap64)
721#define have_bswap
722#endif
723#endif
724
Hanno Beckerf8720072018-11-08 11:53:49 +0000725#if defined(have_bswap)
726 /* The compiler is hopefully able to statically evaluate this! */
727 switch( sizeof(mbedtls_mpi_uint) )
728 {
729 case 4:
730 return( __builtin_bswap32(x) );
731 case 8:
732 return( __builtin_bswap64(x) );
733 }
734#endif
735#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
736#endif /* __BYTE_ORDER__ */
737
738 /* Fall back to C-based reordering if we don't know the byte order
739 * or we couldn't use a compiler-specific builtin. */
740 return( mpi_uint_bigendian_to_host_c( x ) );
741}
742
Hanno Becker2be8a552018-10-25 12:40:09 +0100743static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100744{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100745 mbedtls_mpi_uint *cur_limb_left;
746 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100747 if( limbs == 0 )
748 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100749
750 /*
751 * Traverse limbs and
752 * - adapt byte-order in each limb
753 * - swap the limbs themselves.
754 * For that, simultaneously traverse the limbs from left to right
755 * and from right to left, as long as the left index is not bigger
756 * than the right index (it's not a problem if limbs is odd and the
757 * indices coincide in the last iteration).
758 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100759 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
760 cur_limb_left <= cur_limb_right;
761 cur_limb_left++, cur_limb_right-- )
762 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000763 mbedtls_mpi_uint tmp;
764 /* Note that if cur_limb_left == cur_limb_right,
765 * this code effectively swaps the bytes only once. */
766 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
767 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
768 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100769 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100770}
771
Paul Bakker5121ce52009-01-03 21:22:43 +0000772/*
Janos Follatha778a942019-02-13 10:28:28 +0000773 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100774 *
775 * This function is guaranteed to return an MPI with exactly the necessary
776 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000777 */
778int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
779 const unsigned char *buf, size_t buflen )
780{
Janos Follath24eed8d2019-11-22 13:21:35 +0000781 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000782 size_t i;
783 size_t const limbs = CHARS_TO_LIMBS( buflen );
784
785 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +0200786 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000787
788 for( i = 0; i < buflen; i++ )
789 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
790
791cleanup:
792
Janos Follath171a7ef2019-02-15 16:17:45 +0000793 /*
794 * This function is also used to import keys. However, wiping the buffers
795 * upon failure is not necessary because failure only can happen before any
796 * input is copied.
797 */
Janos Follatha778a942019-02-13 10:28:28 +0000798 return( ret );
799}
800
801/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000802 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100803 *
804 * This function is guaranteed to return an MPI with exactly the necessary
805 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000806 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000808{
Janos Follath24eed8d2019-11-22 13:21:35 +0000809 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100810 size_t const limbs = CHARS_TO_LIMBS( buflen );
811 size_t const overhead = ( limbs * ciL ) - buflen;
812 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000813
Hanno Becker8ce11a32018-12-19 16:18:52 +0000814 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000815 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
816
Hanno Becker073c1992017-10-17 15:17:27 +0100817 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +0200818 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000819
Gilles Peskineed32b572021-06-02 22:17:52 +0200820 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000821 * even if buflen is 0. */
Gilles Peskineed32b572021-06-02 22:17:52 +0200822 if( buflen != 0 )
Hanno Becker0e810b92019-01-03 17:13:11 +0000823 {
824 Xp = (unsigned char*) X->p;
825 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100826
Hanno Becker0e810b92019-01-03 17:13:11 +0000827 mpi_bigendian_to_host( X->p, limbs );
828 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000829
830cleanup:
831
Janos Follath171a7ef2019-02-15 16:17:45 +0000832 /*
833 * This function is also used to import keys. However, wiping the buffers
834 * upon failure is not necessary because failure only can happen before any
835 * input is copied.
836 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000837 return( ret );
838}
839
840/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000841 * Export X into unsigned binary data, little endian
842 */
843int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
844 unsigned char *buf, size_t buflen )
845{
846 size_t stored_bytes = X->n * ciL;
847 size_t bytes_to_copy;
848 size_t i;
849
850 if( stored_bytes < buflen )
851 {
852 bytes_to_copy = stored_bytes;
853 }
854 else
855 {
856 bytes_to_copy = buflen;
857
858 /* The output buffer is smaller than the allocated size of X.
859 * However X may fit if its leading bytes are zero. */
860 for( i = bytes_to_copy; i < stored_bytes; i++ )
861 {
862 if( GET_BYTE( X, i ) != 0 )
863 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
864 }
865 }
866
867 for( i = 0; i < bytes_to_copy; i++ )
868 buf[i] = GET_BYTE( X, i );
869
870 if( stored_bytes < buflen )
871 {
872 /* Write trailing 0 bytes */
873 memset( buf + stored_bytes, 0, buflen - stored_bytes );
874 }
875
876 return( 0 );
877}
878
879/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000880 * Export X into unsigned binary data, big endian
881 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100882int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
883 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000884{
Hanno Becker73d7d792018-12-11 10:35:51 +0000885 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100886 size_t bytes_to_copy;
887 unsigned char *p;
888 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000889
Hanno Becker73d7d792018-12-11 10:35:51 +0000890 MPI_VALIDATE_RET( X != NULL );
891 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
892
893 stored_bytes = X->n * ciL;
894
Gilles Peskine11cdb052018-11-20 16:47:47 +0100895 if( stored_bytes < buflen )
896 {
897 /* There is enough space in the output buffer. Write initial
898 * null bytes and record the position at which to start
899 * writing the significant bytes. In this case, the execution
900 * trace of this function does not depend on the value of the
901 * number. */
902 bytes_to_copy = stored_bytes;
903 p = buf + buflen - stored_bytes;
904 memset( buf, 0, buflen - stored_bytes );
905 }
906 else
907 {
908 /* The output buffer is smaller than the allocated size of X.
909 * However X may fit if its leading bytes are zero. */
910 bytes_to_copy = buflen;
911 p = buf;
912 for( i = bytes_to_copy; i < stored_bytes; i++ )
913 {
914 if( GET_BYTE( X, i ) != 0 )
915 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
916 }
917 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000918
Gilles Peskine11cdb052018-11-20 16:47:47 +0100919 for( i = 0; i < bytes_to_copy; i++ )
920 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000921
922 return( 0 );
923}
924
925/*
926 * Left-shift: X <<= count
927 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000929{
Janos Follath24eed8d2019-11-22 13:21:35 +0000930 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000931 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000933 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000934
935 v0 = count / (biL );
936 t1 = count & (biL - 1);
937
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200938 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
Paul Bakkerf9688572011-05-05 10:00:45 +0000940 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000942
943 ret = 0;
944
945 /*
946 * shift by count / limb_size
947 */
948 if( v0 > 0 )
949 {
Paul Bakker23986e52011-04-24 08:57:21 +0000950 for( i = X->n; i > v0; i-- )
951 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000952
Paul Bakker23986e52011-04-24 08:57:21 +0000953 for( ; i > 0; i-- )
954 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000955 }
956
957 /*
958 * shift by count % limb_size
959 */
960 if( t1 > 0 )
961 {
962 for( i = v0; i < X->n; i++ )
963 {
964 r1 = X->p[i] >> (biL - t1);
965 X->p[i] <<= t1;
966 X->p[i] |= r0;
967 r0 = r1;
968 }
969 }
970
971cleanup:
972
973 return( ret );
974}
975
976/*
977 * Right-shift: X >>= count
978 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200979int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000980{
Paul Bakker23986e52011-04-24 08:57:21 +0000981 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200982 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000983 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000984
985 v0 = count / biL;
986 v1 = count & (biL - 1);
987
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100988 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200989 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100990
Paul Bakker5121ce52009-01-03 21:22:43 +0000991 /*
992 * shift by count / limb_size
993 */
994 if( v0 > 0 )
995 {
996 for( i = 0; i < X->n - v0; i++ )
997 X->p[i] = X->p[i + v0];
998
999 for( ; i < X->n; i++ )
1000 X->p[i] = 0;
1001 }
1002
1003 /*
1004 * shift by count % limb_size
1005 */
1006 if( v1 > 0 )
1007 {
Paul Bakker23986e52011-04-24 08:57:21 +00001008 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001009 {
Paul Bakker23986e52011-04-24 08:57:21 +00001010 r1 = X->p[i - 1] << (biL - v1);
1011 X->p[i - 1] >>= v1;
1012 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001013 r0 = r1;
1014 }
1015 }
1016
1017 return( 0 );
1018}
1019
1020/*
1021 * Compare unsigned values
1022 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001024{
Paul Bakker23986e52011-04-24 08:57:21 +00001025 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001026 MPI_VALIDATE_RET( X != NULL );
1027 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001028
Paul Bakker23986e52011-04-24 08:57:21 +00001029 for( i = X->n; i > 0; i-- )
1030 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 break;
1032
Paul Bakker23986e52011-04-24 08:57:21 +00001033 for( j = Y->n; j > 0; j-- )
1034 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001035 break;
1036
Paul Bakker23986e52011-04-24 08:57:21 +00001037 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001038 return( 0 );
1039
1040 if( i > j ) return( 1 );
1041 if( j > i ) return( -1 );
1042
Paul Bakker23986e52011-04-24 08:57:21 +00001043 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001044 {
Paul Bakker23986e52011-04-24 08:57:21 +00001045 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1046 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 }
1048
1049 return( 0 );
1050}
1051
1052/*
1053 * Compare signed values
1054 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001056{
Paul Bakker23986e52011-04-24 08:57:21 +00001057 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001058 MPI_VALIDATE_RET( X != NULL );
1059 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001060
Paul Bakker23986e52011-04-24 08:57:21 +00001061 for( i = X->n; i > 0; i-- )
1062 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001063 break;
1064
Paul Bakker23986e52011-04-24 08:57:21 +00001065 for( j = Y->n; j > 0; j-- )
1066 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001067 break;
1068
Paul Bakker23986e52011-04-24 08:57:21 +00001069 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 return( 0 );
1071
1072 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001073 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001074
1075 if( X->s > 0 && Y->s < 0 ) return( 1 );
1076 if( Y->s > 0 && X->s < 0 ) return( -1 );
1077
Paul Bakker23986e52011-04-24 08:57:21 +00001078 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001079 {
Paul Bakker23986e52011-04-24 08:57:21 +00001080 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1081 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 }
1083
1084 return( 0 );
1085}
1086
Janos Follathee6abce2019-09-05 14:47:19 +01001087/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 * Compare signed values
1089 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001091{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092 mbedtls_mpi Y;
1093 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001094 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001095
1096 *p = ( z < 0 ) ? -z : z;
1097 Y.s = ( z < 0 ) ? -1 : 1;
1098 Y.n = 1;
1099 Y.p = p;
1100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001101 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001102}
1103
1104/*
1105 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1106 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001108{
Janos Follath24eed8d2019-11-22 13:21:35 +00001109 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001110 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001111 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001112 MPI_VALIDATE_RET( X != NULL );
1113 MPI_VALIDATE_RET( A != NULL );
1114 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001115
1116 if( X == B )
1117 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001118 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001119 }
1120
1121 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001123
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001124 /*
1125 * X should always be positive as a result of unsigned additions.
1126 */
1127 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001128
Paul Bakker23986e52011-04-24 08:57:21 +00001129 for( j = B->n; j > 0; j-- )
1130 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001131 break;
1132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001134
1135 o = B->p; p = X->p; c = 0;
1136
Janos Follath6c922682015-10-30 17:43:11 +01001137 /*
1138 * tmp is used because it might happen that p == o
1139 */
Paul Bakker23986e52011-04-24 08:57:21 +00001140 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001141 {
Janos Follath6c922682015-10-30 17:43:11 +01001142 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001144 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001145 }
1146
1147 while( c != 0 )
1148 {
1149 if( i >= X->n )
1150 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152 p = X->p + i;
1153 }
1154
Paul Bakker2d319fd2012-09-16 21:34:26 +00001155 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001156 }
1157
1158cleanup:
1159
1160 return( ret );
1161}
1162
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001163/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001164 * Helper for mbedtls_mpi subtraction.
1165 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001166 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001167 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001168 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001169 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001170 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001171 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001172 * \param n Number of limbs of \p d, \p l and \p r.
1173 * \param[out] d The result of the subtraction.
1174 * \param[in] l The left operand.
1175 * \param[in] r The right operand.
1176 *
1177 * \return 1 if `l < r`.
1178 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001179 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001180static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1181 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001182 const mbedtls_mpi_uint *l,
1183 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001184{
Paul Bakker23986e52011-04-24 08:57:21 +00001185 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001186 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001187
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001188 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001190 z = ( l[i] < c ); t = l[i] - c;
1191 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 }
1193
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001194 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001195}
1196
1197/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001198 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001199 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001200int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001201{
Janos Follath24eed8d2019-11-22 13:21:35 +00001202 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001203 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001204 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001205 MPI_VALIDATE_RET( X != NULL );
1206 MPI_VALIDATE_RET( A != NULL );
1207 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001208
Paul Bakker23986e52011-04-24 08:57:21 +00001209 for( n = B->n; n > 0; n-- )
1210 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001211 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001212 if( n > A->n )
1213 {
1214 /* B >= (2^ciL)^n > A */
1215 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1216 goto cleanup;
1217 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001219 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1220
1221 /* Set the high limbs of X to match A. Don't touch the lower limbs
1222 * because X might be aliased to B, and we must not overwrite the
1223 * significant digits of B. */
1224 if( A->n > n )
1225 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1226 if( X->n > A->n )
1227 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1228
1229 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001230 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001231 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001232 /* Propagate the carry to the first nonzero limb of X. */
1233 for( ; n < X->n && X->p[n] == 0; n++ )
1234 --X->p[n];
1235 /* If we ran out of space for the carry, it means that the result
1236 * is negative. */
1237 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001238 {
1239 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1240 goto cleanup;
1241 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001242 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001243 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001244
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001245 /* X should always be positive as a result of unsigned subtractions. */
1246 X->s = 1;
1247
Paul Bakker5121ce52009-01-03 21:22:43 +00001248cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001249 return( ret );
1250}
1251
1252/*
1253 * Signed addition: X = A + B
1254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001256{
Hanno Becker73d7d792018-12-11 10:35:51 +00001257 int ret, s;
1258 MPI_VALIDATE_RET( X != NULL );
1259 MPI_VALIDATE_RET( A != NULL );
1260 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
Hanno Becker73d7d792018-12-11 10:35:51 +00001262 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001263 if( A->s * B->s < 0 )
1264 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001266 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001268 X->s = s;
1269 }
1270 else
1271 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001272 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001273 X->s = -s;
1274 }
1275 }
1276 else
1277 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001279 X->s = s;
1280 }
1281
1282cleanup:
1283
1284 return( ret );
1285}
1286
1287/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001288 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001291{
Hanno Becker73d7d792018-12-11 10:35:51 +00001292 int ret, s;
1293 MPI_VALIDATE_RET( X != NULL );
1294 MPI_VALIDATE_RET( A != NULL );
1295 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001296
Hanno Becker73d7d792018-12-11 10:35:51 +00001297 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001298 if( A->s * B->s > 0 )
1299 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001301 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001302 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001303 X->s = s;
1304 }
1305 else
1306 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001308 X->s = -s;
1309 }
1310 }
1311 else
1312 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001314 X->s = s;
1315 }
1316
1317cleanup:
1318
1319 return( ret );
1320}
1321
1322/*
1323 * Signed addition: X = A + b
1324 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001326{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001327 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001329 MPI_VALIDATE_RET( X != NULL );
1330 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001331
1332 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001333 B.s = ( b < 0 ) ? -1 : 1;
1334 B.n = 1;
1335 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001336
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001337 return( mbedtls_mpi_add_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338}
1339
1340/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001341 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001344{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001345 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001347 MPI_VALIDATE_RET( X != NULL );
1348 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001349
1350 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001351 B.s = ( b < 0 ) ? -1 : 1;
1352 B.n = 1;
1353 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001354
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001355 return( mbedtls_mpi_sub_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001356}
1357
Hanno Becker284d7782022-04-11 09:19:24 +01001358mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len,
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001359 const mbedtls_mpi_uint *s, size_t s_len,
1360 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001361{
Hanno Beckere7f14a32022-04-06 06:11:26 +01001362 mbedtls_mpi_uint c = 0; /* carry */
Hanno Becker5d4ceeb2022-04-11 09:46:47 +01001363 size_t excess_len = d_len - s_len;
Hanno Beckerdefe5692022-04-06 06:12:09 +01001364
Hanno Becker63eb28c2022-04-06 11:30:51 +01001365 size_t steps_x8 = s_len / 8;
1366 size_t steps_x1 = s_len & 7;
1367
1368 while( steps_x8-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001369 {
Hanno Beckereacf3b92022-04-06 11:25:22 +01001370 MULADDC_X8_INIT
1371 MULADDC_X8_CORE
1372 MULADDC_X8_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 }
1374
Hanno Becker63eb28c2022-04-06 11:30:51 +01001375 while( steps_x1-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001376 {
Hanno Beckereacf3b92022-04-06 11:25:22 +01001377 MULADDC_X1_INIT
1378 MULADDC_X1_CORE
1379 MULADDC_X1_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001380 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001381
Hanno Becker284d7782022-04-11 09:19:24 +01001382 while( excess_len-- )
Gilles Peskine8e464c42020-07-24 00:08:38 +02001383 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 *d += c; c = ( *d < c ); d++;
1385 }
Hanno Beckerdefe5692022-04-06 06:12:09 +01001386
1387 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001388}
1389
1390/*
1391 * Baseline multiplication: X = A * B (HAC 14.12)
1392 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001394{
Janos Follath24eed8d2019-11-22 13:21:35 +00001395 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001396 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001398 int result_is_zero = 0;
Hanno Becker73d7d792018-12-11 10:35:51 +00001399 MPI_VALIDATE_RET( X != NULL );
1400 MPI_VALIDATE_RET( A != NULL );
1401 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1406 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001407
Hanno Beckerda763de2022-04-13 06:50:02 +01001408 for( i = A->n; i > 0; i-- )
1409 if( A->p[i - 1] != 0 )
1410 break;
1411 if( i == 0 )
1412 result_is_zero = 1;
1413
1414 for( j = B->n; j > 0; j-- )
1415 if( B->p[j - 1] != 0 )
1416 break;
1417 if( j == 0 )
1418 result_is_zero = 1;
1419
1420 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001421 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001422
Hanno Becker1772e052022-04-13 06:51:40 +01001423 for( size_t k = 0; k < j; k++ )
Hanno Beckerfee261a2022-04-06 06:20:22 +01001424 {
1425 /* We know that there cannot be any carry-out since we're
1426 * iterating from bottom to top. */
Hanno Beckerda763de2022-04-13 06:50:02 +01001427 (void) mbedtls_mpi_core_mla( X->p + k, i + 1,
1428 A->p, i,
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001429 B->p[k] );
Hanno Beckerfee261a2022-04-06 06:20:22 +01001430 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001431
Hanno Beckerda763de2022-04-13 06:50:02 +01001432 /* If the result is 0, we don't shortcut the operation, which reduces
1433 * but does not eliminate side channels leaking the zero-ness. We do
1434 * need to take care to set the sign bit properly since the library does
1435 * not fully support an MPI object with a value of 0 and s == -1. */
1436 if( result_is_zero )
1437 X->s = 1;
1438 else
1439 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001440
1441cleanup:
1442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001444
1445 return( ret );
1446}
1447
1448/*
1449 * Baseline multiplication: X = A * b
1450 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001452{
Hanno Becker73d7d792018-12-11 10:35:51 +00001453 MPI_VALIDATE_RET( X != NULL );
1454 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001455
Hanno Becker35771312022-04-14 11:52:11 +01001456 size_t n = A->n;
1457 while( n > 0 && A->p[n - 1] == 0 )
1458 --n;
1459
Hanno Becker74a11a32022-04-06 06:27:00 +01001460 /* The general method below doesn't work if b==0. */
Hanno Becker35771312022-04-14 11:52:11 +01001461 if( b == 0 || n == 0 )
Paul Elliott986b55a2021-04-20 21:46:29 +01001462 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001463
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001464 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001465 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001466 /* In general, A * b requires 1 limb more than b. If
1467 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1468 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001469 * copy() will take care of the growth if needed. However, experimentally,
1470 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001471 * calls to calloc() in ECP code, presumably because it reuses the
1472 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001473 * grow to its final size.
1474 *
1475 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1476 * A,X can be the same. */
Hanno Becker35771312022-04-14 11:52:11 +01001477 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001478 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Hanno Becker35771312022-04-14 11:52:11 +01001479 mbedtls_mpi_core_mla( X->p, X->n, A->p, n, b - 1 );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001480
1481cleanup:
1482 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001483}
1484
1485/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001486 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1487 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001488 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001489static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1490 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001491{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001492#if defined(MBEDTLS_HAVE_UDBL)
1493 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001494#else
Simon Butcher9803d072016-01-03 00:24:34 +00001495 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1496 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001497 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1498 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001499 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001500#endif
1501
Simon Butcher15b15d12015-11-26 19:35:03 +00001502 /*
1503 * Check for overflow
1504 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001505 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001506 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001507 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001508
Simon Butcherf5ba0452015-12-27 23:01:55 +00001509 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001510 }
1511
1512#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001513 dividend = (mbedtls_t_udbl) u1 << biL;
1514 dividend |= (mbedtls_t_udbl) u0;
1515 quotient = dividend / d;
1516 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1517 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1518
1519 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001520 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001521
1522 return (mbedtls_mpi_uint) quotient;
1523#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001524
1525 /*
1526 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1527 * Vol. 2 - Seminumerical Algorithms, Knuth
1528 */
1529
1530 /*
1531 * Normalize the divisor, d, and dividend, u0, u1
1532 */
1533 s = mbedtls_clz( d );
1534 d = d << s;
1535
1536 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001537 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001538 u0 = u0 << s;
1539
1540 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001541 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001542
1543 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001544 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001545
1546 /*
1547 * Find the first quotient and remainder
1548 */
1549 q1 = u1 / d1;
1550 r0 = u1 - d1 * q1;
1551
1552 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1553 {
1554 q1 -= 1;
1555 r0 += d1;
1556
1557 if ( r0 >= radix ) break;
1558 }
1559
Simon Butcherf5ba0452015-12-27 23:01:55 +00001560 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001561 q0 = rAX / d1;
1562 r0 = rAX - q0 * d1;
1563
1564 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1565 {
1566 q0 -= 1;
1567 r0 += d1;
1568
1569 if ( r0 >= radix ) break;
1570 }
1571
1572 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001573 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001574
1575 quotient = q1 * radix + q0;
1576
1577 return quotient;
1578#endif
1579}
1580
1581/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001584int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1585 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001586{
Janos Follath24eed8d2019-11-22 13:21:35 +00001587 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001588 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001589 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001590 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001591 MPI_VALIDATE_RET( A != NULL );
1592 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1595 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001598 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001599 /*
1600 * Avoid dynamic memory allocations for constant-size T2.
1601 *
1602 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1603 * so nobody increase the size of the MPI and we're safe to use an on-stack
1604 * buffer.
1605 */
Alexander K35d6d462019-10-31 14:46:45 +03001606 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001607 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1608 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001611 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1613 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614 return( 0 );
1615 }
1616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1618 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001619 X.s = Y.s = 1;
1620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1622 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001623 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001625 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001626 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001627 {
1628 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1630 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001631 }
1632 else k = 0;
1633
1634 n = X.n - 1;
1635 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001639 {
1640 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001642 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001643 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
1645 for( i = n; i > t ; i-- )
1646 {
1647 if( X.p[i] >= Y.p[t] )
1648 Z.p[i - t - 1] = ~0;
1649 else
1650 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001651 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1652 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 }
1654
Alexander K35d6d462019-10-31 14:46:45 +03001655 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1656 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1657 T2.p[2] = X.p[i];
1658
Paul Bakker5121ce52009-01-03 21:22:43 +00001659 Z.p[i - t - 1]++;
1660 do
1661 {
1662 Z.p[i - t - 1]--;
1663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001665 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001666 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001674
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001675 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001676 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1678 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1679 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001680 Z.p[i - t - 1]--;
1681 }
1682 }
1683
1684 if( Q != NULL )
1685 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687 Q->s = A->s * B->s;
1688 }
1689
1690 if( R != NULL )
1691 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001693 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001697 R->s = 1;
1698 }
1699
1700cleanup:
1701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001703 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001704 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001705
1706 return( ret );
1707}
1708
1709/*
1710 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001711 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001712int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1713 const mbedtls_mpi *A,
1714 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001715{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001716 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001718 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
1720 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001721 B.s = ( b < 0 ) ? -1 : 1;
1722 B.n = 1;
1723 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001724
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001725 return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726}
1727
1728/*
1729 * Modulo: R = A mod B
1730 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001731int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001732{
Janos Follath24eed8d2019-11-22 13:21:35 +00001733 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001734 MPI_VALIDATE_RET( R != NULL );
1735 MPI_VALIDATE_RET( A != NULL );
1736 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1739 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001743 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1744 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001745
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001746 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1747 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
1749cleanup:
1750
1751 return( ret );
1752}
1753
1754/*
1755 * Modulo: r = A mod b
1756 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001758{
Paul Bakker23986e52011-04-24 08:57:21 +00001759 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001761 MPI_VALIDATE_RET( r != NULL );
1762 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001763
1764 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001766
1767 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001769
1770 /*
1771 * handle trivial cases
1772 */
Gilles Peskineae25bb02022-06-09 19:32:46 +02001773 if( b == 1 || A->n == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001774 {
1775 *r = 0;
1776 return( 0 );
1777 }
1778
1779 if( b == 2 )
1780 {
1781 *r = A->p[0] & 1;
1782 return( 0 );
1783 }
1784
1785 /*
1786 * general case
1787 */
Paul Bakker23986e52011-04-24 08:57:21 +00001788 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001789 {
Paul Bakker23986e52011-04-24 08:57:21 +00001790 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001791 y = ( y << biH ) | ( x >> biH );
1792 z = y / b;
1793 y -= z * b;
1794
1795 x <<= biH;
1796 y = ( y << biH ) | ( x >> biH );
1797 z = y / b;
1798 y -= z * b;
1799 }
1800
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001801 /*
1802 * If A is negative, then the current y represents a negative value.
1803 * Flipping it to the positive side.
1804 */
1805 if( A->s < 0 && y != 0 )
1806 y = b - y;
1807
Paul Bakker5121ce52009-01-03 21:22:43 +00001808 *r = y;
1809
1810 return( 0 );
1811}
1812
1813/*
1814 * Fast Montgomery initialization (thanks to Tom St Denis)
1815 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001817{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001819 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
1821 x = m0;
1822 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001824 for( i = biL; i >= 8; i /= 2 )
1825 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
1827 *mm = ~x + 1;
1828}
1829
Gilles Peskine2a82f722020-06-04 15:00:49 +02001830/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1831 *
1832 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02001833 * It must have at least as many limbs as N
1834 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02001835 * On successful completion, A contains the result of
1836 * the multiplication A * B * R^-1 mod N where
1837 * R = (2^ciL)^n.
1838 * \param[in] B One of the numbers to multiply.
1839 * It must be nonzero and must not have more limbs than N
1840 * (B->n <= N->n).
1841 * \param[in] N The modulo. N must be odd.
1842 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1843 * This is -N^-1 mod 2^ciL.
1844 * \param[in,out] T A bignum for temporary storage.
Hanno Beckere1417022022-04-06 06:45:45 +01001845 * It must be at least twice the limb size of N plus 1
1846 * (T->n >= 2 * N->n + 1).
Gilles Peskine2a82f722020-06-04 15:00:49 +02001847 * Its initial content is unused and
1848 * its final content is indeterminate.
1849 * Note that unlike the usual convention in the library
1850 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001852static 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 +02001853 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001854{
Hanno Becker0235f752022-04-12 10:54:46 +01001855 size_t n, m;
1856 mbedtls_mpi_uint *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001857
1858 memset( T->p, 0, T->n * ciL );
1859
1860 d = T->p;
1861 n = N->n;
1862 m = ( B->n < n ) ? B->n : n;
1863
Hanno Becker0235f752022-04-12 10:54:46 +01001864 for( size_t i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001865 {
Hanno Becker0235f752022-04-12 10:54:46 +01001866 mbedtls_mpi_uint u0, u1;
1867
Paul Bakker5121ce52009-01-03 21:22:43 +00001868 /*
1869 * T = (T + u0*B + u1*N) / 2^biL
1870 */
1871 u0 = A->p[i];
1872 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1873
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001874 (void) mbedtls_mpi_core_mla( d, n + 2,
1875 B->p, m,
1876 u0 );
1877 (void) mbedtls_mpi_core_mla( d, n + 2,
1878 N->p, n,
1879 u1 );
Hanno Beckere1417022022-04-06 06:45:45 +01001880 d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 }
1882
Gilles Peskine221626f2020-06-08 22:37:50 +02001883 /* At this point, d is either the desired result or the desired result
1884 * plus N. We now potentially subtract N, avoiding leaking whether the
1885 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
Gilles Peskine221626f2020-06-08 22:37:50 +02001887 /* Copy the n least significant limbs of d to A, so that
1888 * A = d if d < N (recall that N has n limbs). */
1889 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001890 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02001891 * do the calculation without using conditional tests. */
1892 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02001893 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001894 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02001895 /* If d0 < N then d < (2^biL)^n
1896 * so d[n] == 0 and we want to keep A as it is.
1897 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1898 * so d[n] == 1 and we want to set A to the result of the subtraction
1899 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1900 * This exactly corresponds to a conditional assignment. */
Gabor Mezei90437e32021-10-20 11:59:27 +02001901 mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902}
1903
1904/*
1905 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001906 *
1907 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001908 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001909static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1910 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001911{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 mbedtls_mpi_uint z = 1;
1913 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
Paul Bakker8ddb6452013-02-27 14:56:33 +01001915 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001916 U.p = &z;
1917
Gilles Peskine4e91d472020-06-04 20:55:15 +02001918 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919}
1920
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001921/**
1922 * Select an MPI from a table without leaking the index.
1923 *
1924 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1925 * reads the entire table in order to avoid leaking the value of idx to an
1926 * attacker able to observe memory access patterns.
1927 *
1928 * \param[out] R Where to write the selected MPI.
1929 * \param[in] T The table to read from.
1930 * \param[in] T_size The number of elements in the table.
1931 * \param[in] idx The index of the element to select;
1932 * this must satisfy 0 <= idx < T_size.
1933 *
1934 * \return \c 0 on success, or a negative error code.
1935 */
1936static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
1937{
1938 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1939
1940 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001941 {
1942 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
Gabor Mezei90437e32021-10-20 11:59:27 +02001943 (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001944 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001945
1946cleanup:
1947 return( ret );
1948}
1949
Paul Bakker5121ce52009-01-03 21:22:43 +00001950/*
1951 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1952 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001953int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1954 const mbedtls_mpi *E, const mbedtls_mpi *N,
Yuto Takano538a0cb2021-07-14 10:20:09 +01001955 mbedtls_mpi *prec_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001956{
Janos Follath24eed8d2019-11-22 13:21:35 +00001957 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001958 size_t wbits, wsize, one = 1;
1959 size_t i, j, nblimbs;
1960 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001962 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001963 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
Hanno Becker73d7d792018-12-11 10:35:51 +00001965 MPI_VALIDATE_RET( X != NULL );
1966 MPI_VALIDATE_RET( A != NULL );
1967 MPI_VALIDATE_RET( E != NULL );
1968 MPI_VALIDATE_RET( N != NULL );
1969
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001970 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1974 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001975
Chris Jones9246d042020-11-25 15:12:39 +00001976 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
1977 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
1978 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1979
Paul Bakkerf6198c12012-05-16 08:02:29 +00001980 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001981 * Init temps and window size
1982 */
1983 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1985 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001986 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987 memset( W, 0, sizeof( W ) );
1988
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001989 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001990
1991 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1992 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1993
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001994#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1996 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001997#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001998
Paul Bakker5121ce52009-01-03 21:22:43 +00001999 j = N->n + 1;
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002000 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2001 * and mpi_montred() calls later. Here we ensure that W[1] and X are
2002 * large enough, and later we'll grow other W[i] to the same length.
2003 * They must not be shrunk midway through this function!
2004 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2006 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2007 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
2009 /*
Paul Bakker50546922012-05-19 08:40:49 +00002010 * Compensate for negative A (and correct at the end)
2011 */
2012 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002013 if( neg )
2014 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002016 Apos.s = 1;
2017 A = &Apos;
2018 }
2019
2020 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002021 * If 1st call, pre-compute R^2 mod N
2022 */
Yuto Takano538a0cb2021-07-14 10:20:09 +01002023 if( prec_RR == NULL || prec_RR->p == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2026 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2027 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002028
Yuto Takano538a0cb2021-07-14 10:20:09 +01002029 if( prec_RR != NULL )
2030 memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031 }
2032 else
Yuto Takano538a0cb2021-07-14 10:20:09 +01002033 memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
2035 /*
2036 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002039 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002041 /* This should be a no-op because W[1] is already that large before
2042 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2043 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine2aa3f162021-06-15 21:22:48 +02002044 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002045 }
Paul Bakkerc2024f42014-01-23 20:38:35 +01002046 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002048
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02002049 /* Note that this is safe because W[1] always has at least N->n limbs
2050 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002051 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
2053 /*
2054 * X = R^2 * R^-1 mod N = R mod N
2055 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002057 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
2059 if( wsize > 1 )
2060 {
2061 /*
2062 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2063 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002064 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002065
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2067 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002068
2069 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002070 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002071
Paul Bakker5121ce52009-01-03 21:22:43 +00002072 /*
2073 * W[i] = W[i - 1] * W[1]
2074 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002075 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002076 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2078 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079
Gilles Peskine4e91d472020-06-04 20:55:15 +02002080 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002081 }
2082 }
2083
2084 nblimbs = E->n;
2085 bufsize = 0;
2086 nbits = 0;
2087 wbits = 0;
2088 state = 0;
2089
2090 while( 1 )
2091 {
2092 if( bufsize == 0 )
2093 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002094 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002095 break;
2096
Paul Bakker0d7702c2013-10-29 16:18:35 +01002097 nblimbs--;
2098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002100 }
2101
2102 bufsize--;
2103
2104 ei = (E->p[nblimbs] >> bufsize) & 1;
2105
2106 /*
2107 * skip leading 0s
2108 */
2109 if( ei == 0 && state == 0 )
2110 continue;
2111
2112 if( ei == 0 && state == 1 )
2113 {
2114 /*
2115 * out of window, square X
2116 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002117 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002118 continue;
2119 }
2120
2121 /*
2122 * add ei to current window
2123 */
2124 state = 2;
2125
2126 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002127 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
2129 if( nbits == wsize )
2130 {
2131 /*
2132 * X = X^wsize R^-1 mod N
2133 */
2134 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002135 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002136
2137 /*
2138 * X = X * W[wbits] R^-1 mod N
2139 */
Manuel Pégourié-Gonnarde22176e2021-06-10 09:34:00 +02002140 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002141 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002142
2143 state--;
2144 nbits = 0;
2145 wbits = 0;
2146 }
2147 }
2148
2149 /*
2150 * process the remaining bits
2151 */
2152 for( i = 0; i < nbits; i++ )
2153 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002154 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
2156 wbits <<= 1;
2157
Paul Bakker66d5d072014-06-17 16:39:18 +02002158 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002159 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002160 }
2161
2162 /*
2163 * X = A^E * R * R^-1 mod N = A^E mod N
2164 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002165 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002166
Hanno Beckera4af1c42017-04-18 09:07:45 +01002167 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002168 {
2169 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002171 }
2172
Paul Bakker5121ce52009-01-03 21:22:43 +00002173cleanup:
2174
Paul Bakker66d5d072014-06-17 16:39:18 +02002175 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002179 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002180
Yuto Takano538a0cb2021-07-14 10:20:09 +01002181 if( prec_RR == NULL || prec_RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183
2184 return( ret );
2185}
2186
Paul Bakker5121ce52009-01-03 21:22:43 +00002187/*
2188 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002191{
Janos Follath24eed8d2019-11-22 13:21:35 +00002192 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002193 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002194 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002195
Hanno Becker73d7d792018-12-11 10:35:51 +00002196 MPI_VALIDATE_RET( G != NULL );
2197 MPI_VALIDATE_RET( A != NULL );
2198 MPI_VALIDATE_RET( B != NULL );
2199
Alexander Ke8ad49f2019-08-16 16:16:07 +03002200 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2203 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 lz = mbedtls_mpi_lsb( &TA );
2206 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002207
Gilles Peskine27253bc2021-06-09 13:26:43 +02002208 /* The loop below gives the correct result when A==0 but not when B==0.
2209 * So have a special case for B==0. Leverage the fact that we just
2210 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2211 * slightly more efficient than cmp_int(). */
2212 if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2213 {
2214 ret = mbedtls_mpi_copy( G, A );
2215 goto cleanup;
2216 }
2217
Paul Bakker66d5d072014-06-17 16:39:18 +02002218 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002219 lz = lzt;
2220
Paul Bakker5121ce52009-01-03 21:22:43 +00002221 TA.s = TB.s = 1;
2222
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002223 /* We mostly follow the procedure described in HAC 14.54, but with some
2224 * minor differences:
2225 * - Sequences of multiplications or divisions by 2 are grouped into a
2226 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002227 * - The procedure in HAC assumes that 0 < TB <= TA.
2228 * - The condition TB <= TA is not actually necessary for correctness.
2229 * TA and TB have symmetric roles except for the loop termination
2230 * condition, and the shifts at the beginning of the loop body
2231 * remove any significance from the ordering of TA vs TB before
2232 * the shifts.
2233 * - If TA = 0, the loop goes through 0 iterations and the result is
2234 * correctly TB.
2235 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002236 *
2237 * For the correctness proof below, decompose the original values of
2238 * A and B as
2239 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2240 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2241 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2242 * and gcd(A',B') is odd or 0.
2243 *
2244 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2245 * The code maintains the following invariant:
2246 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002247 */
2248
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002249 /* Proof that the loop terminates:
2250 * At each iteration, either the right-shift by 1 is made on a nonzero
2251 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2252 * by at least 1, or the right-shift by 1 is made on zero and then
2253 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2254 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002258 /* Divisions by 2 preserve the invariant (I). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2260 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002262 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2263 * TA-TB is even so the division by 2 has an integer result.
2264 * Invariant (I) is preserved since any odd divisor of both TA and TB
2265 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08002266 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002267 * divides TA.
2268 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2272 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273 }
2274 else
2275 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2277 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002279 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002280 }
2281
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002282 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2283 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2284 * - If there was at least one loop iteration, then one of TA or TB is odd,
2285 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2286 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2287 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002288 * 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 +02002289 */
2290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2292 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002293
2294cleanup:
2295
Alexander Ke8ad49f2019-08-16 16:16:07 +03002296 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
2298 return( ret );
2299}
2300
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002301/* Fill X with n_bytes random bytes.
2302 * X must already have room for those bytes.
Gilles Peskineafb2bd22021-06-03 11:51:09 +02002303 * The ordering of the bytes returned from the RNG is suitable for
2304 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskineebe9b6a2021-04-13 21:55:35 +02002305 * The size and sign of X are unchanged.
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002306 * n_bytes must not be 0.
2307 */
2308static int mpi_fill_random_internal(
2309 mbedtls_mpi *X, size_t n_bytes,
2310 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2311{
2312 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2313 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2314 const size_t overhead = ( limbs * ciL ) - n_bytes;
2315
2316 if( X->n < limbs )
2317 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002318
Gilles Peskineebe9b6a2021-04-13 21:55:35 +02002319 memset( X->p, 0, overhead );
2320 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002321 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2322 mpi_bigendian_to_host( X->p, limbs );
2323
2324cleanup:
2325 return( ret );
2326}
2327
Paul Bakker33dc46b2014-04-30 16:11:39 +02002328/*
2329 * Fill X with size bytes of random.
2330 *
2331 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002332 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002333 * deterministic, eg for tests).
2334 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002336 int (*f_rng)(void *, unsigned char *, size_t),
2337 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002338{
Janos Follath24eed8d2019-11-22 13:21:35 +00002339 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002340 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002341
Hanno Becker8ce11a32018-12-19 16:18:52 +00002342 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002343 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002344
Hanno Beckerda1655a2017-10-18 14:21:44 +01002345 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +02002346 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002347 if( size == 0 )
2348 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002349
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002350 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002351
2352cleanup:
2353 return( ret );
2354}
2355
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002356int mbedtls_mpi_random( mbedtls_mpi *X,
2357 mbedtls_mpi_sint min,
2358 const mbedtls_mpi *N,
2359 int (*f_rng)(void *, unsigned char *, size_t),
2360 void *p_rng )
2361{
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002362 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee5381682021-04-13 21:23:25 +02002363 int count;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002364 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002365 size_t n_bits = mbedtls_mpi_bitlen( N );
2366 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002367 mbedtls_mpi lower_bound;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002368
Gilles Peskine1e918f42021-03-29 22:14:51 +02002369 if( min < 0 )
2370 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2371 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2372 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2373
Gilles Peskinee5381682021-04-13 21:23:25 +02002374 /*
2375 * When min == 0, each try has at worst a probability 1/2 of failing
2376 * (the msb has a probability 1/2 of being 0, and then the result will
2377 * be < N), so after 30 tries failure probability is a most 2**(-30).
2378 *
2379 * When N is just below a power of 2, as is the case when generating
Gilles Peskinee842e582021-04-15 11:45:19 +02002380 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee5381682021-04-13 21:23:25 +02002381 * overwhelming probability. When N is just above a power of 2,
Gilles Peskinee842e582021-04-15 11:45:19 +02002382 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee5381682021-04-13 21:23:25 +02002383 * a probability of failing that is almost 1/2.
2384 *
2385 * The probabilities are almost the same if min is nonzero but negligible
2386 * compared to N. This is always the case when N is crypto-sized, but
2387 * it's convenient to support small N for testing purposes. When N
2388 * is small, use a higher repeat count, otherwise the probability of
2389 * failure is macroscopic.
2390 */
Gilles Peskine87823d72021-06-02 21:18:59 +02002391 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee5381682021-04-13 21:23:25 +02002392
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002393 mbedtls_mpi_init( &lower_bound );
2394
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002395 /* Ensure that target MPI has exactly the same number of limbs
2396 * as the upper bound, even if the upper bound has leading zeros.
2397 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskineed32b572021-06-02 22:17:52 +02002398 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002399 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2400 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002401
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002402 /*
2403 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2404 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2405 * - use the same byte ordering;
2406 * - keep the leftmost n_bits bits of the generated octet string;
2407 * - try until result is in the desired range.
2408 * This also avoids any bias, which is especially important for ECDSA.
2409 */
2410 do
2411 {
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002412 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002413 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2414
Gilles Peskinee5381682021-04-13 21:23:25 +02002415 if( --count == 0 )
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002416 {
2417 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2418 goto cleanup;
2419 }
2420
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002421 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2422 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002423 }
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002424 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002425
2426cleanup:
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002427 mbedtls_mpi_free( &lower_bound );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002428 return( ret );
2429}
2430
Paul Bakker5121ce52009-01-03 21:22:43 +00002431/*
2432 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2433 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002435{
Janos Follath24eed8d2019-11-22 13:21:35 +00002436 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002438 MPI_VALIDATE_RET( X != NULL );
2439 MPI_VALIDATE_RET( A != NULL );
2440 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
Hanno Becker4bcb4912017-04-18 15:49:39 +01002442 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2446 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2447 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002449 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002452 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002454 goto cleanup;
2455 }
2456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2458 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2459 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2460 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002462 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2463 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2464 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2465 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002466
2467 do
2468 {
2469 while( ( TU.p[0] & 1 ) == 0 )
2470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002472
2473 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2474 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2476 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002477 }
2478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002479 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2480 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002481 }
2482
2483 while( ( TV.p[0] & 1 ) == 0 )
2484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002486
2487 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2488 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2490 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002491 }
2492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002493 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2494 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002495 }
2496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002498 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2500 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2501 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002502 }
2503 else
2504 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2506 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2507 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002508 }
2509 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002510 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002515 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2516 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002518 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002519
2520cleanup:
2521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002522 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2523 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2524 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002525
2526 return( ret );
2527}
2528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002530
Paul Bakker5121ce52009-01-03 21:22:43 +00002531static const int small_prime[] =
2532{
2533 3, 5, 7, 11, 13, 17, 19, 23,
2534 29, 31, 37, 41, 43, 47, 53, 59,
2535 61, 67, 71, 73, 79, 83, 89, 97,
2536 101, 103, 107, 109, 113, 127, 131, 137,
2537 139, 149, 151, 157, 163, 167, 173, 179,
2538 181, 191, 193, 197, 199, 211, 223, 227,
2539 229, 233, 239, 241, 251, 257, 263, 269,
2540 271, 277, 281, 283, 293, 307, 311, 313,
2541 317, 331, 337, 347, 349, 353, 359, 367,
2542 373, 379, 383, 389, 397, 401, 409, 419,
2543 421, 431, 433, 439, 443, 449, 457, 461,
2544 463, 467, 479, 487, 491, 499, 503, 509,
2545 521, 523, 541, 547, 557, 563, 569, 571,
2546 577, 587, 593, 599, 601, 607, 613, 617,
2547 619, 631, 641, 643, 647, 653, 659, 661,
2548 673, 677, 683, 691, 701, 709, 719, 727,
2549 733, 739, 743, 751, 757, 761, 769, 773,
2550 787, 797, 809, 811, 821, 823, 827, 829,
2551 839, 853, 857, 859, 863, 877, 881, 883,
2552 887, 907, 911, 919, 929, 937, 941, 947,
2553 953, 967, 971, 977, 983, 991, 997, -103
2554};
2555
2556/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002557 * Small divisors test (X must be positive)
2558 *
2559 * Return values:
2560 * 0: no small factor (possible prime, more tests needed)
2561 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002563 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002564 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002566{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002567 int ret = 0;
2568 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002570
Paul Bakker5121ce52009-01-03 21:22:43 +00002571 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002573
2574 for( i = 0; small_prime[i] > 0; i++ )
2575 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002577 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002580
2581 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002583 }
2584
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002585cleanup:
2586 return( ret );
2587}
2588
2589/*
2590 * Miller-Rabin pseudo-primality test (HAC 4.24)
2591 */
Janos Follathda31fa12018-09-03 14:45:23 +01002592static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002593 int (*f_rng)(void *, unsigned char *, size_t),
2594 void *p_rng )
2595{
Pascal Junodb99183d2015-03-11 16:49:45 +01002596 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002597 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002599
Hanno Becker8ce11a32018-12-19 16:18:52 +00002600 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002601 MPI_VALIDATE_RET( f_rng != NULL );
2602
2603 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2604 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002606
Paul Bakker5121ce52009-01-03 21:22:43 +00002607 /*
2608 * W = |X| - 1
2609 * R = W >> lsb( W )
2610 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002611 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2612 s = mbedtls_mpi_lsb( &W );
2613 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2614 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002615
Janos Follathda31fa12018-09-03 14:45:23 +01002616 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002617 {
2618 /*
2619 * pick a random A, 1 < A < |X| - 1
2620 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002621 count = 0;
2622 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002623 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002624
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002625 j = mbedtls_mpi_bitlen( &A );
2626 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002627 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002628 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002629 }
2630
2631 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002632 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2633 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002634 }
2635
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002636 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2637 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002638
2639 /*
2640 * A = A^R mod |X|
2641 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002642 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002644 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2645 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002646 continue;
2647
2648 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002649 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002650 {
2651 /*
2652 * A = A * A mod |X|
2653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2655 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 break;
2659
2660 j++;
2661 }
2662
2663 /*
2664 * not prime if A != |X| - 1 or A == 1
2665 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002666 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2667 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002668 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002670 break;
2671 }
2672 }
2673
2674cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002675 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2676 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002678
2679 return( ret );
2680}
2681
2682/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002683 * Pseudo-primality test: small factors, then Miller-Rabin
2684 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002685int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2686 int (*f_rng)(void *, unsigned char *, size_t),
2687 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002688{
Janos Follath24eed8d2019-11-22 13:21:35 +00002689 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002691 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002692 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002693
2694 XX.s = 1;
2695 XX.n = X->n;
2696 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2699 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2700 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002703 return( 0 );
2704
2705 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2706 {
2707 if( ret == 1 )
2708 return( 0 );
2709
2710 return( ret );
2711 }
2712
Janos Follathda31fa12018-09-03 14:45:23 +01002713 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002714}
2715
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002716/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002717 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002718 *
Janos Follathf301d232018-08-14 13:34:01 +01002719 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2720 * be either 1024 bits or 1536 bits long, and flags must contain
2721 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 */
Janos Follath7c025a92018-08-14 11:08:41 +01002723int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002724 int (*f_rng)(void *, unsigned char *, size_t),
2725 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002726{
Jethro Beekman66689272018-02-14 19:24:10 -08002727#ifdef MBEDTLS_HAVE_INT64
2728// ceil(2^63.5)
2729#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2730#else
2731// ceil(2^31.5)
2732#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2733#endif
2734 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002735 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002736 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002737 mbedtls_mpi_uint r;
2738 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002739
Hanno Becker8ce11a32018-12-19 16:18:52 +00002740 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002741 MPI_VALIDATE_RET( f_rng != NULL );
2742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002743 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2744 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002745
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002746 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002747
2748 n = BITS_TO_LIMBS( nbits );
2749
Janos Follathda31fa12018-09-03 14:45:23 +01002750 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2751 {
2752 /*
2753 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2754 */
2755 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2756 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2757 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2758 }
2759 else
2760 {
2761 /*
2762 * 2^-100 error probability, number of rounds computed based on HAC,
2763 * fact 4.48
2764 */
2765 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2766 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2767 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2768 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2769 }
2770
Jethro Beekman66689272018-02-14 19:24:10 -08002771 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002772 {
Jethro Beekman66689272018-02-14 19:24:10 -08002773 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2774 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2775 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2776
2777 k = n * biL;
2778 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2779 X->p[0] |= 1;
2780
Janos Follath7c025a92018-08-14 11:08:41 +01002781 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002782 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002783 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002786 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002787 }
Jethro Beekman66689272018-02-14 19:24:10 -08002788 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002789 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002790 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002791 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002792 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2793 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002794 */
Jethro Beekman66689272018-02-14 19:24:10 -08002795
2796 X->p[0] |= 2;
2797
2798 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2799 if( r == 0 )
2800 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2801 else if( r == 1 )
2802 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2803
2804 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2805 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2806 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2807
2808 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002809 {
Jethro Beekman66689272018-02-14 19:24:10 -08002810 /*
2811 * First, check small factors for X and Y
2812 * before doing Miller-Rabin on any of them
2813 */
2814 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2815 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002816 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002817 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002818 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002819 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002820 goto cleanup;
2821
2822 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2823 goto cleanup;
2824
2825 /*
2826 * Next candidates. We want to preserve Y = (X-1) / 2 and
2827 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2828 * so up Y by 6 and X by 12.
2829 */
2830 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2831 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002832 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002833 }
2834 }
2835
2836cleanup:
2837
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002838 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002839
2840 return( ret );
2841}
2842
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002843#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002844
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002845#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002846
Paul Bakker23986e52011-04-24 08:57:21 +00002847#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002848
2849static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2850{
2851 { 693, 609, 21 },
2852 { 1764, 868, 28 },
2853 { 768454923, 542167814, 1 }
2854};
2855
Paul Bakker5121ce52009-01-03 21:22:43 +00002856/*
2857 * Checkup routine
2858 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002859int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002860{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002861 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002862 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002864 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2865 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002866
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002867 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002868 "EFE021C2645FD1DC586E69184AF4A31E" \
2869 "D5F53E93B5F123FA41680867BA110131" \
2870 "944FE7952E2517337780CB0DB80E61AA" \
2871 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2872
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002873 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002874 "B2E7EFD37075B9F03FF989C7C5051C20" \
2875 "34D2A323810251127E7BF8625A4F49A5" \
2876 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2877 "5B5C25763222FEFCCFC38B832366C29E" ) );
2878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002879 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002880 "0066A198186C18C10B2F5ED9B522752A" \
2881 "9830B69916E535C8F047518A889A43A5" \
2882 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2883
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002884 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002885
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002886 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002887 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2888 "9E857EA95A03512E2BAE7391688D264A" \
2889 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2890 "8001B72E848A38CAE1C65F78E56ABDEF" \
2891 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2892 "ECF677152EF804370C1A305CAF3B5BF1" \
2893 "30879B56C61DE584A0F53A2447A51E" ) );
2894
2895 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002896 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002898 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002899 {
2900 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002901 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002902
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002903 ret = 1;
2904 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002905 }
2906
2907 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002908 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002909
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002910 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002912 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002913 "256567336059E52CAE22925474705F39A94" ) );
2914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002915 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002916 "6613F26162223DF488E9CD48CC132C7A" \
2917 "0AC93C701B001B092E4E5B9F73BCD27B" \
2918 "9EE50D0657C77F374E903CDFA4C642" ) );
2919
2920 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002921 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002923 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2924 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002925 {
2926 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002927 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002928
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002929 ret = 1;
2930 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002931 }
2932
2933 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002934 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002935
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002936 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002938 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002939 "36E139AEA55215609D2816998ED020BB" \
2940 "BD96C37890F65171D948E9BC7CBAA4D9" \
2941 "325D24D6A3C12710F10A09FA08AB87" ) );
2942
2943 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002944 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002946 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002947 {
2948 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002949 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002950
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002951 ret = 1;
2952 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002953 }
2954
2955 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002956 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002958 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002960 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002961 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2962 "C3DBA76456363A10869622EAC2DD84EC" \
2963 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2964
2965 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002966 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002968 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002969 {
2970 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002971 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002972
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002973 ret = 1;
2974 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002975 }
2976
2977 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002978 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002979
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002980 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002981 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002982
Paul Bakker66d5d072014-06-17 16:39:18 +02002983 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002984 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002985 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2986 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002988 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002990 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002991 {
2992 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002993 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002994
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002995 ret = 1;
2996 goto cleanup;
2997 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002998 }
2999
3000 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003001 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003002
Paul Bakker5121ce52009-01-03 21:22:43 +00003003cleanup:
3004
3005 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003006 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003007
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003008 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3009 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003010
3011 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003012 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003013
3014 return( ret );
3015}
3016
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003017#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003019#endif /* MBEDTLS_BIGNUM_C */