blob: 0e7b3cea024ec49e77b3972cdfb0430e5687a684 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
Simon Butcher15b15d12015-11-26 19:35:03 +000019
Paul Bakker5121ce52009-01-03 21:22:43 +000020/*
Simon Butcher15b15d12015-11-26 19:35:03 +000021 * The following sources were referenced in the design of this Multi-precision
22 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000023 *
Simon Butcher15b15d12015-11-26 19:35:03 +000024 * [1] Handbook of Applied Cryptography - 1997
25 * Menezes, van Oorschot and Vanstone
26 *
27 * [2] Multi-Precision Math
28 * Tom St Denis
29 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30 *
31 * [3] GNU Multi-Precision Arithmetic Library
32 * https://gmplib.org/manual/index.html
33 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000034 */
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Gilles Peskinedb09ef62020-06-03 01:43:33 +020036#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/bignum.h"
Hanno Beckeraef9cc42022-04-11 06:36:29 +010041#include "bignum_internal.h"
Janos Follath4614b9a2022-07-21 15:34:47 +010042#include "bignum_core.h"
Chris Jones4c5819c2021-03-03 17:45:34 +000043#include "bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050044#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000045#include "mbedtls/error.h"
Gabor Mezei22c9a6f2021-10-20 12:09:35 +020046#include "constant_time_internal.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000047
Dave Rodgman351c71b2021-12-06 17:50:53 +000048#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <string.h>
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020059#endif
60
Gabor Mezei66669142022-08-03 12:52:26 +020061#define MPI_VALIDATE_RET( cond ) \
62 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
63#define MPI_VALIDATE( cond ) \
64 MBEDTLS_INTERNAL_VALIDATE( cond )
65
66#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
67#define biL (ciL << 3) /* bits in limb */
68#define biH (ciL << 2) /* half limb size */
69
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010070#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
71
Gabor Mezei66669142022-08-03 12:52:26 +020072/*
73 * Convert between bits/chars and number of limbs
74 * Divide first in order to avoid potential overflows
75 */
76#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
77#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
78
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050079/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050080static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
81{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050082 mbedtls_platform_zeroize( v, ciL * n );
83}
84
Paul Bakker5121ce52009-01-03 21:22:43 +000085/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000086 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000087 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000089{
Hanno Becker73d7d792018-12-11 10:35:51 +000090 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000091
Paul Bakker6c591fa2011-05-05 11:49:20 +000092 X->s = 1;
93 X->n = 0;
94 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000095}
96
97/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000099 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000102 if( X == NULL )
103 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
Paul Bakker6c591fa2011-05-05 11:49:20 +0000105 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200107 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000109 }
110
Paul Bakker6c591fa2011-05-05 11:49:20 +0000111 X->s = 1;
112 X->n = 0;
113 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000114}
115
116/*
117 * Enlarge to the specified number of limbs
118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000120{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000122 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200125 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000126
Paul Bakker5121ce52009-01-03 21:22:43 +0000127 if( X->n < nblimbs )
128 {
Simon Butcher29176892016-05-20 00:19:09 +0100129 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200130 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000131
Paul Bakker5121ce52009-01-03 21:22:43 +0000132 if( X->p != NULL )
133 {
134 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200135 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000137 }
138
139 X->n = nblimbs;
140 X->p = p;
141 }
142
143 return( 0 );
144}
145
146/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 * Resize down as much as possible,
148 * while keeping at least the specified number of limbs
149 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100151{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100153 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000154 MPI_VALIDATE_RET( X != NULL );
155
156 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
157 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100158
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100159 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100160 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100162 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
Gilles Peskineed32b572021-06-02 22:17:52 +0200188/* Resize X to have exactly n limbs and set it to 0. */
189static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
190{
191 if( limbs == 0 )
192 {
193 mbedtls_mpi_free( X );
194 return( 0 );
195 }
196 else if( X->n == limbs )
197 {
198 memset( X->p, 0, limbs * ciL );
199 X->s = 1;
200 return( 0 );
201 }
202 else
203 {
204 mbedtls_mpi_free( X );
205 return( mbedtls_mpi_grow( X, limbs ) );
206 }
207}
208
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100209/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200210 * Copy the contents of Y into X.
211 *
212 * This function is not constant-time. Leading zeros in Y may be removed.
213 *
214 * Ensure that X does not shrink. This is not guaranteed by the public API,
215 * but some code in the bignum module relies on this property, for example
216 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000217 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000219{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100220 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000221 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000222 MPI_VALIDATE_RET( X != NULL );
223 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000224
225 if( X == Y )
226 return( 0 );
227
Gilles Peskinedb420622020-01-20 21:12:50 +0100228 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200229 {
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200230 if( X->n != 0 )
231 {
232 X->s = 1;
233 memset( X->p, 0, X->n * ciL );
234 }
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200235 return( 0 );
236 }
237
Paul Bakker5121ce52009-01-03 21:22:43 +0000238 for( i = Y->n - 1; i > 0; i-- )
239 if( Y->p[i] != 0 )
240 break;
241 i++;
242
243 X->s = Y->s;
244
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100245 if( X->n < i )
246 {
247 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
248 }
249 else
250 {
251 memset( X->p + i, 0, ( X->n - i ) * ciL );
252 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000253
Paul Bakker5121ce52009-01-03 21:22:43 +0000254 memcpy( X->p, Y->p, i * ciL );
255
256cleanup:
257
258 return( ret );
259}
260
261/*
262 * Swap the contents of X and Y
263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000265{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000267 MPI_VALIDATE( X != NULL );
268 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270 memcpy( &T, X, sizeof( mbedtls_mpi ) );
271 memcpy( X, Y, sizeof( mbedtls_mpi ) );
272 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000273}
274
275/*
276 * Set value from integer
277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000279{
Janos Follath24eed8d2019-11-22 13:21:35 +0000280 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000281 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000284 memset( X->p, 0, X->n * ciL );
285
286 X->p[0] = ( z < 0 ) ? -z : z;
287 X->s = ( z < 0 ) ? -1 : 1;
288
289cleanup:
290
291 return( ret );
292}
293
294/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000295 * Get a specific bit
296 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000298{
Hanno Becker73d7d792018-12-11 10:35:51 +0000299 MPI_VALIDATE_RET( X != NULL );
300
Paul Bakker2f5947e2011-05-18 15:47:11 +0000301 if( X->n * biL <= pos )
302 return( 0 );
303
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200304 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000305}
306
Gilles Peskine11cdb052018-11-20 16:47:47 +0100307/* Get a specific byte, without range checks. */
308#define GET_BYTE( X, i ) \
309 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
310
Paul Bakker2f5947e2011-05-18 15:47:11 +0000311/*
312 * Set a bit to a specific value of 0 or 1
313 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200314int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000315{
316 int ret = 0;
317 size_t off = pos / biL;
318 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000319 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000320
321 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200323
Paul Bakker2f5947e2011-05-18 15:47:11 +0000324 if( X->n * biL <= pos )
325 {
326 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200327 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000330 }
331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
333 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000334
335cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200336
Paul Bakker2f5947e2011-05-18 15:47:11 +0000337 return( ret );
338}
339
340/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200341 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000342 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000344{
Paul Bakker23986e52011-04-24 08:57:21 +0000345 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000346 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000347
348 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000349 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000350 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
351 return( count );
352
353 return( 0 );
354}
355
356/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200357 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000358 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200359size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000360{
Janos Follath4670f882022-07-21 18:25:42 +0100361 return mbedtls_mpi_core_bitlen( X->p, X->n );
Paul Bakker5121ce52009-01-03 21:22:43 +0000362}
363
364/*
365 * Return the total size in bytes
366 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000368{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200369 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000370}
371
372/*
373 * Convert an ASCII character to digit value
374 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000376{
377 *d = 255;
378
379 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
380 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
381 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 if( *d >= (mbedtls_mpi_uint) radix )
384 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000385
386 return( 0 );
387}
388
389/*
390 * Import from an ASCII string
391 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000393{
Janos Follath24eed8d2019-11-22 13:21:35 +0000394 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000395 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200396 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 mbedtls_mpi_uint d;
398 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000399 MPI_VALIDATE_RET( X != NULL );
400 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
402 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000403 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000406
Gilles Peskine7cba8592021-06-08 18:32:34 +0200407 if( s[0] == 0 )
408 {
409 mbedtls_mpi_free( X );
410 return( 0 );
411 }
412
Gilles Peskine80f56732021-04-03 18:26:13 +0200413 if( s[0] == '-' )
414 {
415 ++s;
416 sign = -1;
417 }
418
Paul Bakkerff60ee62010-03-16 21:09:09 +0000419 slen = strlen( s );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 if( radix == 16 )
422 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100423 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200424 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
425
Paul Bakkerff60ee62010-03-16 21:09:09 +0000426 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
429 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
Paul Bakker23986e52011-04-24 08:57:21 +0000431 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000432 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200434 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000435 }
436 }
437 else
438 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
Paul Bakkerff60ee62010-03-16 21:09:09 +0000441 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
444 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200445 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000446 }
447 }
448
Gilles Peskine80f56732021-04-03 18:26:13 +0200449 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
450 X->s = -1;
451
Paul Bakker5121ce52009-01-03 21:22:43 +0000452cleanup:
453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
456 return( ret );
457}
458
459/*
Ron Eldora16fa292018-11-20 14:07:01 +0200460 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000461 */
Ron Eldora16fa292018-11-20 14:07:01 +0200462static int mpi_write_hlp( mbedtls_mpi *X, int radix,
463 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000464{
Janos Follath24eed8d2019-11-22 13:21:35 +0000465 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200467 size_t length = 0;
468 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Ron Eldora16fa292018-11-20 14:07:01 +0200470 do
471 {
472 if( length >= buflen )
473 {
474 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
475 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000476
Ron Eldora16fa292018-11-20 14:07:01 +0200477 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
478 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
479 /*
480 * Write the residue in the current position, as an ASCII character.
481 */
482 if( r < 0xA )
483 *(--p_end) = (char)( '0' + r );
484 else
485 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000486
Ron Eldora16fa292018-11-20 14:07:01 +0200487 length++;
488 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
Ron Eldora16fa292018-11-20 14:07:01 +0200490 memmove( *p, p_end, length );
491 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000492
493cleanup:
494
495 return( ret );
496}
497
498/*
499 * Export into an ASCII string
500 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100501int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
502 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000503{
Paul Bakker23986e52011-04-24 08:57:21 +0000504 int ret = 0;
505 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000506 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000508 MPI_VALIDATE_RET( X != NULL );
509 MPI_VALIDATE_RET( olen != NULL );
510 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
512 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000513 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
Hanno Becker23cfea02019-02-04 09:45:07 +0000515 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
516 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
517 * `n`. If radix > 4, this might be a strict
518 * overapproximation of the number of
519 * radix-adic digits needed to present `n`. */
520 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
521 * present `n`. */
522
Janos Follath80470622019-03-06 13:43:02 +0000523 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000524 n += 1; /* Compensate for the divisions above, which round down `n`
525 * in case it's not even. */
526 n += 1; /* Potential '-'-sign. */
527 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
528 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100530 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000531 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100532 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000534 }
535
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100536 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000538
539 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000540 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000541 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000542 buflen--;
543 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000544
545 if( radix == 16 )
546 {
Paul Bakker23986e52011-04-24 08:57:21 +0000547 int c;
548 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000549
Paul Bakker23986e52011-04-24 08:57:21 +0000550 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000551 {
Paul Bakker23986e52011-04-24 08:57:21 +0000552 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000553 {
Paul Bakker23986e52011-04-24 08:57:21 +0000554 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Paul Bakker6c343d72014-07-10 14:36:19 +0200556 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000557 continue;
558
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000559 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000560 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000561 k = 1;
562 }
563 }
564 }
565 else
566 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000568
569 if( T.s == -1 )
570 T.s = 1;
571
Ron Eldora16fa292018-11-20 14:07:01 +0200572 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000573 }
574
575 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100576 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
578cleanup:
579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
582 return( ret );
583}
584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000586/*
587 * Read X from an opened file
588 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000590{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000592 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000593 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000594 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000595 * Buffer should have space for (short) label and decimal formatted MPI,
596 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000597 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Hanno Becker73d7d792018-12-11 10:35:51 +0000600 MPI_VALIDATE_RET( X != NULL );
601 MPI_VALIDATE_RET( fin != NULL );
602
603 if( radix < 2 || radix > 16 )
604 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
605
Paul Bakker5121ce52009-01-03 21:22:43 +0000606 memset( s, 0, sizeof( s ) );
607 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000611 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000613
Hanno Beckerb2034b72017-04-26 11:46:46 +0100614 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
615 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000616
617 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100618 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 if( mpi_get_digit( &d, radix, *p ) != 0 )
620 break;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623}
624
625/*
626 * Write X into an opened file (or stdout if fout == NULL)
627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000629{
Janos Follath24eed8d2019-11-22 13:21:35 +0000630 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000631 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000632 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000633 * Buffer should have space for (short) label and decimal formatted MPI,
634 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000637 MPI_VALIDATE_RET( X != NULL );
638
639 if( radix < 2 || radix > 16 )
640 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100642 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100644 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000645
646 if( p == NULL ) p = "";
647
648 plen = strlen( p );
649 slen = strlen( s );
650 s[slen++] = '\r';
651 s[slen++] = '\n';
652
653 if( fout != NULL )
654 {
655 if( fwrite( p, 1, plen, fout ) != plen ||
656 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000658 }
659 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
662cleanup:
663
664 return( ret );
665}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
668/*
Janos Follatha778a942019-02-13 10:28:28 +0000669 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100670 *
671 * This function is guaranteed to return an MPI with exactly the necessary
672 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000673 */
674int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
675 const unsigned char *buf, size_t buflen )
676{
Janos Follath24eed8d2019-11-22 13:21:35 +0000677 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000678 size_t const limbs = CHARS_TO_LIMBS( buflen );
679
680 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +0200681 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000682
Janos Follath5f016652022-07-22 16:18:41 +0100683 MBEDTLS_MPI_CHK( mbedtls_mpi_core_read_le( X->p, X->n, buf, buflen ) );
Janos Follatha778a942019-02-13 10:28:28 +0000684
685cleanup:
686
Janos Follath171a7ef2019-02-15 16:17:45 +0000687 /*
688 * This function is also used to import keys. However, wiping the buffers
689 * upon failure is not necessary because failure only can happen before any
690 * input is copied.
691 */
Janos Follatha778a942019-02-13 10:28:28 +0000692 return( ret );
693}
694
695/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000696 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100697 *
698 * This function is guaranteed to return an MPI with exactly the necessary
699 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000700 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000702{
Janos Follath24eed8d2019-11-22 13:21:35 +0000703 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath5f016652022-07-22 16:18:41 +0100704 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
Hanno Becker8ce11a32018-12-19 16:18:52 +0000706 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000707 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
708
Hanno Becker073c1992017-10-17 15:17:27 +0100709 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +0200710 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Janos Follath5f016652022-07-22 16:18:41 +0100712 MBEDTLS_MPI_CHK( mbedtls_mpi_core_read_be( X->p, X->n, buf, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
714cleanup:
715
Janos Follath171a7ef2019-02-15 16:17:45 +0000716 /*
717 * This function is also used to import keys. However, wiping the buffers
718 * upon failure is not necessary because failure only can happen before any
719 * input is copied.
720 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000721 return( ret );
722}
723
724/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000725 * Export X into unsigned binary data, little endian
726 */
727int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
728 unsigned char *buf, size_t buflen )
729{
Janos Follath5f016652022-07-22 16:18:41 +0100730 return( mbedtls_mpi_core_write_le( X->p, X->n, buf, buflen) );
Janos Follathe344d0f2019-02-19 16:17:40 +0000731}
732
733/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 * Export X into unsigned binary data, big endian
735 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100736int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
737 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000738{
Janos Follath5f016652022-07-22 16:18:41 +0100739 return( mbedtls_mpi_core_write_be( X->p, X->n, buf, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000740}
741
742/*
743 * Left-shift: X <<= count
744 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000746{
Janos Follath24eed8d2019-11-22 13:21:35 +0000747 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000748 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000750 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000751
752 v0 = count / (biL );
753 t1 = count & (biL - 1);
754
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200755 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000756
Paul Bakkerf9688572011-05-05 10:00:45 +0000757 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200758 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
760 ret = 0;
761
762 /*
763 * shift by count / limb_size
764 */
765 if( v0 > 0 )
766 {
Paul Bakker23986e52011-04-24 08:57:21 +0000767 for( i = X->n; i > v0; i-- )
768 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000769
Paul Bakker23986e52011-04-24 08:57:21 +0000770 for( ; i > 0; i-- )
771 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000772 }
773
774 /*
775 * shift by count % limb_size
776 */
777 if( t1 > 0 )
778 {
779 for( i = v0; i < X->n; i++ )
780 {
781 r1 = X->p[i] >> (biL - t1);
782 X->p[i] <<= t1;
783 X->p[i] |= r0;
784 r0 = r1;
785 }
786 }
787
788cleanup:
789
790 return( ret );
791}
792
793/*
794 * Right-shift: X >>= count
795 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000797{
Paul Bakker23986e52011-04-24 08:57:21 +0000798 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200799 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000800 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000801
802 v0 = count / biL;
803 v1 = count & (biL - 1);
804
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100805 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200806 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100807
Paul Bakker5121ce52009-01-03 21:22:43 +0000808 /*
809 * shift by count / limb_size
810 */
811 if( v0 > 0 )
812 {
813 for( i = 0; i < X->n - v0; i++ )
814 X->p[i] = X->p[i + v0];
815
816 for( ; i < X->n; i++ )
817 X->p[i] = 0;
818 }
819
820 /*
821 * shift by count % limb_size
822 */
823 if( v1 > 0 )
824 {
Paul Bakker23986e52011-04-24 08:57:21 +0000825 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000826 {
Paul Bakker23986e52011-04-24 08:57:21 +0000827 r1 = X->p[i - 1] << (biL - v1);
828 X->p[i - 1] >>= v1;
829 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000830 r0 = r1;
831 }
832 }
833
834 return( 0 );
835}
836
837/*
838 * Compare unsigned values
839 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000841{
Paul Bakker23986e52011-04-24 08:57:21 +0000842 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000843 MPI_VALIDATE_RET( X != NULL );
844 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
Paul Bakker23986e52011-04-24 08:57:21 +0000846 for( i = X->n; i > 0; i-- )
847 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 break;
849
Paul Bakker23986e52011-04-24 08:57:21 +0000850 for( j = Y->n; j > 0; j-- )
851 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 break;
853
Paul Bakker23986e52011-04-24 08:57:21 +0000854 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855 return( 0 );
856
857 if( i > j ) return( 1 );
858 if( j > i ) return( -1 );
859
Paul Bakker23986e52011-04-24 08:57:21 +0000860 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000861 {
Paul Bakker23986e52011-04-24 08:57:21 +0000862 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
863 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000864 }
865
866 return( 0 );
867}
868
869/*
870 * Compare signed values
871 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873{
Paul Bakker23986e52011-04-24 08:57:21 +0000874 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000875 MPI_VALIDATE_RET( X != NULL );
876 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000877
Paul Bakker23986e52011-04-24 08:57:21 +0000878 for( i = X->n; i > 0; i-- )
879 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000880 break;
881
Paul Bakker23986e52011-04-24 08:57:21 +0000882 for( j = Y->n; j > 0; j-- )
883 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 break;
885
Paul Bakker23986e52011-04-24 08:57:21 +0000886 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000887 return( 0 );
888
889 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000890 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000891
892 if( X->s > 0 && Y->s < 0 ) return( 1 );
893 if( Y->s > 0 && X->s < 0 ) return( -1 );
894
Paul Bakker23986e52011-04-24 08:57:21 +0000895 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 {
Paul Bakker23986e52011-04-24 08:57:21 +0000897 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
898 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000899 }
900
901 return( 0 );
902}
903
Janos Follathee6abce2019-09-05 14:47:19 +0100904/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000905 * Compare signed values
906 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000908{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200909 mbedtls_mpi Y;
910 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +0000911 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
913 *p = ( z < 0 ) ? -z : z;
914 Y.s = ( z < 0 ) ? -1 : 1;
915 Y.n = 1;
916 Y.p = p;
917
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200918 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000919}
920
921/*
922 * Unsigned addition: X = |A| + |B| (HAC 14.7)
923 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000925{
Janos Follath24eed8d2019-11-22 13:21:35 +0000926 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000927 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100928 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000929 MPI_VALIDATE_RET( X != NULL );
930 MPI_VALIDATE_RET( A != NULL );
931 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000932
933 if( X == B )
934 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000936 }
937
938 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200940
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000941 /*
942 * X should always be positive as a result of unsigned additions.
943 */
944 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000945
Paul Bakker23986e52011-04-24 08:57:21 +0000946 for( j = B->n; j > 0; j-- )
947 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000948 break;
949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
952 o = B->p; p = X->p; c = 0;
953
Janos Follath6c922682015-10-30 17:43:11 +0100954 /*
955 * tmp is used because it might happen that p == o
956 */
Paul Bakker23986e52011-04-24 08:57:21 +0000957 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000958 {
Janos Follath6c922682015-10-30 17:43:11 +0100959 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +0000960 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +0100961 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +0000962 }
963
964 while( c != 0 )
965 {
966 if( i >= X->n )
967 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000969 p = X->p + i;
970 }
971
Paul Bakker2d319fd2012-09-16 21:34:26 +0000972 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000973 }
974
975cleanup:
976
977 return( ret );
978}
979
Gilles Peskine09ec10a2020-06-09 10:39:38 +0200980/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200981 * Helper for mbedtls_mpi subtraction.
982 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200983 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200984 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200985 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200986 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200987 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200988 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200989 * \param n Number of limbs of \p d, \p l and \p r.
990 * \param[out] d The result of the subtraction.
991 * \param[in] l The left operand.
992 * \param[in] r The right operand.
993 *
994 * \return 1 if `l < r`.
995 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +0000996 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200997static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
998 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200999 const mbedtls_mpi_uint *l,
1000 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001001{
Paul Bakker23986e52011-04-24 08:57:21 +00001002 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001003 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001004
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001005 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001006 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001007 z = ( l[i] < c ); t = l[i] - c;
1008 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001009 }
1010
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001011 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001012}
1013
1014/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001015 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001016 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018{
Janos Follath24eed8d2019-11-22 13:21:35 +00001019 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001020 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001021 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001022 MPI_VALIDATE_RET( X != NULL );
1023 MPI_VALIDATE_RET( A != NULL );
1024 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001025
Paul Bakker23986e52011-04-24 08:57:21 +00001026 for( n = B->n; n > 0; n-- )
1027 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001028 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001029 if( n > A->n )
1030 {
1031 /* B >= (2^ciL)^n > A */
1032 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1033 goto cleanup;
1034 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001035
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001036 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1037
1038 /* Set the high limbs of X to match A. Don't touch the lower limbs
1039 * because X might be aliased to B, and we must not overwrite the
1040 * significant digits of B. */
1041 if( A->n > n )
1042 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1043 if( X->n > A->n )
1044 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1045
1046 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001047 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001048 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001049 /* Propagate the carry to the first nonzero limb of X. */
1050 for( ; n < X->n && X->p[n] == 0; n++ )
1051 --X->p[n];
1052 /* If we ran out of space for the carry, it means that the result
1053 * is negative. */
1054 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001055 {
1056 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1057 goto cleanup;
1058 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001059 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001060 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001061
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001062 /* X should always be positive as a result of unsigned subtractions. */
1063 X->s = 1;
1064
Paul Bakker5121ce52009-01-03 21:22:43 +00001065cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001066 return( ret );
1067}
1068
1069/*
1070 * Signed addition: X = A + B
1071 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001073{
Hanno Becker73d7d792018-12-11 10:35:51 +00001074 int ret, s;
1075 MPI_VALIDATE_RET( X != NULL );
1076 MPI_VALIDATE_RET( A != NULL );
1077 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001078
Hanno Becker73d7d792018-12-11 10:35:51 +00001079 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001080 if( A->s * B->s < 0 )
1081 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001083 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001084 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001085 X->s = s;
1086 }
1087 else
1088 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001090 X->s = -s;
1091 }
1092 }
1093 else
1094 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001096 X->s = s;
1097 }
1098
1099cleanup:
1100
1101 return( ret );
1102}
1103
1104/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001105 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001106 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001108{
Hanno Becker73d7d792018-12-11 10:35:51 +00001109 int ret, s;
1110 MPI_VALIDATE_RET( X != NULL );
1111 MPI_VALIDATE_RET( A != NULL );
1112 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001113
Hanno Becker73d7d792018-12-11 10:35:51 +00001114 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001115 if( A->s * B->s > 0 )
1116 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001118 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001120 X->s = s;
1121 }
1122 else
1123 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001124 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001125 X->s = -s;
1126 }
1127 }
1128 else
1129 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001131 X->s = s;
1132 }
1133
1134cleanup:
1135
1136 return( ret );
1137}
1138
1139/*
1140 * Signed addition: X = A + b
1141 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001142int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001143{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001144 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001145 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001146 MPI_VALIDATE_RET( X != NULL );
1147 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
1149 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001150 B.s = ( b < 0 ) ? -1 : 1;
1151 B.n = 1;
1152 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001153
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001154 return( mbedtls_mpi_add_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001155}
1156
1157/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001158 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001159 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001161{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001162 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001163 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001164 MPI_VALIDATE_RET( X != NULL );
1165 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
1167 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001168 B.s = ( b < 0 ) ? -1 : 1;
1169 B.n = 1;
1170 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001171
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001172 return( mbedtls_mpi_sub_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001173}
1174
Hanno Becker284d7782022-04-11 09:19:24 +01001175mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len,
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001176 const mbedtls_mpi_uint *s, size_t s_len,
1177 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001178{
Hanno Beckere7f14a32022-04-06 06:11:26 +01001179 mbedtls_mpi_uint c = 0; /* carry */
Hanno Becker5d4ceeb2022-04-11 09:46:47 +01001180 size_t excess_len = d_len - s_len;
Hanno Beckerdefe5692022-04-06 06:12:09 +01001181
Hanno Becker63eb28c2022-04-06 11:30:51 +01001182 size_t steps_x8 = s_len / 8;
1183 size_t steps_x1 = s_len & 7;
1184
1185 while( steps_x8-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186 {
Hanno Beckereacf3b92022-04-06 11:25:22 +01001187 MULADDC_X8_INIT
1188 MULADDC_X8_CORE
1189 MULADDC_X8_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 }
1191
Hanno Becker63eb28c2022-04-06 11:30:51 +01001192 while( steps_x1-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 {
Hanno Beckereacf3b92022-04-06 11:25:22 +01001194 MULADDC_X1_INIT
1195 MULADDC_X1_CORE
1196 MULADDC_X1_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Hanno Becker284d7782022-04-11 09:19:24 +01001199 while( excess_len-- )
Gilles Peskine8e464c42020-07-24 00:08:38 +02001200 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 *d += c; c = ( *d < c ); d++;
1202 }
Hanno Beckerdefe5692022-04-06 06:12:09 +01001203
1204 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205}
1206
1207/*
1208 * Baseline multiplication: X = A * B (HAC 14.12)
1209 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001211{
Janos Follath24eed8d2019-11-22 13:21:35 +00001212 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001213 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001215 int result_is_zero = 0;
Hanno Becker73d7d792018-12-11 10:35:51 +00001216 MPI_VALIDATE_RET( X != NULL );
1217 MPI_VALIDATE_RET( A != NULL );
1218 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1223 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
Hanno Beckerda763de2022-04-13 06:50:02 +01001225 for( i = A->n; i > 0; i-- )
1226 if( A->p[i - 1] != 0 )
1227 break;
1228 if( i == 0 )
1229 result_is_zero = 1;
1230
1231 for( j = B->n; j > 0; j-- )
1232 if( B->p[j - 1] != 0 )
1233 break;
1234 if( j == 0 )
1235 result_is_zero = 1;
1236
1237 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001239
Hanno Becker1772e052022-04-13 06:51:40 +01001240 for( size_t k = 0; k < j; k++ )
Hanno Beckerfee261a2022-04-06 06:20:22 +01001241 {
1242 /* We know that there cannot be any carry-out since we're
1243 * iterating from bottom to top. */
Hanno Beckerda763de2022-04-13 06:50:02 +01001244 (void) mbedtls_mpi_core_mla( X->p + k, i + 1,
1245 A->p, i,
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001246 B->p[k] );
Hanno Beckerfee261a2022-04-06 06:20:22 +01001247 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001248
Hanno Beckerda763de2022-04-13 06:50:02 +01001249 /* If the result is 0, we don't shortcut the operation, which reduces
1250 * but does not eliminate side channels leaking the zero-ness. We do
1251 * need to take care to set the sign bit properly since the library does
1252 * not fully support an MPI object with a value of 0 and s == -1. */
1253 if( result_is_zero )
1254 X->s = 1;
1255 else
1256 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001257
1258cleanup:
1259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
1262 return( ret );
1263}
1264
1265/*
1266 * Baseline multiplication: X = A * b
1267 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001268int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001269{
Hanno Becker73d7d792018-12-11 10:35:51 +00001270 MPI_VALIDATE_RET( X != NULL );
1271 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001272
Hanno Becker35771312022-04-14 11:52:11 +01001273 size_t n = A->n;
1274 while( n > 0 && A->p[n - 1] == 0 )
1275 --n;
1276
Hanno Becker74a11a32022-04-06 06:27:00 +01001277 /* The general method below doesn't work if b==0. */
Hanno Becker35771312022-04-14 11:52:11 +01001278 if( b == 0 || n == 0 )
Paul Elliott986b55a2021-04-20 21:46:29 +01001279 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001280
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001281 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001282 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001283 /* In general, A * b requires 1 limb more than b. If
1284 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1285 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001286 * copy() will take care of the growth if needed. However, experimentally,
1287 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001288 * calls to calloc() in ECP code, presumably because it reuses the
1289 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001290 * grow to its final size.
1291 *
1292 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1293 * A,X can be the same. */
Hanno Becker35771312022-04-14 11:52:11 +01001294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001295 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Hanno Becker35771312022-04-14 11:52:11 +01001296 mbedtls_mpi_core_mla( X->p, X->n, A->p, n, b - 1 );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001297
1298cleanup:
1299 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001300}
1301
1302/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001303 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1304 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001305 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001306static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1307 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001308{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001309#if defined(MBEDTLS_HAVE_UDBL)
1310 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001311#else
Simon Butcher9803d072016-01-03 00:24:34 +00001312 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1313 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001314 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1315 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001316 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001317#endif
1318
Simon Butcher15b15d12015-11-26 19:35:03 +00001319 /*
1320 * Check for overflow
1321 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001322 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001323 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001324 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001325
Simon Butcherf5ba0452015-12-27 23:01:55 +00001326 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001327 }
1328
1329#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001330 dividend = (mbedtls_t_udbl) u1 << biL;
1331 dividend |= (mbedtls_t_udbl) u0;
1332 quotient = dividend / d;
1333 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1334 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1335
1336 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001337 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001338
1339 return (mbedtls_mpi_uint) quotient;
1340#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001341
1342 /*
1343 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1344 * Vol. 2 - Seminumerical Algorithms, Knuth
1345 */
1346
1347 /*
1348 * Normalize the divisor, d, and dividend, u0, u1
1349 */
Janos Follath4670f882022-07-21 18:25:42 +01001350 s = mbedtls_mpi_core_clz( d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001351 d = d << s;
1352
1353 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001354 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001355 u0 = u0 << s;
1356
1357 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001358 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001359
1360 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001361 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001362
1363 /*
1364 * Find the first quotient and remainder
1365 */
1366 q1 = u1 / d1;
1367 r0 = u1 - d1 * q1;
1368
1369 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1370 {
1371 q1 -= 1;
1372 r0 += d1;
1373
1374 if ( r0 >= radix ) break;
1375 }
1376
Simon Butcherf5ba0452015-12-27 23:01:55 +00001377 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001378 q0 = rAX / d1;
1379 r0 = rAX - q0 * d1;
1380
1381 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1382 {
1383 q0 -= 1;
1384 r0 += d1;
1385
1386 if ( r0 >= radix ) break;
1387 }
1388
1389 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001390 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001391
1392 quotient = q1 * radix + q0;
1393
1394 return quotient;
1395#endif
1396}
1397
1398/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001400 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001401int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1402 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001403{
Janos Follath24eed8d2019-11-22 13:21:35 +00001404 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001405 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001407 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001408 MPI_VALIDATE_RET( A != NULL );
1409 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001411 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1412 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001415 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001416 /*
1417 * Avoid dynamic memory allocations for constant-size T2.
1418 *
1419 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1420 * so nobody increase the size of the MPI and we're safe to use an on-stack
1421 * buffer.
1422 */
Alexander K35d6d462019-10-31 14:46:45 +03001423 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001424 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1425 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001427 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001428 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001429 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1430 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001431 return( 0 );
1432 }
1433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1435 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001436 X.s = Y.s = 1;
1437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1439 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001440 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001441
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001442 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001443 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001444 {
1445 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1447 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001448 }
1449 else k = 0;
1450
1451 n = X.n - 1;
1452 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001456 {
1457 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001459 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001461
1462 for( i = n; i > t ; i-- )
1463 {
1464 if( X.p[i] >= Y.p[t] )
1465 Z.p[i - t - 1] = ~0;
1466 else
1467 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001468 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1469 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001470 }
1471
Alexander K35d6d462019-10-31 14:46:45 +03001472 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1473 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1474 T2.p[2] = X.p[i];
1475
Paul Bakker5121ce52009-01-03 21:22:43 +00001476 Z.p[i - t - 1]++;
1477 do
1478 {
1479 Z.p[i - t - 1]--;
1480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001482 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001483 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001485 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1489 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1490 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001493 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1495 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1496 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 Z.p[i - t - 1]--;
1498 }
1499 }
1500
1501 if( Q != NULL )
1502 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 Q->s = A->s * B->s;
1505 }
1506
1507 if( R != NULL )
1508 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001510 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 R->s = 1;
1515 }
1516
1517cleanup:
1518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001520 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001521 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001522
1523 return( ret );
1524}
1525
1526/*
1527 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001528 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001529int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1530 const mbedtls_mpi *A,
1531 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001532{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001533 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001535 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001536
1537 p[0] = ( b < 0 ) ? -b : b;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001538 B.s = ( b < 0 ) ? -1 : 1;
1539 B.n = 1;
1540 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001542 return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001543}
1544
1545/*
1546 * Modulo: R = A mod B
1547 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001549{
Janos Follath24eed8d2019-11-22 13:21:35 +00001550 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001551 MPI_VALIDATE_RET( R != NULL );
1552 MPI_VALIDATE_RET( A != NULL );
1553 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1556 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001557
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1561 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001563 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1564 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001565
1566cleanup:
1567
1568 return( ret );
1569}
1570
1571/*
1572 * Modulo: r = A mod b
1573 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001575{
Paul Bakker23986e52011-04-24 08:57:21 +00001576 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001578 MPI_VALIDATE_RET( r != NULL );
1579 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
1581 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001583
1584 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001586
1587 /*
1588 * handle trivial cases
1589 */
Gilles Peskineae25bb02022-06-09 19:32:46 +02001590 if( b == 1 || A->n == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001591 {
1592 *r = 0;
1593 return( 0 );
1594 }
1595
1596 if( b == 2 )
1597 {
1598 *r = A->p[0] & 1;
1599 return( 0 );
1600 }
1601
1602 /*
1603 * general case
1604 */
Paul Bakker23986e52011-04-24 08:57:21 +00001605 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001606 {
Paul Bakker23986e52011-04-24 08:57:21 +00001607 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001608 y = ( y << biH ) | ( x >> biH );
1609 z = y / b;
1610 y -= z * b;
1611
1612 x <<= biH;
1613 y = ( y << biH ) | ( x >> biH );
1614 z = y / b;
1615 y -= z * b;
1616 }
1617
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001618 /*
1619 * If A is negative, then the current y represents a negative value.
1620 * Flipping it to the positive side.
1621 */
1622 if( A->s < 0 && y != 0 )
1623 y = b - y;
1624
Paul Bakker5121ce52009-01-03 21:22:43 +00001625 *r = y;
1626
1627 return( 0 );
1628}
1629
1630/*
1631 * Fast Montgomery initialization (thanks to Tom St Denis)
1632 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001634{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001636 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
1638 x = m0;
1639 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001640
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001641 for( i = biL; i >= 8; i /= 2 )
1642 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
1644 *mm = ~x + 1;
1645}
1646
Gilles Peskine2a82f722020-06-04 15:00:49 +02001647/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1648 *
1649 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02001650 * It must have at least as many limbs as N
1651 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02001652 * On successful completion, A contains the result of
1653 * the multiplication A * B * R^-1 mod N where
1654 * R = (2^ciL)^n.
1655 * \param[in] B One of the numbers to multiply.
1656 * It must be nonzero and must not have more limbs than N
1657 * (B->n <= N->n).
1658 * \param[in] N The modulo. N must be odd.
1659 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1660 * This is -N^-1 mod 2^ciL.
1661 * \param[in,out] T A bignum for temporary storage.
Hanno Beckere1417022022-04-06 06:45:45 +01001662 * It must be at least twice the limb size of N plus 1
1663 * (T->n >= 2 * N->n + 1).
Gilles Peskine2a82f722020-06-04 15:00:49 +02001664 * Its initial content is unused and
1665 * its final content is indeterminate.
1666 * Note that unlike the usual convention in the library
1667 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001668 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001669static 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 +02001670 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001671{
Hanno Becker0235f752022-04-12 10:54:46 +01001672 size_t n, m;
1673 mbedtls_mpi_uint *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001674
1675 memset( T->p, 0, T->n * ciL );
1676
1677 d = T->p;
1678 n = N->n;
1679 m = ( B->n < n ) ? B->n : n;
1680
Hanno Becker0235f752022-04-12 10:54:46 +01001681 for( size_t i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001682 {
Hanno Becker0235f752022-04-12 10:54:46 +01001683 mbedtls_mpi_uint u0, u1;
1684
Paul Bakker5121ce52009-01-03 21:22:43 +00001685 /*
1686 * T = (T + u0*B + u1*N) / 2^biL
1687 */
1688 u0 = A->p[i];
1689 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1690
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001691 (void) mbedtls_mpi_core_mla( d, n + 2,
1692 B->p, m,
1693 u0 );
1694 (void) mbedtls_mpi_core_mla( d, n + 2,
1695 N->p, n,
1696 u1 );
Hanno Beckere1417022022-04-06 06:45:45 +01001697 d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 }
1699
Gilles Peskine221626f2020-06-08 22:37:50 +02001700 /* At this point, d is either the desired result or the desired result
1701 * plus N. We now potentially subtract N, avoiding leaking whether the
1702 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
Gilles Peskine221626f2020-06-08 22:37:50 +02001704 /* Copy the n least significant limbs of d to A, so that
1705 * A = d if d < N (recall that N has n limbs). */
1706 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001707 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02001708 * do the calculation without using conditional tests. */
1709 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02001710 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001711 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02001712 /* If d0 < N then d < (2^biL)^n
1713 * so d[n] == 0 and we want to keep A as it is.
1714 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1715 * so d[n] == 1 and we want to set A to the result of the subtraction
1716 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1717 * This exactly corresponds to a conditional assignment. */
Gabor Mezei90437e32021-10-20 11:59:27 +02001718 mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719}
1720
1721/*
1722 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001723 *
1724 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001725 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001726static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1727 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001728{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001729 mbedtls_mpi_uint z = 1;
1730 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001731
Paul Bakker8ddb6452013-02-27 14:56:33 +01001732 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 U.p = &z;
1734
Gilles Peskine4e91d472020-06-04 20:55:15 +02001735 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001736}
1737
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001738/**
1739 * Select an MPI from a table without leaking the index.
1740 *
1741 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1742 * reads the entire table in order to avoid leaking the value of idx to an
1743 * attacker able to observe memory access patterns.
1744 *
1745 * \param[out] R Where to write the selected MPI.
1746 * \param[in] T The table to read from.
1747 * \param[in] T_size The number of elements in the table.
1748 * \param[in] idx The index of the element to select;
1749 * this must satisfy 0 <= idx < T_size.
1750 *
1751 * \return \c 0 on success, or a negative error code.
1752 */
1753static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
1754{
1755 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1756
1757 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001758 {
1759 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
Gabor Mezei90437e32021-10-20 11:59:27 +02001760 (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001761 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001762
1763cleanup:
1764 return( ret );
1765}
1766
Paul Bakker5121ce52009-01-03 21:22:43 +00001767/*
1768 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1769 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001770int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1771 const mbedtls_mpi *E, const mbedtls_mpi *N,
Yuto Takano538a0cb2021-07-14 10:20:09 +01001772 mbedtls_mpi *prec_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001773{
Janos Follath24eed8d2019-11-22 13:21:35 +00001774 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001775 size_t wbits, wsize, one = 1;
1776 size_t i, j, nblimbs;
1777 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001779 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001780 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001781
Hanno Becker73d7d792018-12-11 10:35:51 +00001782 MPI_VALIDATE_RET( X != NULL );
1783 MPI_VALIDATE_RET( A != NULL );
1784 MPI_VALIDATE_RET( E != NULL );
1785 MPI_VALIDATE_RET( N != NULL );
1786
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001787 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001788 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1791 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001792
Chris Jones9246d042020-11-25 15:12:39 +00001793 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
1794 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
1795 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1796
Paul Bakkerf6198c12012-05-16 08:02:29 +00001797 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001798 * Init temps and window size
1799 */
1800 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1802 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001803 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804 memset( W, 0, sizeof( W ) );
1805
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001806 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
1808 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1809 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1810
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001811#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1813 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001814#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001815
Paul Bakker5121ce52009-01-03 21:22:43 +00001816 j = N->n + 1;
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001817 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
1818 * and mpi_montred() calls later. Here we ensure that W[1] and X are
1819 * large enough, and later we'll grow other W[i] to the same length.
1820 * They must not be shrunk midway through this function!
1821 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1823 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1824 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
1826 /*
Paul Bakker50546922012-05-19 08:40:49 +00001827 * Compensate for negative A (and correct at the end)
1828 */
1829 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001830 if( neg )
1831 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001833 Apos.s = 1;
1834 A = &Apos;
1835 }
1836
1837 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 * If 1st call, pre-compute R^2 mod N
1839 */
Yuto Takano538a0cb2021-07-14 10:20:09 +01001840 if( prec_RR == NULL || prec_RR->p == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1843 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1844 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
Yuto Takano538a0cb2021-07-14 10:20:09 +01001846 if( prec_RR != NULL )
1847 memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848 }
1849 else
Yuto Takano538a0cb2021-07-14 10:20:09 +01001850 memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
1852 /*
1853 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1854 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001856 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001858 /* This should be a no-op because W[1] is already that large before
1859 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
1860 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine2aa3f162021-06-15 21:22:48 +02001861 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001862 }
Paul Bakkerc2024f42014-01-23 20:38:35 +01001863 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001865
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001866 /* Note that this is safe because W[1] always has at least N->n limbs
1867 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001868 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
1870 /*
1871 * X = R^2 * R^-1 mod N = R mod N
1872 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02001874 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
1876 if( wsize > 1 )
1877 {
1878 /*
1879 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1880 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001881 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1884 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
1886 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02001887 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001888
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 /*
1890 * W[i] = W[i - 1] * W[1]
1891 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001892 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001893 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1895 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Gilles Peskine4e91d472020-06-04 20:55:15 +02001897 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898 }
1899 }
1900
1901 nblimbs = E->n;
1902 bufsize = 0;
1903 nbits = 0;
1904 wbits = 0;
1905 state = 0;
1906
1907 while( 1 )
1908 {
1909 if( bufsize == 0 )
1910 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001911 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001912 break;
1913
Paul Bakker0d7702c2013-10-29 16:18:35 +01001914 nblimbs--;
1915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 }
1918
1919 bufsize--;
1920
1921 ei = (E->p[nblimbs] >> bufsize) & 1;
1922
1923 /*
1924 * skip leading 0s
1925 */
1926 if( ei == 0 && state == 0 )
1927 continue;
1928
1929 if( ei == 0 && state == 1 )
1930 {
1931 /*
1932 * out of window, square X
1933 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001934 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 continue;
1936 }
1937
1938 /*
1939 * add ei to current window
1940 */
1941 state = 2;
1942
1943 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001944 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
1946 if( nbits == wsize )
1947 {
1948 /*
1949 * X = X^wsize R^-1 mod N
1950 */
1951 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02001952 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
1954 /*
1955 * X = X * W[wbits] R^-1 mod N
1956 */
Manuel Pégourié-Gonnarde22176e2021-06-10 09:34:00 +02001957 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001958 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
1960 state--;
1961 nbits = 0;
1962 wbits = 0;
1963 }
1964 }
1965
1966 /*
1967 * process the remaining bits
1968 */
1969 for( i = 0; i < nbits; i++ )
1970 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02001971 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
1973 wbits <<= 1;
1974
Paul Bakker66d5d072014-06-17 16:39:18 +02001975 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02001976 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977 }
1978
1979 /*
1980 * X = A^E * R * R^-1 mod N = A^E mod N
1981 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001982 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
Hanno Beckera4af1c42017-04-18 09:07:45 +01001984 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001985 {
1986 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001987 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001988 }
1989
Paul Bakker5121ce52009-01-03 21:22:43 +00001990cleanup:
1991
Paul Bakker66d5d072014-06-17 16:39:18 +02001992 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001996 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001997
Yuto Takano538a0cb2021-07-14 10:20:09 +01001998 if( prec_RR == NULL || prec_RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001999 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
2001 return( ret );
2002}
2003
Paul Bakker5121ce52009-01-03 21:22:43 +00002004/*
2005 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2006 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002008{
Janos Follath24eed8d2019-11-22 13:21:35 +00002009 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002010 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002011 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002012
Hanno Becker73d7d792018-12-11 10:35:51 +00002013 MPI_VALIDATE_RET( G != NULL );
2014 MPI_VALIDATE_RET( A != NULL );
2015 MPI_VALIDATE_RET( B != NULL );
2016
Alexander Ke8ad49f2019-08-16 16:16:07 +03002017 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2020 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022 lz = mbedtls_mpi_lsb( &TA );
2023 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002024
Gilles Peskine27253bc2021-06-09 13:26:43 +02002025 /* The loop below gives the correct result when A==0 but not when B==0.
2026 * So have a special case for B==0. Leverage the fact that we just
2027 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2028 * slightly more efficient than cmp_int(). */
2029 if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2030 {
2031 ret = mbedtls_mpi_copy( G, A );
2032 goto cleanup;
2033 }
2034
Paul Bakker66d5d072014-06-17 16:39:18 +02002035 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002036 lz = lzt;
2037
Paul Bakker5121ce52009-01-03 21:22:43 +00002038 TA.s = TB.s = 1;
2039
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002040 /* We mostly follow the procedure described in HAC 14.54, but with some
2041 * minor differences:
2042 * - Sequences of multiplications or divisions by 2 are grouped into a
2043 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02002044 * - The procedure in HAC assumes that 0 < TB <= TA.
2045 * - The condition TB <= TA is not actually necessary for correctness.
2046 * TA and TB have symmetric roles except for the loop termination
2047 * condition, and the shifts at the beginning of the loop body
2048 * remove any significance from the ordering of TA vs TB before
2049 * the shifts.
2050 * - If TA = 0, the loop goes through 0 iterations and the result is
2051 * correctly TB.
2052 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002053 *
2054 * For the correctness proof below, decompose the original values of
2055 * A and B as
2056 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2057 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2058 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2059 * and gcd(A',B') is odd or 0.
2060 *
2061 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2062 * The code maintains the following invariant:
2063 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02002064 */
2065
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002066 /* Proof that the loop terminates:
2067 * At each iteration, either the right-shift by 1 is made on a nonzero
2068 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2069 * by at least 1, or the right-shift by 1 is made on zero and then
2070 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2071 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2072 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002074 {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002075 /* Divisions by 2 preserve the invariant (I). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2077 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002079 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2080 * TA-TB is even so the division by 2 has an integer result.
2081 * Invariant (I) is preserved since any odd divisor of both TA and TB
2082 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08002083 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002084 * divides TA.
2085 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002087 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2089 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 }
2091 else
2092 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2094 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002096 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002097 }
2098
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002099 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2100 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2101 * - If there was at least one loop iteration, then one of TA or TB is odd,
2102 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2103 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2104 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002105 * 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 +02002106 */
2107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002108 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2109 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110
2111cleanup:
2112
Alexander Ke8ad49f2019-08-16 16:16:07 +03002113 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
2115 return( ret );
2116}
2117
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002118/* Fill X with n_bytes random bytes.
2119 * X must already have room for those bytes.
Gilles Peskineafb2bd22021-06-03 11:51:09 +02002120 * The ordering of the bytes returned from the RNG is suitable for
2121 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskineebe9b6a2021-04-13 21:55:35 +02002122 * The size and sign of X are unchanged.
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002123 * n_bytes must not be 0.
2124 */
2125static int mpi_fill_random_internal(
2126 mbedtls_mpi *X, size_t n_bytes,
2127 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2128{
2129 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2130 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2131 const size_t overhead = ( limbs * ciL ) - n_bytes;
2132
2133 if( X->n < limbs )
2134 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002135
Gilles Peskineebe9b6a2021-04-13 21:55:35 +02002136 memset( X->p, 0, overhead );
2137 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002138 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
Janos Follath4670f882022-07-21 18:25:42 +01002139 mbedtls_mpi_core_bigendian_to_host( X->p, limbs );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002140
2141cleanup:
2142 return( ret );
2143}
2144
Paul Bakker33dc46b2014-04-30 16:11:39 +02002145/*
2146 * Fill X with size bytes of random.
2147 *
2148 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002149 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002150 * deterministic, eg for tests).
2151 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002153 int (*f_rng)(void *, unsigned char *, size_t),
2154 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002155{
Janos Follath24eed8d2019-11-22 13:21:35 +00002156 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002157 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002158
Hanno Becker8ce11a32018-12-19 16:18:52 +00002159 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002160 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002161
Hanno Beckerda1655a2017-10-18 14:21:44 +01002162 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskineed32b572021-06-02 22:17:52 +02002163 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002164 if( size == 0 )
2165 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002166
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002167 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002168
2169cleanup:
2170 return( ret );
2171}
2172
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002173int mbedtls_mpi_random( mbedtls_mpi *X,
2174 mbedtls_mpi_sint min,
2175 const mbedtls_mpi *N,
2176 int (*f_rng)(void *, unsigned char *, size_t),
2177 void *p_rng )
2178{
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002179 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee5381682021-04-13 21:23:25 +02002180 int count;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002181 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002182 size_t n_bits = mbedtls_mpi_bitlen( N );
2183 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002184 mbedtls_mpi lower_bound;
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002185
Gilles Peskine1e918f42021-03-29 22:14:51 +02002186 if( min < 0 )
2187 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2188 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2189 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2190
Gilles Peskinee5381682021-04-13 21:23:25 +02002191 /*
2192 * When min == 0, each try has at worst a probability 1/2 of failing
2193 * (the msb has a probability 1/2 of being 0, and then the result will
2194 * be < N), so after 30 tries failure probability is a most 2**(-30).
2195 *
2196 * When N is just below a power of 2, as is the case when generating
Gilles Peskinee842e582021-04-15 11:45:19 +02002197 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee5381682021-04-13 21:23:25 +02002198 * overwhelming probability. When N is just above a power of 2,
Gilles Peskinee842e582021-04-15 11:45:19 +02002199 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee5381682021-04-13 21:23:25 +02002200 * a probability of failing that is almost 1/2.
2201 *
2202 * The probabilities are almost the same if min is nonzero but negligible
2203 * compared to N. This is always the case when N is crypto-sized, but
2204 * it's convenient to support small N for testing purposes. When N
2205 * is small, use a higher repeat count, otherwise the probability of
2206 * failure is macroscopic.
2207 */
Gilles Peskine87823d72021-06-02 21:18:59 +02002208 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee5381682021-04-13 21:23:25 +02002209
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002210 mbedtls_mpi_init( &lower_bound );
2211
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002212 /* Ensure that target MPI has exactly the same number of limbs
2213 * as the upper bound, even if the upper bound has leading zeros.
2214 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskineed32b572021-06-02 22:17:52 +02002215 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2217 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002218
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002219 /*
2220 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2221 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2222 * - use the same byte ordering;
2223 * - keep the leftmost n_bits bits of the generated octet string;
2224 * - try until result is in the desired range.
2225 * This also avoids any bias, which is especially important for ECDSA.
2226 */
2227 do
2228 {
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002229 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2231
Gilles Peskinee5381682021-04-13 21:23:25 +02002232 if( --count == 0 )
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002233 {
2234 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2235 goto cleanup;
2236 }
2237
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002238 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2239 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002240 }
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002241 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002242
2243cleanup:
Gilles Peskine5b0589e2021-04-13 21:09:10 +02002244 mbedtls_mpi_free( &lower_bound );
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002245 return( ret );
2246}
2247
Paul Bakker5121ce52009-01-03 21:22:43 +00002248/*
2249 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2250 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002252{
Janos Follath24eed8d2019-11-22 13:21:35 +00002253 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002255 MPI_VALIDATE_RET( X != NULL );
2256 MPI_VALIDATE_RET( A != NULL );
2257 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
Hanno Becker4bcb4912017-04-18 15:49:39 +01002259 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2263 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2264 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002271 goto cleanup;
2272 }
2273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2275 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2276 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2277 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2280 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2281 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2282 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283
2284 do
2285 {
2286 while( ( TU.p[0] & 1 ) == 0 )
2287 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
2290 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2291 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2293 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002294 }
2295
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2297 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002298 }
2299
2300 while( ( TV.p[0] & 1 ) == 0 )
2301 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
2304 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2305 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2307 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 }
2309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2311 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 }
2313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2317 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2318 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 }
2320 else
2321 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2323 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2324 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002325 }
2326 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2330 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2333 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
2337cleanup:
2338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2340 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2341 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
2343 return( ret );
2344}
2345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002347
Paul Bakker5121ce52009-01-03 21:22:43 +00002348static const int small_prime[] =
2349{
2350 3, 5, 7, 11, 13, 17, 19, 23,
2351 29, 31, 37, 41, 43, 47, 53, 59,
2352 61, 67, 71, 73, 79, 83, 89, 97,
2353 101, 103, 107, 109, 113, 127, 131, 137,
2354 139, 149, 151, 157, 163, 167, 173, 179,
2355 181, 191, 193, 197, 199, 211, 223, 227,
2356 229, 233, 239, 241, 251, 257, 263, 269,
2357 271, 277, 281, 283, 293, 307, 311, 313,
2358 317, 331, 337, 347, 349, 353, 359, 367,
2359 373, 379, 383, 389, 397, 401, 409, 419,
2360 421, 431, 433, 439, 443, 449, 457, 461,
2361 463, 467, 479, 487, 491, 499, 503, 509,
2362 521, 523, 541, 547, 557, 563, 569, 571,
2363 577, 587, 593, 599, 601, 607, 613, 617,
2364 619, 631, 641, 643, 647, 653, 659, 661,
2365 673, 677, 683, 691, 701, 709, 719, 727,
2366 733, 739, 743, 751, 757, 761, 769, 773,
2367 787, 797, 809, 811, 821, 823, 827, 829,
2368 839, 853, 857, 859, 863, 877, 881, 883,
2369 887, 907, 911, 919, 929, 937, 941, 947,
2370 953, 967, 971, 977, 983, 991, 997, -103
2371};
2372
2373/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002374 * Small divisors test (X must be positive)
2375 *
2376 * Return values:
2377 * 0: no small factor (possible prime, more tests needed)
2378 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002380 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002381 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002383{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002384 int ret = 0;
2385 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
Paul Bakker5121ce52009-01-03 21:22:43 +00002388 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002390
2391 for( i = 0; small_prime[i] > 0; i++ )
2392 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002394 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
2398 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 }
2401
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002402cleanup:
2403 return( ret );
2404}
2405
2406/*
2407 * Miller-Rabin pseudo-primality test (HAC 4.24)
2408 */
Janos Follathda31fa12018-09-03 14:45:23 +01002409static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002410 int (*f_rng)(void *, unsigned char *, size_t),
2411 void *p_rng )
2412{
Pascal Junodb99183d2015-03-11 16:49:45 +01002413 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002414 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002416
Hanno Becker8ce11a32018-12-19 16:18:52 +00002417 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002418 MPI_VALIDATE_RET( f_rng != NULL );
2419
2420 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2421 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002423
Paul Bakker5121ce52009-01-03 21:22:43 +00002424 /*
2425 * W = |X| - 1
2426 * R = W >> lsb( W )
2427 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002428 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2429 s = mbedtls_mpi_lsb( &W );
2430 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2431 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Janos Follathda31fa12018-09-03 14:45:23 +01002433 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002434 {
2435 /*
2436 * pick a random A, 1 < A < |X| - 1
2437 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002438 count = 0;
2439 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002440 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002441
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002442 j = mbedtls_mpi_bitlen( &A );
2443 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002444 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002445 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002446 }
2447
2448 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002449 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2450 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002451 }
2452
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002453 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2454 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002455
2456 /*
2457 * A = A^R mod |X|
2458 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2462 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002463 continue;
2464
2465 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002467 {
2468 /*
2469 * A = A * A mod |X|
2470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2472 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002474 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002475 break;
2476
2477 j++;
2478 }
2479
2480 /*
2481 * not prime if A != |X| - 1 or A == 1
2482 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2484 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002485 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002487 break;
2488 }
2489 }
2490
2491cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002492 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2493 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002495
2496 return( ret );
2497}
2498
2499/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002500 * Pseudo-primality test: small factors, then Miller-Rabin
2501 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002502int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2503 int (*f_rng)(void *, unsigned char *, size_t),
2504 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002505{
Janos Follath24eed8d2019-11-22 13:21:35 +00002506 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002508 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002509 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002510
2511 XX.s = 1;
2512 XX.n = X->n;
2513 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002515 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2516 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2517 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002519 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002520 return( 0 );
2521
2522 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2523 {
2524 if( ret == 1 )
2525 return( 0 );
2526
2527 return( ret );
2528 }
2529
Janos Follathda31fa12018-09-03 14:45:23 +01002530 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002531}
2532
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002533/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002534 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002535 *
Janos Follathf301d232018-08-14 13:34:01 +01002536 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2537 * be either 1024 bits or 1536 bits long, and flags must contain
2538 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002539 */
Janos Follath7c025a92018-08-14 11:08:41 +01002540int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002541 int (*f_rng)(void *, unsigned char *, size_t),
2542 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002543{
Jethro Beekman66689272018-02-14 19:24:10 -08002544#ifdef MBEDTLS_HAVE_INT64
2545// ceil(2^63.5)
2546#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2547#else
2548// ceil(2^31.5)
2549#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2550#endif
2551 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002552 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002553 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 mbedtls_mpi_uint r;
2555 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002556
Hanno Becker8ce11a32018-12-19 16:18:52 +00002557 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002558 MPI_VALIDATE_RET( f_rng != NULL );
2559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002560 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2561 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002563 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002564
2565 n = BITS_TO_LIMBS( nbits );
2566
Janos Follathda31fa12018-09-03 14:45:23 +01002567 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2568 {
2569 /*
2570 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2571 */
2572 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2573 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2574 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2575 }
2576 else
2577 {
2578 /*
2579 * 2^-100 error probability, number of rounds computed based on HAC,
2580 * fact 4.48
2581 */
2582 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2583 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2584 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2585 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2586 }
2587
Jethro Beekman66689272018-02-14 19:24:10 -08002588 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002589 {
Jethro Beekman66689272018-02-14 19:24:10 -08002590 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2591 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2592 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2593
2594 k = n * biL;
2595 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2596 X->p[0] |= 1;
2597
Janos Follath7c025a92018-08-14 11:08:41 +01002598 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002599 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002600 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002602 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002603 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002604 }
Jethro Beekman66689272018-02-14 19:24:10 -08002605 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002606 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002607 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002608 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002609 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2610 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002611 */
Jethro Beekman66689272018-02-14 19:24:10 -08002612
2613 X->p[0] |= 2;
2614
2615 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2616 if( r == 0 )
2617 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2618 else if( r == 1 )
2619 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2620
2621 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2622 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2623 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2624
2625 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002626 {
Jethro Beekman66689272018-02-14 19:24:10 -08002627 /*
2628 * First, check small factors for X and Y
2629 * before doing Miller-Rabin on any of them
2630 */
2631 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2632 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002633 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002634 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002635 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002636 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002637 goto cleanup;
2638
2639 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2640 goto cleanup;
2641
2642 /*
2643 * Next candidates. We want to preserve Y = (X-1) / 2 and
2644 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2645 * so up Y by 6 and X by 12.
2646 */
2647 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2648 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002649 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002650 }
2651 }
2652
2653cleanup:
2654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002655 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002656
2657 return( ret );
2658}
2659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002662#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002663
Paul Bakker23986e52011-04-24 08:57:21 +00002664#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002665
2666static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2667{
2668 { 693, 609, 21 },
2669 { 1764, 868, 28 },
2670 { 768454923, 542167814, 1 }
2671};
2672
Paul Bakker5121ce52009-01-03 21:22:43 +00002673/*
2674 * Checkup routine
2675 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002676int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002677{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002678 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002679 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002680
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002681 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2682 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002685 "EFE021C2645FD1DC586E69184AF4A31E" \
2686 "D5F53E93B5F123FA41680867BA110131" \
2687 "944FE7952E2517337780CB0DB80E61AA" \
2688 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002691 "B2E7EFD37075B9F03FF989C7C5051C20" \
2692 "34D2A323810251127E7BF8625A4F49A5" \
2693 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2694 "5B5C25763222FEFCCFC38B832366C29E" ) );
2695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002696 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002697 "0066A198186C18C10B2F5ED9B522752A" \
2698 "9830B69916E535C8F047518A889A43A5" \
2699 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002703 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002704 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2705 "9E857EA95A03512E2BAE7391688D264A" \
2706 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2707 "8001B72E848A38CAE1C65F78E56ABDEF" \
2708 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2709 "ECF677152EF804370C1A305CAF3B5BF1" \
2710 "30879B56C61DE584A0F53A2447A51E" ) );
2711
2712 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002713 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002714
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002715 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002716 {
2717 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002718 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002719
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002720 ret = 1;
2721 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 }
2723
2724 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002727 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002728
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002729 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002730 "256567336059E52CAE22925474705F39A94" ) );
2731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002732 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002733 "6613F26162223DF488E9CD48CC132C7A" \
2734 "0AC93C701B001B092E4E5B9F73BCD27B" \
2735 "9EE50D0657C77F374E903CDFA4C642" ) );
2736
2737 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002738 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002740 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2741 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002742 {
2743 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002745
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002746 ret = 1;
2747 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002748 }
2749
2750 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002751 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002752
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002753 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002755 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002756 "36E139AEA55215609D2816998ED020BB" \
2757 "BD96C37890F65171D948E9BC7CBAA4D9" \
2758 "325D24D6A3C12710F10A09FA08AB87" ) );
2759
2760 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002761 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002763 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002764 {
2765 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002766 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002767
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002768 ret = 1;
2769 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002770 }
2771
2772 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002773 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002774
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002775 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002776
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002777 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002778 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2779 "C3DBA76456363A10869622EAC2DD84EC" \
2780 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2781
2782 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002786 {
2787 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002788 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002789
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002790 ret = 1;
2791 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002792 }
2793
2794 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002796
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002797 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002798 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002799
Paul Bakker66d5d072014-06-17 16:39:18 +02002800 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002801 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002802 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2803 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002805 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002808 {
2809 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002810 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002811
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002812 ret = 1;
2813 goto cleanup;
2814 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002815 }
2816
2817 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002818 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002819
Paul Bakker5121ce52009-01-03 21:22:43 +00002820cleanup:
2821
2822 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02002823 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2826 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002827
2828 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002829 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002830
2831 return( ret );
2832}
2833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002834#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002836#endif /* MBEDTLS_BIGNUM_C */