blob: 9dcd0f895dfb79215bd81f138f082fce47cc30c9 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
Simon Butcher15b15d12015-11-26 19:35:03 +000019
Paul Bakker5121ce52009-01-03 21:22:43 +000020/*
Simon Butcher15b15d12015-11-26 19:35:03 +000021 * The following sources were referenced in the design of this Multi-precision
22 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000023 *
Simon Butcher15b15d12015-11-26 19:35:03 +000024 * [1] Handbook of Applied Cryptography - 1997
25 * Menezes, van Oorschot and Vanstone
26 *
27 * [2] Multi-Precision Math
28 * Tom St Denis
29 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30 *
31 * [3] GNU Multi-Precision Arithmetic Library
32 * https://gmplib.org/manual/index.html
33 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000034 */
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Gilles Peskinedb09ef62020-06-03 01:43:33 +020036#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/bignum.h"
41#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050042#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000043#include "mbedtls/error.h"
Gabor Mezeic0ae1cf2021-10-20 12:09:35 +020044#include "constant_time_internal.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Tom Cosgrove58efe612021-11-15 09:59:53 +000046#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000047#include <string.h>
48
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020050
Hanno Becker73d7d792018-12-11 10:35:51 +000051#define MPI_VALIDATE_RET( cond ) \
52 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
53#define MPI_VALIDATE( cond ) \
54 MBEDTLS_INTERNAL_VALIDATE( cond )
55
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000057#define biL (ciL << 3) /* bits in limb */
58#define biH (ciL << 2) /* half limb size */
59
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010060#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
61
Paul Bakker5121ce52009-01-03 21:22:43 +000062/*
63 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020064 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000065 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020066#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
67#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000068
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050069/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050070static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
71{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050072 mbedtls_platform_zeroize( v, ciL * n );
73}
74
Paul Bakker5121ce52009-01-03 21:22:43 +000075/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000076 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000077 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000079{
Hanno Becker73d7d792018-12-11 10:35:51 +000080 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000081
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 X->s = 1;
83 X->n = 0;
84 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000085}
86
87/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000089 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000091{
Paul Bakker6c591fa2011-05-05 11:49:20 +000092 if( X == NULL )
93 return;
Paul Bakker5121ce52009-01-03 21:22:43 +000094
Paul Bakker6c591fa2011-05-05 11:49:20 +000095 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +000096 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +020097 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +000099 }
100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 X->s = 1;
102 X->n = 0;
103 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104}
105
106/*
107 * Enlarge to the specified number of limbs
108 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000110{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000112 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200115 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000116
Paul Bakker5121ce52009-01-03 21:22:43 +0000117 if( X->n < nblimbs )
118 {
Simon Butcher29176892016-05-20 00:19:09 +0100119 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200120 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000121
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 if( X->p != NULL )
123 {
124 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200125 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000127 }
128
129 X->n = nblimbs;
130 X->p = p;
131 }
132
133 return( 0 );
134}
135
136/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100137 * Resize down as much as possible,
138 * while keeping at least the specified number of limbs
139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000144 MPI_VALIDATE_RET( X != NULL );
145
146 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
147 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100149 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100152 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100153
154 for( i = X->n - 1; i > 0; i-- )
155 if( X->p[i] != 0 )
156 break;
157 i++;
158
159 if( i < nblimbs )
160 i = nblimbs;
161
Simon Butcher29176892016-05-20 00:19:09 +0100162 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200163 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100165 if( X->p != NULL )
166 {
167 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200168 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170 }
171
172 X->n = i;
173 X->p = p;
174
175 return( 0 );
176}
177
Gilles Peskine3130ce22021-06-02 22:17:52 +0200178/* Resize X to have exactly n limbs and set it to 0. */
179static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
180{
181 if( limbs == 0 )
182 {
183 mbedtls_mpi_free( X );
184 return( 0 );
185 }
186 else if( X->n == limbs )
187 {
188 memset( X->p, 0, limbs * ciL );
189 X->s = 1;
190 return( 0 );
191 }
192 else
193 {
194 mbedtls_mpi_free( X );
195 return( mbedtls_mpi_grow( X, limbs ) );
196 }
197}
198
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100199/*
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200200 * Copy the contents of Y into X.
201 *
202 * This function is not constant-time. Leading zeros in Y may be removed.
203 *
204 * Ensure that X does not shrink. This is not guaranteed by the public API,
205 * but some code in the bignum module relies on this property, for example
206 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000209{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100210 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000211 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000212 MPI_VALIDATE_RET( X != NULL );
213 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
215 if( X == Y )
216 return( 0 );
217
Gilles Peskinedb420622020-01-20 21:12:50 +0100218 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200219 {
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200220 if( X->n != 0 )
221 {
222 X->s = 1;
223 memset( X->p, 0, X->n * ciL );
224 }
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200225 return( 0 );
226 }
227
Paul Bakker5121ce52009-01-03 21:22:43 +0000228 for( i = Y->n - 1; i > 0; i-- )
229 if( Y->p[i] != 0 )
230 break;
231 i++;
232
233 X->s = Y->s;
234
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100235 if( X->n < i )
236 {
237 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
238 }
239 else
240 {
241 memset( X->p + i, 0, ( X->n - i ) * ciL );
242 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000243
Paul Bakker5121ce52009-01-03 21:22:43 +0000244 memcpy( X->p, Y->p, i * ciL );
245
246cleanup:
247
248 return( ret );
249}
250
251/*
252 * Swap the contents of X and Y
253 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000255{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000257 MPI_VALIDATE( X != NULL );
258 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 memcpy( &T, X, sizeof( mbedtls_mpi ) );
261 memcpy( X, Y, sizeof( mbedtls_mpi ) );
262 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000263}
264
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100265static inline mbedtls_mpi_uint mpi_sint_abs( mbedtls_mpi_sint z )
266{
267 if( z >= 0 )
268 return( z );
269 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
270 * A naive -z would have undefined behavior.
271 * Write this in a way that makes popular compilers happy (GCC, Clang,
272 * MSVC). */
273 return( (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z );
274}
275
Paul Bakker5121ce52009-01-03 21:22:43 +0000276/*
277 * Set value from integer
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000280{
Janos Follath24eed8d2019-11-22 13:21:35 +0000281 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000282 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000285 memset( X->p, 0, X->n * ciL );
286
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100287 X->p[0] = mpi_sint_abs( z );
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 X->s = ( z < 0 ) ? -1 : 1;
289
290cleanup:
291
292 return( ret );
293}
294
295/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000296 * Get a specific bit
297 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000299{
Hanno Becker73d7d792018-12-11 10:35:51 +0000300 MPI_VALIDATE_RET( X != NULL );
301
Paul Bakker2f5947e2011-05-18 15:47:11 +0000302 if( X->n * biL <= pos )
303 return( 0 );
304
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200305 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000306}
307
Gilles Peskine11cdb052018-11-20 16:47:47 +0100308/* Get a specific byte, without range checks. */
309#define GET_BYTE( X, i ) \
310 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
311
Paul Bakker2f5947e2011-05-18 15:47:11 +0000312/*
313 * Set a bit to a specific value of 0 or 1
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000316{
317 int ret = 0;
318 size_t off = pos / biL;
319 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000320 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000321
322 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200324
Paul Bakker2f5947e2011-05-18 15:47:11 +0000325 if( X->n * biL <= pos )
326 {
327 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200328 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200330 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000331 }
332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
334 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335
336cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 return( ret );
339}
340
341/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200342 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000343 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000345{
Paul Bakker23986e52011-04-24 08:57:21 +0000346 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000347 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000348
349 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000350 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000351 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
352 return( count );
353
354 return( 0 );
355}
356
357/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000358 * Count leading zero bits in a given integer
359 */
360static size_t mbedtls_clz( const mbedtls_mpi_uint x )
361{
362 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100363 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000364
365 for( j = 0; j < biL; j++ )
366 {
367 if( x & mask ) break;
368
369 mask >>= 1;
370 }
371
372 return j;
373}
374
375/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200376 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000377 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000379{
Paul Bakker23986e52011-04-24 08:57:21 +0000380 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000381
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200382 if( X->n == 0 )
383 return( 0 );
384
Paul Bakker5121ce52009-01-03 21:22:43 +0000385 for( i = X->n - 1; i > 0; i-- )
386 if( X->p[i] != 0 )
387 break;
388
Simon Butcher15b15d12015-11-26 19:35:03 +0000389 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000390
Paul Bakker23986e52011-04-24 08:57:21 +0000391 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000392}
393
394/*
395 * Return the total size in bytes
396 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000398{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200399 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000400}
401
402/*
403 * Convert an ASCII character to digit value
404 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000406{
407 *d = 255;
408
409 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
410 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
411 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 if( *d >= (mbedtls_mpi_uint) radix )
414 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000415
416 return( 0 );
417}
418
419/*
420 * Import from an ASCII string
421 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000423{
Janos Follath24eed8d2019-11-22 13:21:35 +0000424 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000425 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200426 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 mbedtls_mpi_uint d;
428 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000429 MPI_VALIDATE_RET( X != NULL );
430 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000431
432 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000433 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000434
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436
Gilles Peskined4876132021-06-08 18:32:34 +0200437 if( s[0] == 0 )
438 {
439 mbedtls_mpi_free( X );
440 return( 0 );
441 }
442
Gilles Peskine80f56732021-04-03 18:26:13 +0200443 if( s[0] == '-' )
444 {
445 ++s;
446 sign = -1;
447 }
448
Paul Bakkerff60ee62010-03-16 21:09:09 +0000449 slen = strlen( s );
450
Paul Bakker5121ce52009-01-03 21:22:43 +0000451 if( radix == 16 )
452 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100453 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200454 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
455
Paul Bakkerff60ee62010-03-16 21:09:09 +0000456 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
459 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
Paul Bakker23986e52011-04-24 08:57:21 +0000461 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000462 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200464 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000465 }
466 }
467 else
468 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470
Paul Bakkerff60ee62010-03-16 21:09:09 +0000471 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000472 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
474 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200475 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000476 }
477 }
478
Gilles Peskine80f56732021-04-03 18:26:13 +0200479 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
480 X->s = -1;
481
Paul Bakker5121ce52009-01-03 21:22:43 +0000482cleanup:
483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
486 return( ret );
487}
488
489/*
Ron Eldora16fa292018-11-20 14:07:01 +0200490 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000491 */
Ron Eldora16fa292018-11-20 14:07:01 +0200492static int mpi_write_hlp( mbedtls_mpi *X, int radix,
493 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000494{
Janos Follath24eed8d2019-11-22 13:21:35 +0000495 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200497 size_t length = 0;
498 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Ron Eldora16fa292018-11-20 14:07:01 +0200500 do
501 {
502 if( length >= buflen )
503 {
504 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
505 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000506
Ron Eldora16fa292018-11-20 14:07:01 +0200507 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
508 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
509 /*
510 * Write the residue in the current position, as an ASCII character.
511 */
512 if( r < 0xA )
513 *(--p_end) = (char)( '0' + r );
514 else
515 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000516
Ron Eldora16fa292018-11-20 14:07:01 +0200517 length++;
518 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
Ron Eldora16fa292018-11-20 14:07:01 +0200520 memmove( *p, p_end, length );
521 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
523cleanup:
524
525 return( ret );
526}
527
528/*
529 * Export into an ASCII string
530 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100531int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
532 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000533{
Paul Bakker23986e52011-04-24 08:57:21 +0000534 int ret = 0;
535 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000538 MPI_VALIDATE_RET( X != NULL );
539 MPI_VALIDATE_RET( olen != NULL );
540 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000541
542 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000543 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000544
Hanno Becker23cfea02019-02-04 09:45:07 +0000545 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
546 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
547 * `n`. If radix > 4, this might be a strict
548 * overapproximation of the number of
549 * radix-adic digits needed to present `n`. */
550 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
551 * present `n`. */
552
Janos Follath80470622019-03-06 13:43:02 +0000553 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000554 n += 1; /* Compensate for the divisions above, which round down `n`
555 * in case it's not even. */
556 n += 1; /* Potential '-'-sign. */
557 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
558 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100560 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000561 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100562 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 }
565
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100566 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000568
569 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000570 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000572 buflen--;
573 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000574
575 if( radix == 16 )
576 {
Paul Bakker23986e52011-04-24 08:57:21 +0000577 int c;
578 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000579
Paul Bakker23986e52011-04-24 08:57:21 +0000580 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 {
Paul Bakker23986e52011-04-24 08:57:21 +0000582 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000583 {
Paul Bakker23986e52011-04-24 08:57:21 +0000584 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000585
Paul Bakker6c343d72014-07-10 14:36:19 +0200586 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 continue;
588
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000589 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000590 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000591 k = 1;
592 }
593 }
594 }
595 else
596 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000598
599 if( T.s == -1 )
600 T.s = 1;
601
Ron Eldora16fa292018-11-20 14:07:01 +0200602 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 }
604
605 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100606 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000607
608cleanup:
609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200610 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
612 return( ret );
613}
614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000616/*
617 * Read X from an opened file
618 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000620{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000622 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000624 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000625 * Buffer should have space for (short) label and decimal formatted MPI,
626 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000629
Hanno Becker73d7d792018-12-11 10:35:51 +0000630 MPI_VALIDATE_RET( X != NULL );
631 MPI_VALIDATE_RET( fin != NULL );
632
633 if( radix < 2 || radix > 16 )
634 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
635
Paul Bakker5121ce52009-01-03 21:22:43 +0000636 memset( s, 0, sizeof( s ) );
637 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000641 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000643
Hanno Beckerb2034b72017-04-26 11:46:46 +0100644 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
645 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100648 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000649 if( mpi_get_digit( &d, radix, *p ) != 0 )
650 break;
651
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653}
654
655/*
656 * Write X into an opened file (or stdout if fout == NULL)
657 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000659{
Janos Follath24eed8d2019-11-22 13:21:35 +0000660 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000661 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000662 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000663 * Buffer should have space for (short) label and decimal formatted MPI,
664 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000665 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000667 MPI_VALIDATE_RET( X != NULL );
668
669 if( radix < 2 || radix > 16 )
670 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100672 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100674 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000675
676 if( p == NULL ) p = "";
677
678 plen = strlen( p );
679 slen = strlen( s );
680 s[slen++] = '\r';
681 s[slen++] = '\n';
682
683 if( fout != NULL )
684 {
685 if( fwrite( p, 1, plen, fout ) != plen ||
686 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000688 }
689 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692cleanup:
693
694 return( ret );
695}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
Hanno Beckerda1655a2017-10-18 14:21:44 +0100698
699/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
700 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000701
702static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
703{
704 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100705 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000706 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100707
708 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
709 {
710 tmp <<= CHAR_BIT;
711 tmp |= (mbedtls_mpi_uint) *x_ptr;
712 }
713
Hanno Beckerf8720072018-11-08 11:53:49 +0000714 return( tmp );
715}
716
717static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
718{
719#if defined(__BYTE_ORDER__)
720
721/* Nothing to do on bigendian systems. */
722#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
723 return( x );
724#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
725
726#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
727
728/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000729#if defined(__GNUC__) && defined(__GNUC_PREREQ)
730#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000731#define have_bswap
732#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000733#endif
734
735#if defined(__clang__) && defined(__has_builtin)
736#if __has_builtin(__builtin_bswap32) && \
737 __has_builtin(__builtin_bswap64)
738#define have_bswap
739#endif
740#endif
741
Hanno Beckerf8720072018-11-08 11:53:49 +0000742#if defined(have_bswap)
743 /* The compiler is hopefully able to statically evaluate this! */
744 switch( sizeof(mbedtls_mpi_uint) )
745 {
746 case 4:
747 return( __builtin_bswap32(x) );
748 case 8:
749 return( __builtin_bswap64(x) );
750 }
751#endif
752#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
753#endif /* __BYTE_ORDER__ */
754
755 /* Fall back to C-based reordering if we don't know the byte order
756 * or we couldn't use a compiler-specific builtin. */
757 return( mpi_uint_bigendian_to_host_c( x ) );
758}
759
Hanno Becker2be8a552018-10-25 12:40:09 +0100760static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100761{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100762 mbedtls_mpi_uint *cur_limb_left;
763 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100764 if( limbs == 0 )
765 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100766
767 /*
768 * Traverse limbs and
769 * - adapt byte-order in each limb
770 * - swap the limbs themselves.
771 * For that, simultaneously traverse the limbs from left to right
772 * and from right to left, as long as the left index is not bigger
773 * than the right index (it's not a problem if limbs is odd and the
774 * indices coincide in the last iteration).
775 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100776 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
777 cur_limb_left <= cur_limb_right;
778 cur_limb_left++, cur_limb_right-- )
779 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000780 mbedtls_mpi_uint tmp;
781 /* Note that if cur_limb_left == cur_limb_right,
782 * this code effectively swaps the bytes only once. */
783 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
784 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
785 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100786 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100787}
788
Paul Bakker5121ce52009-01-03 21:22:43 +0000789/*
Janos Follatha778a942019-02-13 10:28:28 +0000790 * Import X from unsigned binary data, little endian
791 */
792int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
793 const unsigned char *buf, size_t buflen )
794{
Janos Follath24eed8d2019-11-22 13:21:35 +0000795 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000796 size_t i;
797 size_t const limbs = CHARS_TO_LIMBS( buflen );
798
799 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200800 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000801
802 for( i = 0; i < buflen; i++ )
803 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
804
805cleanup:
806
Janos Follath171a7ef2019-02-15 16:17:45 +0000807 /*
808 * This function is also used to import keys. However, wiping the buffers
809 * upon failure is not necessary because failure only can happen before any
810 * input is copied.
811 */
Janos Follatha778a942019-02-13 10:28:28 +0000812 return( ret );
813}
814
815/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000816 * Import X from unsigned binary data, big endian
817 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200818int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000819{
Janos Follath24eed8d2019-11-22 13:21:35 +0000820 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100821 size_t const limbs = CHARS_TO_LIMBS( buflen );
822 size_t const overhead = ( limbs * ciL ) - buflen;
823 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000824
Hanno Becker8ce11a32018-12-19 16:18:52 +0000825 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000826 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
827
Hanno Becker073c1992017-10-17 15:17:27 +0100828 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200829 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000830
Gilles Peskine3130ce22021-06-02 22:17:52 +0200831 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000832 * even if buflen is 0. */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200833 if( buflen != 0 )
Hanno Becker0e810b92019-01-03 17:13:11 +0000834 {
835 Xp = (unsigned char*) X->p;
836 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100837
Hanno Becker0e810b92019-01-03 17:13:11 +0000838 mpi_bigendian_to_host( X->p, limbs );
839 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000840
841cleanup:
842
Janos Follath171a7ef2019-02-15 16:17:45 +0000843 /*
844 * This function is also used to import keys. However, wiping the buffers
845 * upon failure is not necessary because failure only can happen before any
846 * input is copied.
847 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000848 return( ret );
849}
850
851/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000852 * Export X into unsigned binary data, little endian
853 */
854int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
855 unsigned char *buf, size_t buflen )
856{
857 size_t stored_bytes = X->n * ciL;
858 size_t bytes_to_copy;
859 size_t i;
860
861 if( stored_bytes < buflen )
862 {
863 bytes_to_copy = stored_bytes;
864 }
865 else
866 {
867 bytes_to_copy = buflen;
868
869 /* The output buffer is smaller than the allocated size of X.
870 * However X may fit if its leading bytes are zero. */
871 for( i = bytes_to_copy; i < stored_bytes; i++ )
872 {
873 if( GET_BYTE( X, i ) != 0 )
874 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
875 }
876 }
877
878 for( i = 0; i < bytes_to_copy; i++ )
879 buf[i] = GET_BYTE( X, i );
880
881 if( stored_bytes < buflen )
882 {
883 /* Write trailing 0 bytes */
884 memset( buf + stored_bytes, 0, buflen - stored_bytes );
885 }
886
887 return( 0 );
888}
889
890/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000891 * Export X into unsigned binary data, big endian
892 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100893int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
894 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000895{
Hanno Becker73d7d792018-12-11 10:35:51 +0000896 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100897 size_t bytes_to_copy;
898 unsigned char *p;
899 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000900
Hanno Becker73d7d792018-12-11 10:35:51 +0000901 MPI_VALIDATE_RET( X != NULL );
902 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
903
904 stored_bytes = X->n * ciL;
905
Gilles Peskine11cdb052018-11-20 16:47:47 +0100906 if( stored_bytes < buflen )
907 {
908 /* There is enough space in the output buffer. Write initial
909 * null bytes and record the position at which to start
910 * writing the significant bytes. In this case, the execution
911 * trace of this function does not depend on the value of the
912 * number. */
913 bytes_to_copy = stored_bytes;
914 p = buf + buflen - stored_bytes;
915 memset( buf, 0, buflen - stored_bytes );
916 }
917 else
918 {
919 /* The output buffer is smaller than the allocated size of X.
920 * However X may fit if its leading bytes are zero. */
921 bytes_to_copy = buflen;
922 p = buf;
923 for( i = bytes_to_copy; i < stored_bytes; i++ )
924 {
925 if( GET_BYTE( X, i ) != 0 )
926 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
927 }
928 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
Gilles Peskine11cdb052018-11-20 16:47:47 +0100930 for( i = 0; i < bytes_to_copy; i++ )
931 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000932
933 return( 0 );
934}
935
936/*
937 * Left-shift: X <<= count
938 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000940{
Janos Follath24eed8d2019-11-22 13:21:35 +0000941 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000942 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000944 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000945
946 v0 = count / (biL );
947 t1 = count & (biL - 1);
948
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200949 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000950
Paul Bakkerf9688572011-05-05 10:00:45 +0000951 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000953
954 ret = 0;
955
956 /*
957 * shift by count / limb_size
958 */
959 if( v0 > 0 )
960 {
Paul Bakker23986e52011-04-24 08:57:21 +0000961 for( i = X->n; i > v0; i-- )
962 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000963
Paul Bakker23986e52011-04-24 08:57:21 +0000964 for( ; i > 0; i-- )
965 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000966 }
967
968 /*
969 * shift by count % limb_size
970 */
971 if( t1 > 0 )
972 {
973 for( i = v0; i < X->n; i++ )
974 {
975 r1 = X->p[i] >> (biL - t1);
976 X->p[i] <<= t1;
977 X->p[i] |= r0;
978 r0 = r1;
979 }
980 }
981
982cleanup:
983
984 return( ret );
985}
986
987/*
988 * Right-shift: X >>= count
989 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000991{
Paul Bakker23986e52011-04-24 08:57:21 +0000992 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200993 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000994 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000995
996 v0 = count / biL;
997 v1 = count & (biL - 1);
998
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100999 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001000 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001001
Paul Bakker5121ce52009-01-03 21:22:43 +00001002 /*
1003 * shift by count / limb_size
1004 */
1005 if( v0 > 0 )
1006 {
1007 for( i = 0; i < X->n - v0; i++ )
1008 X->p[i] = X->p[i + v0];
1009
1010 for( ; i < X->n; i++ )
1011 X->p[i] = 0;
1012 }
1013
1014 /*
1015 * shift by count % limb_size
1016 */
1017 if( v1 > 0 )
1018 {
Paul Bakker23986e52011-04-24 08:57:21 +00001019 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 {
Paul Bakker23986e52011-04-24 08:57:21 +00001021 r1 = X->p[i - 1] << (biL - v1);
1022 X->p[i - 1] >>= v1;
1023 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001024 r0 = r1;
1025 }
1026 }
1027
1028 return( 0 );
1029}
1030
1031/*
1032 * Compare unsigned values
1033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001035{
Paul Bakker23986e52011-04-24 08:57:21 +00001036 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001037 MPI_VALIDATE_RET( X != NULL );
1038 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001039
Paul Bakker23986e52011-04-24 08:57:21 +00001040 for( i = X->n; i > 0; i-- )
1041 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001042 break;
1043
Paul Bakker23986e52011-04-24 08:57:21 +00001044 for( j = Y->n; j > 0; j-- )
1045 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001046 break;
1047
Paul Bakker23986e52011-04-24 08:57:21 +00001048 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001049 return( 0 );
1050
1051 if( i > j ) return( 1 );
1052 if( j > i ) return( -1 );
1053
Paul Bakker23986e52011-04-24 08:57:21 +00001054 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 {
Paul Bakker23986e52011-04-24 08:57:21 +00001056 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1057 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 }
1059
1060 return( 0 );
1061}
1062
1063/*
1064 * Compare signed values
1065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001067{
Paul Bakker23986e52011-04-24 08:57:21 +00001068 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001069 MPI_VALIDATE_RET( X != NULL );
1070 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001071
Paul Bakker23986e52011-04-24 08:57:21 +00001072 for( i = X->n; i > 0; i-- )
1073 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001074 break;
1075
Paul Bakker23986e52011-04-24 08:57:21 +00001076 for( j = Y->n; j > 0; j-- )
1077 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001078 break;
1079
Paul Bakker23986e52011-04-24 08:57:21 +00001080 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 return( 0 );
1082
1083 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001084 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001085
1086 if( X->s > 0 && Y->s < 0 ) return( 1 );
1087 if( Y->s > 0 && X->s < 0 ) return( -1 );
1088
Paul Bakker23986e52011-04-24 08:57:21 +00001089 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001090 {
Paul Bakker23986e52011-04-24 08:57:21 +00001091 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1092 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 }
1094
1095 return( 0 );
1096}
1097
Janos Follathee6abce2019-09-05 14:47:19 +01001098/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001099 * Compare signed values
1100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001101int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001102{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 mbedtls_mpi Y;
1104 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001105 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001106
Gilles Peskineae7cbd72022-11-15 23:25:27 +01001107 *p = mpi_sint_abs( z );
Paul Bakker5121ce52009-01-03 21:22:43 +00001108 Y.s = ( z < 0 ) ? -1 : 1;
1109 Y.n = 1;
1110 Y.p = p;
1111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001112 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001113}
1114
1115/*
1116 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001118int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001119{
Janos Follath24eed8d2019-11-22 13:21:35 +00001120 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001121 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001122 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001123 MPI_VALIDATE_RET( X != NULL );
1124 MPI_VALIDATE_RET( A != NULL );
1125 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
1127 if( X == B )
1128 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 }
1131
1132 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001134
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001135 /*
1136 * X should always be positive as a result of unsigned additions.
1137 */
1138 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001139
Paul Bakker23986e52011-04-24 08:57:21 +00001140 for( j = B->n; j > 0; j-- )
1141 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001142 break;
1143
Gilles Peskine103cf592022-11-15 22:59:00 +01001144 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1145 * and B is 0 (of any size). */
1146 if( j == 0 )
1147 return( 0 );
1148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
1151 o = B->p; p = X->p; c = 0;
1152
Janos Follath6c922682015-10-30 17:43:11 +01001153 /*
1154 * tmp is used because it might happen that p == o
1155 */
Paul Bakker23986e52011-04-24 08:57:21 +00001156 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001157 {
Janos Follath6c922682015-10-30 17:43:11 +01001158 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001159 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001160 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 }
1162
1163 while( c != 0 )
1164 {
1165 if( i >= X->n )
1166 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 p = X->p + i;
1169 }
1170
Paul Bakker2d319fd2012-09-16 21:34:26 +00001171 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 }
1173
1174cleanup:
1175
1176 return( ret );
1177}
1178
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001179/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001180 * Helper for mbedtls_mpi subtraction.
1181 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001182 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001183 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001184 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001185 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001186 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001187 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001188 * \param n Number of limbs of \p d, \p l and \p r.
1189 * \param[out] d The result of the subtraction.
1190 * \param[in] l The left operand.
1191 * \param[in] r The right operand.
1192 *
1193 * \return 1 if `l < r`.
1194 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001195 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001196static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1197 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001198 const mbedtls_mpi_uint *l,
1199 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001200{
Paul Bakker23986e52011-04-24 08:57:21 +00001201 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001202 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001203
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001204 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001205 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001206 z = ( l[i] < c ); t = l[i] - c;
1207 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001208 }
1209
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001210 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001211}
1212
1213/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001214 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001215 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001217{
Janos Follath24eed8d2019-11-22 13:21:35 +00001218 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001219 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001220 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001221 MPI_VALIDATE_RET( X != NULL );
1222 MPI_VALIDATE_RET( A != NULL );
1223 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001224
Paul Bakker23986e52011-04-24 08:57:21 +00001225 for( n = B->n; n > 0; n-- )
1226 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001227 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001228 if( n > A->n )
1229 {
1230 /* B >= (2^ciL)^n > A */
1231 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1232 goto cleanup;
1233 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001234
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001235 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1236
1237 /* Set the high limbs of X to match A. Don't touch the lower limbs
1238 * because X might be aliased to B, and we must not overwrite the
1239 * significant digits of B. */
1240 if( A->n > n )
1241 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1242 if( X->n > A->n )
1243 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1244
1245 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001246 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001247 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001248 /* Propagate the carry to the first nonzero limb of X. */
1249 for( ; n < X->n && X->p[n] == 0; n++ )
1250 --X->p[n];
1251 /* If we ran out of space for the carry, it means that the result
1252 * is negative. */
1253 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001254 {
1255 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1256 goto cleanup;
1257 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001258 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001259 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001260
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001261 /* X should always be positive as a result of unsigned subtractions. */
1262 X->s = 1;
1263
Paul Bakker5121ce52009-01-03 21:22:43 +00001264cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001265 return( ret );
1266}
1267
1268/*
1269 * Signed addition: X = A + B
1270 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001271int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001272{
Hanno Becker73d7d792018-12-11 10:35:51 +00001273 int ret, s;
1274 MPI_VALIDATE_RET( X != NULL );
1275 MPI_VALIDATE_RET( A != NULL );
1276 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
Hanno Becker73d7d792018-12-11 10:35:51 +00001278 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001279 if( A->s * B->s < 0 )
1280 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001281 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001282 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001284 X->s = s;
1285 }
1286 else
1287 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001288 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001289 X->s = -s;
1290 }
1291 }
1292 else
1293 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001295 X->s = s;
1296 }
1297
1298cleanup:
1299
1300 return( ret );
1301}
1302
1303/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001304 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001305 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001307{
Hanno Becker73d7d792018-12-11 10:35:51 +00001308 int ret, s;
1309 MPI_VALIDATE_RET( X != NULL );
1310 MPI_VALIDATE_RET( A != NULL );
1311 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001312
Hanno Becker73d7d792018-12-11 10:35:51 +00001313 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001314 if( A->s * B->s > 0 )
1315 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001316 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001317 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001318 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001319 X->s = s;
1320 }
1321 else
1322 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001324 X->s = -s;
1325 }
1326 }
1327 else
1328 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 X->s = s;
1331 }
1332
1333cleanup:
1334
1335 return( ret );
1336}
1337
1338/*
1339 * Signed addition: X = A + b
1340 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001342{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001343 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001345 MPI_VALIDATE_RET( X != NULL );
1346 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347
Gilles Peskineae7cbd72022-11-15 23:25:27 +01001348 p[0] = mpi_sint_abs( b );
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001349 B.s = ( b < 0 ) ? -1 : 1;
1350 B.n = 1;
1351 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001352
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001353 return( mbedtls_mpi_add_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001354}
1355
1356/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001357 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001360{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001361 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001363 MPI_VALIDATE_RET( X != NULL );
1364 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001365
Gilles Peskineae7cbd72022-11-15 23:25:27 +01001366 p[0] = mpi_sint_abs( b );
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001367 B.s = ( b < 0 ) ? -1 : 1;
1368 B.n = 1;
1369 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001370
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001371 return( mbedtls_mpi_sub_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001372}
1373
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001374/** Helper for mbedtls_mpi multiplication.
1375 *
1376 * Add \p b * \p s to \p d.
1377 *
1378 * \param i The number of limbs of \p s.
1379 * \param[in] s A bignum to multiply, of size \p i.
1380 * It may overlap with \p d, but only if
1381 * \p d <= \p s.
1382 * Its leading limb must not be \c 0.
1383 * \param[in,out] d The bignum to add to.
1384 * It must be sufficiently large to store the
1385 * result of the multiplication. This means
1386 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1387 * is not known a priori.
1388 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001389 */
1390static
1391#if defined(__APPLE__) && defined(__arm__)
1392/*
1393 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1394 * appears to need this to prevent bad ARM code generation at -O3.
1395 */
1396__attribute__ ((noinline))
1397#endif
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001398void mpi_mul_hlp( size_t i,
1399 const mbedtls_mpi_uint *s,
1400 mbedtls_mpi_uint *d,
1401 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001402{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
1405#if defined(MULADDC_HUIT)
1406 for( ; i >= 8; i -= 8 )
1407 {
1408 MULADDC_INIT
1409 MULADDC_HUIT
1410 MULADDC_STOP
1411 }
1412
1413 for( ; i > 0; i-- )
1414 {
1415 MULADDC_INIT
1416 MULADDC_CORE
1417 MULADDC_STOP
1418 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001419#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001420 for( ; i >= 16; i -= 16 )
1421 {
1422 MULADDC_INIT
1423 MULADDC_CORE MULADDC_CORE
1424 MULADDC_CORE MULADDC_CORE
1425 MULADDC_CORE MULADDC_CORE
1426 MULADDC_CORE MULADDC_CORE
1427
1428 MULADDC_CORE MULADDC_CORE
1429 MULADDC_CORE MULADDC_CORE
1430 MULADDC_CORE MULADDC_CORE
1431 MULADDC_CORE MULADDC_CORE
1432 MULADDC_STOP
1433 }
1434
1435 for( ; i >= 8; i -= 8 )
1436 {
1437 MULADDC_INIT
1438 MULADDC_CORE MULADDC_CORE
1439 MULADDC_CORE MULADDC_CORE
1440
1441 MULADDC_CORE MULADDC_CORE
1442 MULADDC_CORE MULADDC_CORE
1443 MULADDC_STOP
1444 }
1445
1446 for( ; i > 0; i-- )
1447 {
1448 MULADDC_INIT
1449 MULADDC_CORE
1450 MULADDC_STOP
1451 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001452#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001453
1454 t++;
1455
Gilles Peskine8e464c42020-07-24 00:08:38 +02001456 while( c != 0 )
1457 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001458 *d += c; c = ( *d < c ); d++;
1459 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001460}
1461
1462/*
1463 * Baseline multiplication: X = A * B (HAC 14.12)
1464 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001466{
Janos Follath24eed8d2019-11-22 13:21:35 +00001467 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001468 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 mbedtls_mpi TA, TB;
Gilles Peskined65b5002021-06-15 21:44:32 +02001470 int result_is_zero = 0;
Hanno Becker73d7d792018-12-11 10:35:51 +00001471 MPI_VALIDATE_RET( X != NULL );
1472 MPI_VALIDATE_RET( A != NULL );
1473 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1478 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001479
Paul Bakker23986e52011-04-24 08:57:21 +00001480 for( i = A->n; i > 0; i-- )
1481 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 break;
Gilles Peskine38a384d2021-06-17 14:35:25 +02001483 if( i == 0 )
Gilles Peskined65b5002021-06-15 21:44:32 +02001484 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001485
Paul Bakker23986e52011-04-24 08:57:21 +00001486 for( j = B->n; j > 0; j-- )
1487 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001488 break;
Gilles Peskine38a384d2021-06-17 14:35:25 +02001489 if( j == 0 )
Gilles Peskined65b5002021-06-15 21:44:32 +02001490 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1493 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001494
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001495 for( ; j > 0; j-- )
1496 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001497
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001498 /* If the result is 0, we don't shortcut the operation, which reduces
1499 * but does not eliminate side channels leaking the zero-ness. We do
1500 * need to take care to set the sign bit properly since the library does
1501 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskined65b5002021-06-15 21:44:32 +02001502 if( result_is_zero )
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001503 X->s = 1;
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001504 else
1505 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001506
1507cleanup:
1508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
1511 return( ret );
1512}
1513
1514/*
1515 * Baseline multiplication: X = A * b
1516 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518{
Hanno Becker73d7d792018-12-11 10:35:51 +00001519 MPI_VALIDATE_RET( X != NULL );
1520 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001522 /* mpi_mul_hlp can't deal with a leading 0. */
1523 size_t n = A->n;
1524 while( n > 0 && A->p[n - 1] == 0 )
1525 --n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001527 /* The general method below doesn't work if n==0 or b==0. By chance
1528 * calculating the result is trivial in those cases. */
1529 if( b == 0 || n == 0 )
1530 {
Paul Elliott986b55a2021-04-20 21:46:29 +01001531 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001532 }
1533
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001534 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001535 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001536 /* In general, A * b requires 1 limb more than b. If
1537 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1538 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001539 * copy() will take care of the growth if needed. However, experimentally,
1540 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001541 * calls to calloc() in ECP code, presumably because it reuses the
1542 * same mpi for a while and this way the mpi is more likely to directly
1543 * grow to its final size. */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001544 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
1545 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1546 mpi_mul_hlp( n, A->p, X->p, b - 1 );
1547
1548cleanup:
1549 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550}
1551
1552/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001553 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1554 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001555 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001556static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1557 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001558{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001559#if defined(MBEDTLS_HAVE_UDBL)
1560 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001561#else
Simon Butcher9803d072016-01-03 00:24:34 +00001562 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1563 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001564 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1565 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001566 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001567#endif
1568
Simon Butcher15b15d12015-11-26 19:35:03 +00001569 /*
1570 * Check for overflow
1571 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001572 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001573 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001574 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001575
Simon Butcherf5ba0452015-12-27 23:01:55 +00001576 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001577 }
1578
1579#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001580 dividend = (mbedtls_t_udbl) u1 << biL;
1581 dividend |= (mbedtls_t_udbl) u0;
1582 quotient = dividend / d;
1583 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1584 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1585
1586 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001587 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001588
1589 return (mbedtls_mpi_uint) quotient;
1590#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001591
1592 /*
1593 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1594 * Vol. 2 - Seminumerical Algorithms, Knuth
1595 */
1596
1597 /*
1598 * Normalize the divisor, d, and dividend, u0, u1
1599 */
1600 s = mbedtls_clz( d );
1601 d = d << s;
1602
1603 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001604 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001605 u0 = u0 << s;
1606
1607 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001608 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001609
1610 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001611 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001612
1613 /*
1614 * Find the first quotient and remainder
1615 */
1616 q1 = u1 / d1;
1617 r0 = u1 - d1 * q1;
1618
1619 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1620 {
1621 q1 -= 1;
1622 r0 += d1;
1623
1624 if ( r0 >= radix ) break;
1625 }
1626
Simon Butcherf5ba0452015-12-27 23:01:55 +00001627 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001628 q0 = rAX / d1;
1629 r0 = rAX - q0 * d1;
1630
1631 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1632 {
1633 q0 -= 1;
1634 r0 += d1;
1635
1636 if ( r0 >= radix ) break;
1637 }
1638
1639 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001640 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001641
1642 quotient = q1 * radix + q0;
1643
1644 return quotient;
1645#endif
1646}
1647
1648/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001650 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001651int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1652 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001653{
Janos Follath24eed8d2019-11-22 13:21:35 +00001654 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001655 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001656 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001657 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001658 MPI_VALIDATE_RET( A != NULL );
1659 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1662 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001665 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001666 /*
1667 * Avoid dynamic memory allocations for constant-size T2.
1668 *
1669 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1670 * so nobody increase the size of the MPI and we're safe to use an on-stack
1671 * buffer.
1672 */
Alexander K35d6d462019-10-31 14:46:45 +03001673 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001674 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1675 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1680 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681 return( 0 );
1682 }
1683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1685 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 X.s = Y.s = 1;
1687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001690 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001692 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001693 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001694 {
1695 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1697 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 }
1699 else k = 0;
1700
1701 n = X.n - 1;
1702 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001703 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001706 {
1707 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001709 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001710 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001711
1712 for( i = n; i > t ; i-- )
1713 {
1714 if( X.p[i] >= Y.p[t] )
1715 Z.p[i - t - 1] = ~0;
1716 else
1717 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001718 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1719 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 }
1721
Alexander K35d6d462019-10-31 14:46:45 +03001722 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1723 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1724 T2.p[2] = X.p[i];
1725
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 Z.p[i - t - 1]++;
1727 do
1728 {
1729 Z.p[i - t - 1]--;
1730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001731 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001732 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001735 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1739 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1740 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001741
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001742 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001743 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001744 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1745 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1746 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001747 Z.p[i - t - 1]--;
1748 }
1749 }
1750
1751 if( Q != NULL )
1752 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754 Q->s = A->s * B->s;
1755 }
1756
1757 if( R != NULL )
1758 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001760 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001764 R->s = 1;
1765 }
1766
1767cleanup:
1768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001769 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001770 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001771 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001772
1773 return( ret );
1774}
1775
1776/*
1777 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001779int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1780 const mbedtls_mpi *A,
1781 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001782{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001783 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001784 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001785 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001786
Gilles Peskineae7cbd72022-11-15 23:25:27 +01001787 p[0] = mpi_sint_abs( b );
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001788 B.s = ( b < 0 ) ? -1 : 1;
1789 B.n = 1;
1790 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001791
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001792 return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793}
1794
1795/*
1796 * Modulo: R = A mod B
1797 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001798int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001799{
Janos Follath24eed8d2019-11-22 13:21:35 +00001800 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001801 MPI_VALIDATE_RET( R != NULL );
1802 MPI_VALIDATE_RET( A != NULL );
1803 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1806 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1811 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1814 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
1816cleanup:
1817
1818 return( ret );
1819}
1820
1821/*
1822 * Modulo: r = A mod b
1823 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001825{
Paul Bakker23986e52011-04-24 08:57:21 +00001826 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001828 MPI_VALIDATE_RET( r != NULL );
1829 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001830
1831 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
1834 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
1837 /*
1838 * handle trivial cases
1839 */
Gilles Peskinec9529f92022-06-09 19:32:46 +02001840 if( b == 1 || A->n == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 {
1842 *r = 0;
1843 return( 0 );
1844 }
1845
1846 if( b == 2 )
1847 {
1848 *r = A->p[0] & 1;
1849 return( 0 );
1850 }
1851
1852 /*
1853 * general case
1854 */
Paul Bakker23986e52011-04-24 08:57:21 +00001855 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001856 {
Paul Bakker23986e52011-04-24 08:57:21 +00001857 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 y = ( y << biH ) | ( x >> biH );
1859 z = y / b;
1860 y -= z * b;
1861
1862 x <<= biH;
1863 y = ( y << biH ) | ( x >> biH );
1864 z = y / b;
1865 y -= z * b;
1866 }
1867
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001868 /*
1869 * If A is negative, then the current y represents a negative value.
1870 * Flipping it to the positive side.
1871 */
1872 if( A->s < 0 && y != 0 )
1873 y = b - y;
1874
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 *r = y;
1876
1877 return( 0 );
1878}
1879
1880/*
1881 * Fast Montgomery initialization (thanks to Tom St Denis)
1882 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001884{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001886 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
1888 x = m0;
1889 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001891 for( i = biL; i >= 8; i /= 2 )
1892 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
1894 *mm = ~x + 1;
1895}
1896
Gilles Peskine2a82f722020-06-04 15:00:49 +02001897/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1898 *
1899 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02001900 * It must have at least as many limbs as N
1901 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02001902 * On successful completion, A contains the result of
1903 * the multiplication A * B * R^-1 mod N where
1904 * R = (2^ciL)^n.
1905 * \param[in] B One of the numbers to multiply.
1906 * It must be nonzero and must not have more limbs than N
1907 * (B->n <= N->n).
1908 * \param[in] N The modulo. N must be odd.
1909 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1910 * This is -N^-1 mod 2^ciL.
1911 * \param[in,out] T A bignum for temporary storage.
1912 * It must be at least twice the limb size of N plus 2
1913 * (T->n >= 2 * (N->n + 1)).
1914 * Its initial content is unused and
1915 * its final content is indeterminate.
1916 * Note that unlike the usual convention in the library
1917 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001918 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001919static 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 +02001920 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001921{
Paul Bakker23986e52011-04-24 08:57:21 +00001922 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
1925 memset( T->p, 0, T->n * ciL );
1926
1927 d = T->p;
1928 n = N->n;
1929 m = ( B->n < n ) ? B->n : n;
1930
1931 for( i = 0; i < n; i++ )
1932 {
1933 /*
1934 * T = (T + u0*B + u1*N) / 2^biL
1935 */
1936 u0 = A->p[i];
1937 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1938
1939 mpi_mul_hlp( m, B->p, d, u0 );
1940 mpi_mul_hlp( n, N->p, d, u1 );
1941
1942 *d++ = u0; d[n + 1] = 0;
1943 }
1944
Gilles Peskine221626f2020-06-08 22:37:50 +02001945 /* At this point, d is either the desired result or the desired result
1946 * plus N. We now potentially subtract N, avoiding leaking whether the
1947 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
Gilles Peskine221626f2020-06-08 22:37:50 +02001949 /* Copy the n least significant limbs of d to A, so that
1950 * A = d if d < N (recall that N has n limbs). */
1951 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001952 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02001953 * do the calculation without using conditional tests. */
1954 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02001955 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001956 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02001957 /* If d0 < N then d < (2^biL)^n
1958 * so d[n] == 0 and we want to keep A as it is.
1959 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1960 * so d[n] == 1 and we want to set A to the result of the subtraction
1961 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1962 * This exactly corresponds to a conditional assignment. */
Gabor Mezei18a44942021-10-20 11:59:27 +02001963 mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964}
1965
1966/*
1967 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001968 *
1969 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001970 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001971static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1972 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001973{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 mbedtls_mpi_uint z = 1;
1975 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
Paul Bakker8ddb6452013-02-27 14:56:33 +01001977 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 U.p = &z;
1979
Gilles Peskine4e91d472020-06-04 20:55:15 +02001980 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001981}
1982
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01001983/**
1984 * Select an MPI from a table without leaking the index.
1985 *
1986 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1987 * reads the entire table in order to avoid leaking the value of idx to an
1988 * attacker able to observe memory access patterns.
1989 *
1990 * \param[out] R Where to write the selected MPI.
1991 * \param[in] T The table to read from.
1992 * \param[in] T_size The number of elements in the table.
1993 * \param[in] idx The index of the element to select;
1994 * this must satisfy 0 <= idx < T_size.
1995 *
1996 * \return \c 0 on success, or a negative error code.
1997 */
1998static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
1999{
2000 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2001
2002 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002003 {
2004 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
Gabor Mezei18a44942021-10-20 11:59:27 +02002005 (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002006 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002007
2008cleanup:
2009 return( ret );
2010}
2011
Paul Bakker5121ce52009-01-03 21:22:43 +00002012/*
2013 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2014 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002015int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2016 const mbedtls_mpi *E, const mbedtls_mpi *N,
Yuto Takano284857e2021-07-14 10:20:09 +01002017 mbedtls_mpi *prec_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002018{
Janos Follath24eed8d2019-11-22 13:21:35 +00002019 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002020 size_t wbits, wsize, one = 1;
2021 size_t i, j, nblimbs;
2022 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002024 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002025 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
Hanno Becker73d7d792018-12-11 10:35:51 +00002027 MPI_VALIDATE_RET( X != NULL );
2028 MPI_VALIDATE_RET( A != NULL );
2029 MPI_VALIDATE_RET( E != NULL );
2030 MPI_VALIDATE_RET( N != NULL );
2031
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002032 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2036 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002037
Chris Jones9246d042020-11-25 15:12:39 +00002038 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2039 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2040 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2041
Paul Bakkerf6198c12012-05-16 08:02:29 +00002042 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002043 * Init temps and window size
2044 */
2045 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2047 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002048 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 memset( W, 0, sizeof( W ) );
2050
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002051 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
2053 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2054 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2055
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002056#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2058 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002059#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002060
Paul Bakker5121ce52009-01-03 21:22:43 +00002061 j = N->n + 1;
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002062 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2063 * and mpi_montred() calls later. Here we ensure that W[1] and X are
2064 * large enough, and later we'll grow other W[i] to the same length.
2065 * They must not be shrunk midway through this function!
2066 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2068 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2069 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
2071 /*
Paul Bakker50546922012-05-19 08:40:49 +00002072 * Compensate for negative A (and correct at the end)
2073 */
2074 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002075 if( neg )
2076 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002078 Apos.s = 1;
2079 A = &Apos;
2080 }
2081
2082 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 * If 1st call, pre-compute R^2 mod N
2084 */
Yuto Takano284857e2021-07-14 10:20:09 +01002085 if( prec_RR == NULL || prec_RR->p == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00002086 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2088 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2089 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002090
Yuto Takano284857e2021-07-14 10:20:09 +01002091 if( prec_RR != NULL )
2092 memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002093 }
2094 else
Yuto Takano284857e2021-07-14 10:20:09 +01002095 memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
2097 /*
2098 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2099 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002101 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002103 /* This should be a no-op because W[1] is already that large before
2104 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2105 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine0759cad2021-06-15 21:22:48 +02002106 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002107 }
Paul Bakkerc2024f42014-01-23 20:38:35 +01002108 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002111 /* Note that this is safe because W[1] always has at least N->n limbs
2112 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002113 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
2115 /*
2116 * X = R^2 * R^-1 mod N = R mod N
2117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002119 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
2121 if( wsize > 1 )
2122 {
2123 /*
2124 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2125 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002126 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002128 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2129 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002130
2131 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002132 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002133
Paul Bakker5121ce52009-01-03 21:22:43 +00002134 /*
2135 * W[i] = W[i - 1] * W[1]
2136 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002137 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002138 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2140 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Gilles Peskine4e91d472020-06-04 20:55:15 +02002142 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143 }
2144 }
2145
2146 nblimbs = E->n;
2147 bufsize = 0;
2148 nbits = 0;
2149 wbits = 0;
2150 state = 0;
2151
2152 while( 1 )
2153 {
2154 if( bufsize == 0 )
2155 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002156 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002157 break;
2158
Paul Bakker0d7702c2013-10-29 16:18:35 +01002159 nblimbs--;
2160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002162 }
2163
2164 bufsize--;
2165
2166 ei = (E->p[nblimbs] >> bufsize) & 1;
2167
2168 /*
2169 * skip leading 0s
2170 */
2171 if( ei == 0 && state == 0 )
2172 continue;
2173
2174 if( ei == 0 && state == 1 )
2175 {
2176 /*
2177 * out of window, square X
2178 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002179 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 continue;
2181 }
2182
2183 /*
2184 * add ei to current window
2185 */
2186 state = 2;
2187
2188 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002189 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
2191 if( nbits == wsize )
2192 {
2193 /*
2194 * X = X^wsize R^-1 mod N
2195 */
2196 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002197 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002198
2199 /*
2200 * X = X * W[wbits] R^-1 mod N
2201 */
Manuel Pégourié-Gonnard0b3bde52021-06-10 09:34:00 +02002202 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002203 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
2205 state--;
2206 nbits = 0;
2207 wbits = 0;
2208 }
2209 }
2210
2211 /*
2212 * process the remaining bits
2213 */
2214 for( i = 0; i < nbits; i++ )
2215 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002216 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
2218 wbits <<= 1;
2219
Paul Bakker66d5d072014-06-17 16:39:18 +02002220 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002221 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002222 }
2223
2224 /*
2225 * X = A^E * R * R^-1 mod N = A^E mod N
2226 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002227 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002228
Hanno Beckera4af1c42017-04-18 09:07:45 +01002229 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002230 {
2231 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002233 }
2234
Paul Bakker5121ce52009-01-03 21:22:43 +00002235cleanup:
2236
Paul Bakker66d5d072014-06-17 16:39:18 +02002237 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002241 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002242
Yuto Takano284857e2021-07-14 10:20:09 +01002243 if( prec_RR == NULL || prec_RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002245
2246 return( ret );
2247}
2248
Paul Bakker5121ce52009-01-03 21:22:43 +00002249/*
2250 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2251 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002253{
Janos Follath24eed8d2019-11-22 13:21:35 +00002254 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002255 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002256 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002257
Hanno Becker73d7d792018-12-11 10:35:51 +00002258 MPI_VALIDATE_RET( G != NULL );
2259 MPI_VALIDATE_RET( A != NULL );
2260 MPI_VALIDATE_RET( B != NULL );
2261
Alexander Ke8ad49f2019-08-16 16:16:07 +03002262 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2265 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 lz = mbedtls_mpi_lsb( &TA );
2268 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002269
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002270 /* The loop below gives the correct result when A==0 but not when B==0.
2271 * So have a special case for B==0. Leverage the fact that we just
2272 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2273 * slightly more efficient than cmp_int(). */
2274 if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2275 {
2276 ret = mbedtls_mpi_copy( G, A );
2277 goto cleanup;
2278 }
2279
Paul Bakker66d5d072014-06-17 16:39:18 +02002280 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002281 lz = lzt;
2282
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 TA.s = TB.s = 1;
2284
Gilles Peskineea9aa142021-06-16 13:42:04 +02002285 /* We mostly follow the procedure described in HAC 14.54, but with some
2286 * minor differences:
2287 * - Sequences of multiplications or divisions by 2 are grouped into a
2288 * single shift operation.
Gilles Peskine37d690c2021-06-21 18:58:39 +02002289 * - The procedure in HAC assumes that 0 < TB <= TA.
2290 * - The condition TB <= TA is not actually necessary for correctness.
2291 * TA and TB have symmetric roles except for the loop termination
2292 * condition, and the shifts at the beginning of the loop body
2293 * remove any significance from the ordering of TA vs TB before
2294 * the shifts.
2295 * - If TA = 0, the loop goes through 0 iterations and the result is
2296 * correctly TB.
2297 * - The case TB = 0 was short-circuited above.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002298 *
2299 * For the correctness proof below, decompose the original values of
2300 * A and B as
2301 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2302 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2303 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2304 * and gcd(A',B') is odd or 0.
2305 *
2306 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2307 * The code maintains the following invariant:
2308 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine6537bdb2021-06-15 22:09:39 +02002309 */
2310
Gilles Peskineea9aa142021-06-16 13:42:04 +02002311 /* Proof that the loop terminates:
2312 * At each iteration, either the right-shift by 1 is made on a nonzero
2313 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2314 * by at least 1, or the right-shift by 1 is made on zero and then
2315 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2316 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2317 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 {
Gilles Peskineea9aa142021-06-16 13:42:04 +02002320 /* Divisions by 2 preserve the invariant (I). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2322 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002323
Gilles Peskineea9aa142021-06-16 13:42:04 +02002324 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2325 * TA-TB is even so the division by 2 has an integer result.
2326 * Invariant (I) is preserved since any odd divisor of both TA and TB
2327 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case0e7791f2021-12-20 21:14:10 -08002328 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskineea9aa142021-06-16 13:42:04 +02002329 * divides TA.
2330 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2334 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335 }
2336 else
2337 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2339 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340 }
Gilles Peskineea9aa142021-06-16 13:42:04 +02002341 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002342 }
2343
Gilles Peskineea9aa142021-06-16 13:42:04 +02002344 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2345 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2346 * - If there was at least one loop iteration, then one of TA or TB is odd,
2347 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2348 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2349 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskineb798b352021-06-21 11:40:38 +02002350 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002351 */
2352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2354 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
2356cleanup:
2357
Alexander Ke8ad49f2019-08-16 16:16:07 +03002358 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002359
2360 return( ret );
2361}
2362
Gilles Peskine8f454702021-04-01 15:57:18 +02002363/* Fill X with n_bytes random bytes.
2364 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002365 * The ordering of the bytes returned from the RNG is suitable for
2366 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002367 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002368 * n_bytes must not be 0.
2369 */
2370static int mpi_fill_random_internal(
2371 mbedtls_mpi *X, size_t n_bytes,
2372 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2373{
2374 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2375 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2376 const size_t overhead = ( limbs * ciL ) - n_bytes;
2377
2378 if( X->n < limbs )
2379 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine8f454702021-04-01 15:57:18 +02002380
Gilles Peskinea16001e2021-04-13 21:55:35 +02002381 memset( X->p, 0, overhead );
2382 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine8f454702021-04-01 15:57:18 +02002383 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2384 mpi_bigendian_to_host( X->p, limbs );
2385
2386cleanup:
2387 return( ret );
2388}
2389
Paul Bakker33dc46b2014-04-30 16:11:39 +02002390/*
2391 * Fill X with size bytes of random.
2392 *
2393 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002394 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002395 * deterministic, eg for tests).
2396 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002398 int (*f_rng)(void *, unsigned char *, size_t),
2399 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002400{
Janos Follath24eed8d2019-11-22 13:21:35 +00002401 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002402 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002403
Hanno Becker8ce11a32018-12-19 16:18:52 +00002404 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002405 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002406
Hanno Beckerda1655a2017-10-18 14:21:44 +01002407 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002408 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002409 if( size == 0 )
2410 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002411
Gilles Peskine8f454702021-04-01 15:57:18 +02002412 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002413
2414cleanup:
2415 return( ret );
2416}
2417
Gilles Peskine4699fa42021-03-29 22:02:55 +02002418int mbedtls_mpi_random( mbedtls_mpi *X,
2419 mbedtls_mpi_sint min,
2420 const mbedtls_mpi *N,
2421 int (*f_rng)(void *, unsigned char *, size_t),
2422 void *p_rng )
2423{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002424 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002425 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002426 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002427 size_t n_bits = mbedtls_mpi_bitlen( N );
2428 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002429 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002430
Gilles Peskine9312ba52021-03-29 22:14:51 +02002431 if( min < 0 )
2432 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2433 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2434 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2435
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002436 /*
2437 * When min == 0, each try has at worst a probability 1/2 of failing
2438 * (the msb has a probability 1/2 of being 0, and then the result will
2439 * be < N), so after 30 tries failure probability is a most 2**(-30).
2440 *
2441 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002442 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002443 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002444 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002445 * a probability of failing that is almost 1/2.
2446 *
2447 * The probabilities are almost the same if min is nonzero but negligible
2448 * compared to N. This is always the case when N is crypto-sized, but
2449 * it's convenient to support small N for testing purposes. When N
2450 * is small, use a higher repeat count, otherwise the probability of
2451 * failure is macroscopic.
2452 */
Gilles Peskine11779072021-06-02 21:18:59 +02002453 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002454
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002455 mbedtls_mpi_init( &lower_bound );
2456
Gilles Peskine8f454702021-04-01 15:57:18 +02002457 /* Ensure that target MPI has exactly the same number of limbs
2458 * as the upper bound, even if the upper bound has leading zeros.
2459 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002460 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002461 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2462 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002463
Gilles Peskine4699fa42021-03-29 22:02:55 +02002464 /*
2465 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2466 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2467 * - use the same byte ordering;
2468 * - keep the leftmost n_bits bits of the generated octet string;
2469 * - try until result is in the desired range.
2470 * This also avoids any bias, which is especially important for ECDSA.
2471 */
2472 do
2473 {
Gilles Peskine8f454702021-04-01 15:57:18 +02002474 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002475 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2476
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002477 if( --count == 0 )
Gilles Peskine4699fa42021-03-29 22:02:55 +02002478 {
2479 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2480 goto cleanup;
2481 }
2482
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002483 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2484 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002485 }
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002486 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002487
2488cleanup:
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002489 mbedtls_mpi_free( &lower_bound );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002490 return( ret );
2491}
2492
Paul Bakker5121ce52009-01-03 21:22:43 +00002493/*
2494 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002497{
Janos Follath24eed8d2019-11-22 13:21:35 +00002498 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002500 MPI_VALIDATE_RET( X != NULL );
2501 MPI_VALIDATE_RET( A != NULL );
2502 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002503
Hanno Becker4bcb4912017-04-18 15:49:39 +01002504 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2508 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2509 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002513 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002514 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002515 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002516 goto cleanup;
2517 }
2518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002519 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2520 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2521 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2522 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2525 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2526 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2527 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002528
2529 do
2530 {
2531 while( ( TU.p[0] & 1 ) == 0 )
2532 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002534
2535 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2536 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2538 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002539 }
2540
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002541 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2542 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002543 }
2544
2545 while( ( TV.p[0] & 1 ) == 0 )
2546 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002548
2549 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2550 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002551 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2552 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553 }
2554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002555 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2556 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002557 }
2558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002560 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002561 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2562 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2563 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002564 }
2565 else
2566 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002567 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2568 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2569 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002570 }
2571 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2575 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2578 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002580 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002581
2582cleanup:
2583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2585 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2586 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002587
2588 return( ret );
2589}
2590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002592
Paul Bakker5121ce52009-01-03 21:22:43 +00002593static const int small_prime[] =
2594{
2595 3, 5, 7, 11, 13, 17, 19, 23,
2596 29, 31, 37, 41, 43, 47, 53, 59,
2597 61, 67, 71, 73, 79, 83, 89, 97,
2598 101, 103, 107, 109, 113, 127, 131, 137,
2599 139, 149, 151, 157, 163, 167, 173, 179,
2600 181, 191, 193, 197, 199, 211, 223, 227,
2601 229, 233, 239, 241, 251, 257, 263, 269,
2602 271, 277, 281, 283, 293, 307, 311, 313,
2603 317, 331, 337, 347, 349, 353, 359, 367,
2604 373, 379, 383, 389, 397, 401, 409, 419,
2605 421, 431, 433, 439, 443, 449, 457, 461,
2606 463, 467, 479, 487, 491, 499, 503, 509,
2607 521, 523, 541, 547, 557, 563, 569, 571,
2608 577, 587, 593, 599, 601, 607, 613, 617,
2609 619, 631, 641, 643, 647, 653, 659, 661,
2610 673, 677, 683, 691, 701, 709, 719, 727,
2611 733, 739, 743, 751, 757, 761, 769, 773,
2612 787, 797, 809, 811, 821, 823, 827, 829,
2613 839, 853, 857, 859, 863, 877, 881, 883,
2614 887, 907, 911, 919, 929, 937, 941, 947,
2615 953, 967, 971, 977, 983, 991, 997, -103
2616};
2617
2618/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002619 * Small divisors test (X must be positive)
2620 *
2621 * Return values:
2622 * 0: no small factor (possible prime, more tests needed)
2623 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002625 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002626 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002627static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002628{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002629 int ret = 0;
2630 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002631 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002632
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002635
2636 for( i = 0; small_prime[i] > 0; i++ )
2637 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002638 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002639 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002641 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002642
2643 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002644 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002645 }
2646
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002647cleanup:
2648 return( ret );
2649}
2650
2651/*
2652 * Miller-Rabin pseudo-primality test (HAC 4.24)
2653 */
Janos Follathda31fa12018-09-03 14:45:23 +01002654static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002655 int (*f_rng)(void *, unsigned char *, size_t),
2656 void *p_rng )
2657{
Pascal Junodb99183d2015-03-11 16:49:45 +01002658 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002659 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002661
Hanno Becker8ce11a32018-12-19 16:18:52 +00002662 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002663 MPI_VALIDATE_RET( f_rng != NULL );
2664
2665 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2666 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002668
Paul Bakker5121ce52009-01-03 21:22:43 +00002669 /*
2670 * W = |X| - 1
2671 * R = W >> lsb( W )
2672 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2674 s = mbedtls_mpi_lsb( &W );
2675 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2676 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002677
Janos Follathda31fa12018-09-03 14:45:23 +01002678 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002679 {
2680 /*
2681 * pick a random A, 1 < A < |X| - 1
2682 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002683 count = 0;
2684 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002685 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002686
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002687 j = mbedtls_mpi_bitlen( &A );
2688 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002689 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002690 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002691 }
2692
2693 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002694 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2695 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002696 }
2697
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002698 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2699 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002700
2701 /*
2702 * A = A^R mod |X|
2703 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002705
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002706 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2707 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002708 continue;
2709
2710 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002712 {
2713 /*
2714 * A = A * A mod |X|
2715 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002716 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2717 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002719 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002720 break;
2721
2722 j++;
2723 }
2724
2725 /*
2726 * not prime if A != |X| - 1 or A == 1
2727 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002728 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2729 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002730 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002732 break;
2733 }
2734 }
2735
2736cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002737 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2738 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002739 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002740
2741 return( ret );
2742}
2743
2744/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002745 * Pseudo-primality test: small factors, then Miller-Rabin
2746 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002747int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2748 int (*f_rng)(void *, unsigned char *, size_t),
2749 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002750{
Janos Follath24eed8d2019-11-22 13:21:35 +00002751 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002753 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002754 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002755
2756 XX.s = 1;
2757 XX.n = X->n;
2758 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002760 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2761 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2762 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002763
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002764 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002765 return( 0 );
2766
2767 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2768 {
2769 if( ret == 1 )
2770 return( 0 );
2771
2772 return( ret );
2773 }
2774
Janos Follathda31fa12018-09-03 14:45:23 +01002775 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002776}
2777
Janos Follatha0b67c22018-09-18 14:48:23 +01002778#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002779/*
2780 * Pseudo-primality test, error probability 2^-80
2781 */
2782int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2783 int (*f_rng)(void *, unsigned char *, size_t),
2784 void *p_rng )
2785{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002786 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002787 MPI_VALIDATE_RET( f_rng != NULL );
2788
Janos Follatha0b67c22018-09-18 14:48:23 +01002789 /*
2790 * In the past our key generation aimed for an error rate of at most
2791 * 2^-80. Since this function is deprecated, aim for the same certainty
2792 * here as well.
2793 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002794 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002795}
Janos Follatha0b67c22018-09-18 14:48:23 +01002796#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002797
2798/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002799 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002800 *
Janos Follathf301d232018-08-14 13:34:01 +01002801 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2802 * be either 1024 bits or 1536 bits long, and flags must contain
2803 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002804 */
Janos Follath7c025a92018-08-14 11:08:41 +01002805int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002806 int (*f_rng)(void *, unsigned char *, size_t),
2807 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002808{
Jethro Beekman66689272018-02-14 19:24:10 -08002809#ifdef MBEDTLS_HAVE_INT64
2810// ceil(2^63.5)
2811#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2812#else
2813// ceil(2^31.5)
2814#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2815#endif
2816 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002817 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002818 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002819 mbedtls_mpi_uint r;
2820 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002821
Hanno Becker8ce11a32018-12-19 16:18:52 +00002822 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002823 MPI_VALIDATE_RET( f_rng != NULL );
2824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2826 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002828 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002829
2830 n = BITS_TO_LIMBS( nbits );
2831
Janos Follathda31fa12018-09-03 14:45:23 +01002832 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2833 {
2834 /*
2835 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2836 */
2837 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2838 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2839 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2840 }
2841 else
2842 {
2843 /*
2844 * 2^-100 error probability, number of rounds computed based on HAC,
2845 * fact 4.48
2846 */
2847 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2848 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2849 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2850 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2851 }
2852
Jethro Beekman66689272018-02-14 19:24:10 -08002853 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002854 {
Jethro Beekman66689272018-02-14 19:24:10 -08002855 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2856 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2857 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2858
2859 k = n * biL;
2860 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2861 X->p[0] |= 1;
2862
Janos Follath7c025a92018-08-14 11:08:41 +01002863 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002864 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002865 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002866
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002867 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002868 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002869 }
Jethro Beekman66689272018-02-14 19:24:10 -08002870 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002871 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002872 /*
Tom Cosgrove5205c972022-07-28 06:12:08 +01002873 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002874 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2875 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002876 */
Jethro Beekman66689272018-02-14 19:24:10 -08002877
2878 X->p[0] |= 2;
2879
2880 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2881 if( r == 0 )
2882 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2883 else if( r == 1 )
2884 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2885
2886 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2887 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2888 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2889
2890 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002891 {
Jethro Beekman66689272018-02-14 19:24:10 -08002892 /*
2893 * First, check small factors for X and Y
2894 * before doing Miller-Rabin on any of them
2895 */
2896 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2897 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002898 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002899 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002900 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002901 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002902 goto cleanup;
2903
2904 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2905 goto cleanup;
2906
2907 /*
2908 * Next candidates. We want to preserve Y = (X-1) / 2 and
2909 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2910 * so up Y by 6 and X by 12.
2911 */
2912 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2913 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002914 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002915 }
2916 }
2917
2918cleanup:
2919
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002920 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002921
2922 return( ret );
2923}
2924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002925#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002927#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002928
Paul Bakker23986e52011-04-24 08:57:21 +00002929#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002930
2931static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2932{
2933 { 693, 609, 21 },
2934 { 1764, 868, 28 },
2935 { 768454923, 542167814, 1 }
2936};
2937
Paul Bakker5121ce52009-01-03 21:22:43 +00002938/*
2939 * Checkup routine
2940 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002941int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002942{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002943 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002944 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002946 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2947 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002948
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002949 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002950 "EFE021C2645FD1DC586E69184AF4A31E" \
2951 "D5F53E93B5F123FA41680867BA110131" \
2952 "944FE7952E2517337780CB0DB80E61AA" \
2953 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002955 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002956 "B2E7EFD37075B9F03FF989C7C5051C20" \
2957 "34D2A323810251127E7BF8625A4F49A5" \
2958 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2959 "5B5C25763222FEFCCFC38B832366C29E" ) );
2960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002961 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002962 "0066A198186C18C10B2F5ED9B522752A" \
2963 "9830B69916E535C8F047518A889A43A5" \
2964 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2965
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002966 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002968 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002969 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2970 "9E857EA95A03512E2BAE7391688D264A" \
2971 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2972 "8001B72E848A38CAE1C65F78E56ABDEF" \
2973 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2974 "ECF677152EF804370C1A305CAF3B5BF1" \
2975 "30879B56C61DE584A0F53A2447A51E" ) );
2976
2977 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002978 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002980 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002981 {
2982 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002983 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002984
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002985 ret = 1;
2986 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002987 }
2988
2989 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002990 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002991
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002992 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002994 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002995 "256567336059E52CAE22925474705F39A94" ) );
2996
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002997 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002998 "6613F26162223DF488E9CD48CC132C7A" \
2999 "0AC93C701B001B092E4E5B9F73BCD27B" \
3000 "9EE50D0657C77F374E903CDFA4C642" ) );
3001
3002 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003003 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003004
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003005 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3006 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003007 {
3008 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003009 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003010
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003011 ret = 1;
3012 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003013 }
3014
3015 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003016 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003018 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003020 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003021 "36E139AEA55215609D2816998ED020BB" \
3022 "BD96C37890F65171D948E9BC7CBAA4D9" \
3023 "325D24D6A3C12710F10A09FA08AB87" ) );
3024
3025 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003026 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003028 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003029 {
3030 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003031 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003032
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003033 ret = 1;
3034 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003035 }
3036
3037 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003038 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003040 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003042 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003043 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3044 "C3DBA76456363A10869622EAC2DD84EC" \
3045 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3046
3047 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003048 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003049
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003050 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003051 {
3052 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003053 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003054
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003055 ret = 1;
3056 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003057 }
3058
3059 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003060 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003061
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003062 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003063 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003064
Paul Bakker66d5d072014-06-17 16:39:18 +02003065 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003066 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003067 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3068 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003070 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003072 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003073 {
3074 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003075 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003076
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003077 ret = 1;
3078 goto cleanup;
3079 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003080 }
3081
3082 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003083 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003084
Paul Bakker5121ce52009-01-03 21:22:43 +00003085cleanup:
3086
3087 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003088 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003090 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3091 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003092
3093 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003094 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003095
3096 return( ret );
3097}
3098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003099#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003101#endif /* MBEDTLS_BIGNUM_C */