blob: 62e7f76727f5dc3d7129cf77ab7eeb4184f1bc73 [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é-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000050#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020051#else
Rich Evans00ab4702015-02-06 13:43:58 +000052#include <stdio.h>
53#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020055#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020057#endif
58
Hanno Becker73d7d792018-12-11 10:35:51 +000059#define MPI_VALIDATE_RET( cond ) \
60 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
61#define MPI_VALIDATE( cond ) \
62 MBEDTLS_INTERNAL_VALIDATE( cond )
63
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020064#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000065#define biL (ciL << 3) /* bits in limb */
66#define biH (ciL << 2) /* half limb size */
67
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010068#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
69
Paul Bakker5121ce52009-01-03 21:22:43 +000070/*
71 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020072 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000073 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020074#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
75#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000076
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050077/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050078static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
79{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080 mbedtls_platform_zeroize( v, ciL * n );
81}
82
Paul Bakker5121ce52009-01-03 21:22:43 +000083/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000084 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000085 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000087{
Hanno Becker73d7d792018-12-11 10:35:51 +000088 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000089
Paul Bakker6c591fa2011-05-05 11:49:20 +000090 X->s = 1;
91 X->n = 0;
92 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000093}
94
95/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000096 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000097 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000099{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000100 if( X == NULL )
101 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000102
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000104 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200105 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 }
108
Paul Bakker6c591fa2011-05-05 11:49:20 +0000109 X->s = 1;
110 X->n = 0;
111 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000112}
113
114/*
115 * Enlarge to the specified number of limbs
116 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000118{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000120 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200123 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000124
Paul Bakker5121ce52009-01-03 21:22:43 +0000125 if( X->n < nblimbs )
126 {
Simon Butcher29176892016-05-20 00:19:09 +0100127 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200128 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000129
Paul Bakker5121ce52009-01-03 21:22:43 +0000130 if( X->p != NULL )
131 {
132 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200133 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000135 }
136
137 X->n = nblimbs;
138 X->p = p;
139 }
140
141 return( 0 );
142}
143
144/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100145 * Resize down as much as possible,
146 * while keeping at least the specified number of limbs
147 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100151 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000152 MPI_VALIDATE_RET( X != NULL );
153
154 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
155 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100156
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100157 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100158 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100160 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100161
162 for( i = X->n - 1; i > 0; i-- )
163 if( X->p[i] != 0 )
164 break;
165 i++;
166
167 if( i < nblimbs )
168 i = nblimbs;
169
Simon Butcher29176892016-05-20 00:19:09 +0100170 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200171 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100172
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100173 if( X->p != NULL )
174 {
175 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200176 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100178 }
179
180 X->n = i;
181 X->p = p;
182
183 return( 0 );
184}
185
Gilles Peskine3130ce22021-06-02 22:17:52 +0200186/* Resize X to have exactly n limbs and set it to 0. */
187static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
188{
189 if( limbs == 0 )
190 {
191 mbedtls_mpi_free( X );
192 return( 0 );
193 }
194 else if( X->n == limbs )
195 {
196 memset( X->p, 0, limbs * ciL );
197 X->s = 1;
198 return( 0 );
199 }
200 else
201 {
202 mbedtls_mpi_free( X );
203 return( mbedtls_mpi_grow( X, limbs ) );
204 }
205}
206
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100207/*
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200208 * Copy the contents of Y into X.
209 *
210 * This function is not constant-time. Leading zeros in Y may be removed.
211 *
212 * Ensure that X does not shrink. This is not guaranteed by the public API,
213 * but some code in the bignum module relies on this property, for example
214 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000215 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000217{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100218 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000219 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000220 MPI_VALIDATE_RET( X != NULL );
221 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
223 if( X == Y )
224 return( 0 );
225
Gilles Peskinedb420622020-01-20 21:12:50 +0100226 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200227 {
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200228 if( X->n != 0 )
229 {
230 X->s = 1;
231 memset( X->p, 0, X->n * ciL );
232 }
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200233 return( 0 );
234 }
235
Paul Bakker5121ce52009-01-03 21:22:43 +0000236 for( i = Y->n - 1; i > 0; i-- )
237 if( Y->p[i] != 0 )
238 break;
239 i++;
240
241 X->s = Y->s;
242
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100243 if( X->n < i )
244 {
245 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
246 }
247 else
248 {
249 memset( X->p + i, 0, ( X->n - i ) * ciL );
250 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000251
Paul Bakker5121ce52009-01-03 21:22:43 +0000252 memcpy( X->p, Y->p, i * ciL );
253
254cleanup:
255
256 return( ret );
257}
258
259/*
260 * Swap the contents of X and Y
261 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000263{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000265 MPI_VALIDATE( X != NULL );
266 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 memcpy( &T, X, sizeof( mbedtls_mpi ) );
269 memcpy( X, Y, sizeof( mbedtls_mpi ) );
270 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000271}
272
273/*
274 * Set value from integer
275 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000277{
Janos Follath24eed8d2019-11-22 13:21:35 +0000278 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000279 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000282 memset( X->p, 0, X->n * ciL );
283
284 X->p[0] = ( z < 0 ) ? -z : z;
285 X->s = ( z < 0 ) ? -1 : 1;
286
287cleanup:
288
289 return( ret );
290}
291
292/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000293 * Get a specific bit
294 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000296{
Hanno Becker73d7d792018-12-11 10:35:51 +0000297 MPI_VALIDATE_RET( X != NULL );
298
Paul Bakker2f5947e2011-05-18 15:47:11 +0000299 if( X->n * biL <= pos )
300 return( 0 );
301
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200302 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000303}
304
Gilles Peskine11cdb052018-11-20 16:47:47 +0100305/* Get a specific byte, without range checks. */
306#define GET_BYTE( X, i ) \
307 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
308
Paul Bakker2f5947e2011-05-18 15:47:11 +0000309/*
310 * Set a bit to a specific value of 0 or 1
311 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000313{
314 int ret = 0;
315 size_t off = pos / biL;
316 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000317 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000318
319 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200321
Paul Bakker2f5947e2011-05-18 15:47:11 +0000322 if( X->n * biL <= pos )
323 {
324 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200325 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000328 }
329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200330 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
331 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332
333cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200334
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335 return( ret );
336}
337
338/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200339 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000340 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000342{
Paul Bakker23986e52011-04-24 08:57:21 +0000343 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000344 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000345
346 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000347 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
349 return( count );
350
351 return( 0 );
352}
353
354/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000355 * Count leading zero bits in a given integer
356 */
357static size_t mbedtls_clz( const mbedtls_mpi_uint x )
358{
359 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100360 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000361
362 for( j = 0; j < biL; j++ )
363 {
364 if( x & mask ) break;
365
366 mask >>= 1;
367 }
368
369 return j;
370}
371
372/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200373 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000374 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200375size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000376{
Paul Bakker23986e52011-04-24 08:57:21 +0000377 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000378
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200379 if( X->n == 0 )
380 return( 0 );
381
Paul Bakker5121ce52009-01-03 21:22:43 +0000382 for( i = X->n - 1; i > 0; i-- )
383 if( X->p[i] != 0 )
384 break;
385
Simon Butcher15b15d12015-11-26 19:35:03 +0000386 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000387
Paul Bakker23986e52011-04-24 08:57:21 +0000388 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000389}
390
391/*
392 * Return the total size in bytes
393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000395{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200396 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000397}
398
399/*
400 * Convert an ASCII character to digit value
401 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000403{
404 *d = 255;
405
406 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
407 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
408 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410 if( *d >= (mbedtls_mpi_uint) radix )
411 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000412
413 return( 0 );
414}
415
416/*
417 * Import from an ASCII string
418 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000420{
Janos Follath24eed8d2019-11-22 13:21:35 +0000421 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000422 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200423 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 mbedtls_mpi_uint d;
425 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000426 MPI_VALIDATE_RET( X != NULL );
427 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428
429 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000430 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
Gilles Peskined4876132021-06-08 18:32:34 +0200434 if( s[0] == 0 )
435 {
436 mbedtls_mpi_free( X );
437 return( 0 );
438 }
439
Gilles Peskine80f56732021-04-03 18:26:13 +0200440 if( s[0] == '-' )
441 {
442 ++s;
443 sign = -1;
444 }
445
Paul Bakkerff60ee62010-03-16 21:09:09 +0000446 slen = strlen( s );
447
Paul Bakker5121ce52009-01-03 21:22:43 +0000448 if( radix == 16 )
449 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100450 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200451 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
452
Paul Bakkerff60ee62010-03-16 21:09:09 +0000453 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
456 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000457
Paul Bakker23986e52011-04-24 08:57:21 +0000458 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200461 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000462 }
463 }
464 else
465 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467
Paul Bakkerff60ee62010-03-16 21:09:09 +0000468 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000469 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
471 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200472 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000473 }
474 }
475
Gilles Peskine80f56732021-04-03 18:26:13 +0200476 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
477 X->s = -1;
478
Paul Bakker5121ce52009-01-03 21:22:43 +0000479cleanup:
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000482
483 return( ret );
484}
485
486/*
Ron Eldora16fa292018-11-20 14:07:01 +0200487 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 */
Ron Eldora16fa292018-11-20 14:07:01 +0200489static int mpi_write_hlp( mbedtls_mpi *X, int radix,
490 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000491{
Janos Follath24eed8d2019-11-22 13:21:35 +0000492 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200494 size_t length = 0;
495 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000496
Ron Eldora16fa292018-11-20 14:07:01 +0200497 do
498 {
499 if( length >= buflen )
500 {
501 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
502 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Ron Eldora16fa292018-11-20 14:07:01 +0200504 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
505 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
506 /*
507 * Write the residue in the current position, as an ASCII character.
508 */
509 if( r < 0xA )
510 *(--p_end) = (char)( '0' + r );
511 else
512 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513
Ron Eldora16fa292018-11-20 14:07:01 +0200514 length++;
515 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000516
Ron Eldora16fa292018-11-20 14:07:01 +0200517 memmove( *p, p_end, length );
518 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
520cleanup:
521
522 return( ret );
523}
524
525/*
526 * Export into an ASCII string
527 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100528int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
529 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000530{
Paul Bakker23986e52011-04-24 08:57:21 +0000531 int ret = 0;
532 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000533 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000535 MPI_VALIDATE_RET( X != NULL );
536 MPI_VALIDATE_RET( olen != NULL );
537 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000538
539 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000540 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000541
Hanno Becker23cfea02019-02-04 09:45:07 +0000542 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
543 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
544 * `n`. If radix > 4, this might be a strict
545 * overapproximation of the number of
546 * radix-adic digits needed to present `n`. */
547 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
548 * present `n`. */
549
Janos Follath80470622019-03-06 13:43:02 +0000550 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000551 n += 1; /* Compensate for the divisions above, which round down `n`
552 * in case it's not even. */
553 n += 1; /* Potential '-'-sign. */
554 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
555 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100557 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000558 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100559 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000561 }
562
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100563 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
566 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000567 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000568 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000569 buflen--;
570 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000571
572 if( radix == 16 )
573 {
Paul Bakker23986e52011-04-24 08:57:21 +0000574 int c;
575 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576
Paul Bakker23986e52011-04-24 08:57:21 +0000577 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 {
Paul Bakker23986e52011-04-24 08:57:21 +0000579 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000580 {
Paul Bakker23986e52011-04-24 08:57:21 +0000581 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
Paul Bakker6c343d72014-07-10 14:36:19 +0200583 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 continue;
585
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000586 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000587 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000588 k = 1;
589 }
590 }
591 }
592 else
593 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000595
596 if( T.s == -1 )
597 T.s = 1;
598
Ron Eldora16fa292018-11-20 14:07:01 +0200599 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000600 }
601
602 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100603 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000604
605cleanup:
606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
609 return( ret );
610}
611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000613/*
614 * Read X from an opened file
615 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000617{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000619 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000620 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000621 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000622 * Buffer should have space for (short) label and decimal formatted MPI,
623 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000624 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000626
Hanno Becker73d7d792018-12-11 10:35:51 +0000627 MPI_VALIDATE_RET( X != NULL );
628 MPI_VALIDATE_RET( fin != NULL );
629
630 if( radix < 2 || radix > 16 )
631 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
632
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 memset( s, 0, sizeof( s ) );
634 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000636
637 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000638 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000640
Hanno Beckerb2034b72017-04-26 11:46:46 +0100641 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
642 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
644 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100645 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000646 if( mpi_get_digit( &d, radix, *p ) != 0 )
647 break;
648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000650}
651
652/*
653 * Write X into an opened file (or stdout if fout == NULL)
654 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000656{
Janos Follath24eed8d2019-11-22 13:21:35 +0000657 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000658 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000659 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000660 * Buffer should have space for (short) label and decimal formatted MPI,
661 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000662 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000664 MPI_VALIDATE_RET( X != NULL );
665
666 if( radix < 2 || radix > 16 )
667 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100669 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100671 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000672
673 if( p == NULL ) p = "";
674
675 plen = strlen( p );
676 slen = strlen( s );
677 s[slen++] = '\r';
678 s[slen++] = '\n';
679
680 if( fout != NULL )
681 {
682 if( fwrite( p, 1, plen, fout ) != plen ||
683 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000685 }
686 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000688
689cleanup:
690
691 return( ret );
692}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
Hanno Beckerda1655a2017-10-18 14:21:44 +0100695
696/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
697 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000698
699static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
700{
701 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100702 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000703 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100704
705 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
706 {
707 tmp <<= CHAR_BIT;
708 tmp |= (mbedtls_mpi_uint) *x_ptr;
709 }
710
Hanno Beckerf8720072018-11-08 11:53:49 +0000711 return( tmp );
712}
713
714static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
715{
716#if defined(__BYTE_ORDER__)
717
718/* Nothing to do on bigendian systems. */
719#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
720 return( x );
721#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
722
723#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
724
725/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000726#if defined(__GNUC__) && defined(__GNUC_PREREQ)
727#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000728#define have_bswap
729#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000730#endif
731
732#if defined(__clang__) && defined(__has_builtin)
733#if __has_builtin(__builtin_bswap32) && \
734 __has_builtin(__builtin_bswap64)
735#define have_bswap
736#endif
737#endif
738
Hanno Beckerf8720072018-11-08 11:53:49 +0000739#if defined(have_bswap)
740 /* The compiler is hopefully able to statically evaluate this! */
741 switch( sizeof(mbedtls_mpi_uint) )
742 {
743 case 4:
744 return( __builtin_bswap32(x) );
745 case 8:
746 return( __builtin_bswap64(x) );
747 }
748#endif
749#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
750#endif /* __BYTE_ORDER__ */
751
752 /* Fall back to C-based reordering if we don't know the byte order
753 * or we couldn't use a compiler-specific builtin. */
754 return( mpi_uint_bigendian_to_host_c( x ) );
755}
756
Hanno Becker2be8a552018-10-25 12:40:09 +0100757static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100758{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100759 mbedtls_mpi_uint *cur_limb_left;
760 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100761 if( limbs == 0 )
762 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100763
764 /*
765 * Traverse limbs and
766 * - adapt byte-order in each limb
767 * - swap the limbs themselves.
768 * For that, simultaneously traverse the limbs from left to right
769 * and from right to left, as long as the left index is not bigger
770 * than the right index (it's not a problem if limbs is odd and the
771 * indices coincide in the last iteration).
772 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100773 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
774 cur_limb_left <= cur_limb_right;
775 cur_limb_left++, cur_limb_right-- )
776 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000777 mbedtls_mpi_uint tmp;
778 /* Note that if cur_limb_left == cur_limb_right,
779 * this code effectively swaps the bytes only once. */
780 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
781 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
782 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100783 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100784}
785
Paul Bakker5121ce52009-01-03 21:22:43 +0000786/*
Janos Follatha778a942019-02-13 10:28:28 +0000787 * Import X from unsigned binary data, little endian
788 */
789int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
790 const unsigned char *buf, size_t buflen )
791{
Janos Follath24eed8d2019-11-22 13:21:35 +0000792 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000793 size_t i;
794 size_t const limbs = CHARS_TO_LIMBS( buflen );
795
796 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200797 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000798
799 for( i = 0; i < buflen; i++ )
800 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
801
802cleanup:
803
Janos Follath171a7ef2019-02-15 16:17:45 +0000804 /*
805 * This function is also used to import keys. However, wiping the buffers
806 * upon failure is not necessary because failure only can happen before any
807 * input is copied.
808 */
Janos Follatha778a942019-02-13 10:28:28 +0000809 return( ret );
810}
811
812/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000813 * Import X from unsigned binary data, big endian
814 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200815int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000816{
Janos Follath24eed8d2019-11-22 13:21:35 +0000817 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100818 size_t const limbs = CHARS_TO_LIMBS( buflen );
819 size_t const overhead = ( limbs * ciL ) - buflen;
820 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000821
Hanno Becker8ce11a32018-12-19 16:18:52 +0000822 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000823 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
824
Hanno Becker073c1992017-10-17 15:17:27 +0100825 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200826 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000827
Gilles Peskine3130ce22021-06-02 22:17:52 +0200828 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000829 * even if buflen is 0. */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200830 if( buflen != 0 )
Hanno Becker0e810b92019-01-03 17:13:11 +0000831 {
832 Xp = (unsigned char*) X->p;
833 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100834
Hanno Becker0e810b92019-01-03 17:13:11 +0000835 mpi_bigendian_to_host( X->p, limbs );
836 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000837
838cleanup:
839
Janos Follath171a7ef2019-02-15 16:17:45 +0000840 /*
841 * This function is also used to import keys. However, wiping the buffers
842 * upon failure is not necessary because failure only can happen before any
843 * input is copied.
844 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000845 return( ret );
846}
847
848/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000849 * Export X into unsigned binary data, little endian
850 */
851int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
852 unsigned char *buf, size_t buflen )
853{
854 size_t stored_bytes = X->n * ciL;
855 size_t bytes_to_copy;
856 size_t i;
857
858 if( stored_bytes < buflen )
859 {
860 bytes_to_copy = stored_bytes;
861 }
862 else
863 {
864 bytes_to_copy = buflen;
865
866 /* The output buffer is smaller than the allocated size of X.
867 * However X may fit if its leading bytes are zero. */
868 for( i = bytes_to_copy; i < stored_bytes; i++ )
869 {
870 if( GET_BYTE( X, i ) != 0 )
871 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
872 }
873 }
874
875 for( i = 0; i < bytes_to_copy; i++ )
876 buf[i] = GET_BYTE( X, i );
877
878 if( stored_bytes < buflen )
879 {
880 /* Write trailing 0 bytes */
881 memset( buf + stored_bytes, 0, buflen - stored_bytes );
882 }
883
884 return( 0 );
885}
886
887/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000888 * Export X into unsigned binary data, big endian
889 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100890int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
891 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000892{
Hanno Becker73d7d792018-12-11 10:35:51 +0000893 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100894 size_t bytes_to_copy;
895 unsigned char *p;
896 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000897
Hanno Becker73d7d792018-12-11 10:35:51 +0000898 MPI_VALIDATE_RET( X != NULL );
899 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
900
901 stored_bytes = X->n * ciL;
902
Gilles Peskine11cdb052018-11-20 16:47:47 +0100903 if( stored_bytes < buflen )
904 {
905 /* There is enough space in the output buffer. Write initial
906 * null bytes and record the position at which to start
907 * writing the significant bytes. In this case, the execution
908 * trace of this function does not depend on the value of the
909 * number. */
910 bytes_to_copy = stored_bytes;
911 p = buf + buflen - stored_bytes;
912 memset( buf, 0, buflen - stored_bytes );
913 }
914 else
915 {
916 /* The output buffer is smaller than the allocated size of X.
917 * However X may fit if its leading bytes are zero. */
918 bytes_to_copy = buflen;
919 p = buf;
920 for( i = bytes_to_copy; i < stored_bytes; i++ )
921 {
922 if( GET_BYTE( X, i ) != 0 )
923 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
924 }
925 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
Gilles Peskine11cdb052018-11-20 16:47:47 +0100927 for( i = 0; i < bytes_to_copy; i++ )
928 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
930 return( 0 );
931}
932
933/*
934 * Left-shift: X <<= count
935 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000937{
Janos Follath24eed8d2019-11-22 13:21:35 +0000938 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000939 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000941 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000942
943 v0 = count / (biL );
944 t1 = count & (biL - 1);
945
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200946 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000947
Paul Bakkerf9688572011-05-05 10:00:45 +0000948 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000950
951 ret = 0;
952
953 /*
954 * shift by count / limb_size
955 */
956 if( v0 > 0 )
957 {
Paul Bakker23986e52011-04-24 08:57:21 +0000958 for( i = X->n; i > v0; i-- )
959 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000960
Paul Bakker23986e52011-04-24 08:57:21 +0000961 for( ; i > 0; i-- )
962 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000963 }
964
965 /*
966 * shift by count % limb_size
967 */
968 if( t1 > 0 )
969 {
970 for( i = v0; i < X->n; i++ )
971 {
972 r1 = X->p[i] >> (biL - t1);
973 X->p[i] <<= t1;
974 X->p[i] |= r0;
975 r0 = r1;
976 }
977 }
978
979cleanup:
980
981 return( ret );
982}
983
984/*
985 * Right-shift: X >>= count
986 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000988{
Paul Bakker23986e52011-04-24 08:57:21 +0000989 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000991 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000992
993 v0 = count / biL;
994 v1 = count & (biL - 1);
995
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100996 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100998
Paul Bakker5121ce52009-01-03 21:22:43 +0000999 /*
1000 * shift by count / limb_size
1001 */
1002 if( v0 > 0 )
1003 {
1004 for( i = 0; i < X->n - v0; i++ )
1005 X->p[i] = X->p[i + v0];
1006
1007 for( ; i < X->n; i++ )
1008 X->p[i] = 0;
1009 }
1010
1011 /*
1012 * shift by count % limb_size
1013 */
1014 if( v1 > 0 )
1015 {
Paul Bakker23986e52011-04-24 08:57:21 +00001016 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001017 {
Paul Bakker23986e52011-04-24 08:57:21 +00001018 r1 = X->p[i - 1] << (biL - v1);
1019 X->p[i - 1] >>= v1;
1020 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 r0 = r1;
1022 }
1023 }
1024
1025 return( 0 );
1026}
1027
1028/*
1029 * Compare unsigned values
1030 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001032{
Paul Bakker23986e52011-04-24 08:57:21 +00001033 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001034 MPI_VALIDATE_RET( X != NULL );
1035 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001036
Paul Bakker23986e52011-04-24 08:57:21 +00001037 for( i = X->n; i > 0; i-- )
1038 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 break;
1040
Paul Bakker23986e52011-04-24 08:57:21 +00001041 for( j = Y->n; j > 0; j-- )
1042 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 break;
1044
Paul Bakker23986e52011-04-24 08:57:21 +00001045 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001046 return( 0 );
1047
1048 if( i > j ) return( 1 );
1049 if( j > i ) return( -1 );
1050
Paul Bakker23986e52011-04-24 08:57:21 +00001051 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001052 {
Paul Bakker23986e52011-04-24 08:57:21 +00001053 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1054 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 }
1056
1057 return( 0 );
1058}
1059
1060/*
1061 * Compare signed values
1062 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001064{
Paul Bakker23986e52011-04-24 08:57:21 +00001065 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001066 MPI_VALIDATE_RET( X != NULL );
1067 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001068
Paul Bakker23986e52011-04-24 08:57:21 +00001069 for( i = X->n; i > 0; i-- )
1070 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001071 break;
1072
Paul Bakker23986e52011-04-24 08:57:21 +00001073 for( j = Y->n; j > 0; j-- )
1074 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001075 break;
1076
Paul Bakker23986e52011-04-24 08:57:21 +00001077 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001078 return( 0 );
1079
1080 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001081 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001082
1083 if( X->s > 0 && Y->s < 0 ) return( 1 );
1084 if( Y->s > 0 && X->s < 0 ) return( -1 );
1085
Paul Bakker23986e52011-04-24 08:57:21 +00001086 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001087 {
Paul Bakker23986e52011-04-24 08:57:21 +00001088 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1089 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001090 }
1091
1092 return( 0 );
1093}
1094
Janos Follathee6abce2019-09-05 14:47:19 +01001095/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001096 * Compare signed values
1097 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001098int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001099{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100 mbedtls_mpi Y;
1101 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001102 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001103
1104 *p = ( z < 0 ) ? -z : z;
1105 Y.s = ( z < 0 ) ? -1 : 1;
1106 Y.n = 1;
1107 Y.p = p;
1108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001110}
1111
1112/*
1113 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001116{
Janos Follath24eed8d2019-11-22 13:21:35 +00001117 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001118 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001119 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001120 MPI_VALIDATE_RET( X != NULL );
1121 MPI_VALIDATE_RET( A != NULL );
1122 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001123
1124 if( X == B )
1125 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001126 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001127 }
1128
1129 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001131
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001132 /*
1133 * X should always be positive as a result of unsigned additions.
1134 */
1135 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001136
Paul Bakker23986e52011-04-24 08:57:21 +00001137 for( j = B->n; j > 0; j-- )
1138 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 break;
1140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001142
1143 o = B->p; p = X->p; c = 0;
1144
Janos Follath6c922682015-10-30 17:43:11 +01001145 /*
1146 * tmp is used because it might happen that p == o
1147 */
Paul Bakker23986e52011-04-24 08:57:21 +00001148 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001149 {
Janos Follath6c922682015-10-30 17:43:11 +01001150 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001151 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001152 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001153 }
1154
1155 while( c != 0 )
1156 {
1157 if( i >= X->n )
1158 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001159 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001160 p = X->p + i;
1161 }
1162
Paul Bakker2d319fd2012-09-16 21:34:26 +00001163 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001164 }
1165
1166cleanup:
1167
1168 return( ret );
1169}
1170
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001171/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001172 * Helper for mbedtls_mpi subtraction.
1173 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001174 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001175 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001176 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001177 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001178 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001179 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001180 * \param n Number of limbs of \p d, \p l and \p r.
1181 * \param[out] d The result of the subtraction.
1182 * \param[in] l The left operand.
1183 * \param[in] r The right operand.
1184 *
1185 * \return 1 if `l < r`.
1186 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001187 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001188static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1189 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001190 const mbedtls_mpi_uint *l,
1191 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001192{
Paul Bakker23986e52011-04-24 08:57:21 +00001193 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001194 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001195
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001196 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001197 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001198 z = ( l[i] < c ); t = l[i] - c;
1199 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001200 }
1201
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001202 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203}
1204
1205/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001206 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001209{
Janos Follath24eed8d2019-11-22 13:21:35 +00001210 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001211 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001212 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001213 MPI_VALIDATE_RET( X != NULL );
1214 MPI_VALIDATE_RET( A != NULL );
1215 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001216
Paul Bakker23986e52011-04-24 08:57:21 +00001217 for( n = B->n; n > 0; n-- )
1218 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001219 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001220 if( n > A->n )
1221 {
1222 /* B >= (2^ciL)^n > A */
1223 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1224 goto cleanup;
1225 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001226
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001227 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1228
1229 /* Set the high limbs of X to match A. Don't touch the lower limbs
1230 * because X might be aliased to B, and we must not overwrite the
1231 * significant digits of B. */
1232 if( A->n > n )
1233 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1234 if( X->n > A->n )
1235 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1236
1237 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001238 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001239 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001240 /* Propagate the carry to the first nonzero limb of X. */
1241 for( ; n < X->n && X->p[n] == 0; n++ )
1242 --X->p[n];
1243 /* If we ran out of space for the carry, it means that the result
1244 * is negative. */
1245 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001246 {
1247 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1248 goto cleanup;
1249 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001250 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001251 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001252
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001253 /* X should always be positive as a result of unsigned subtractions. */
1254 X->s = 1;
1255
Paul Bakker5121ce52009-01-03 21:22:43 +00001256cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001257 return( ret );
1258}
1259
1260/*
1261 * Signed addition: X = A + B
1262 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001263int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001264{
Hanno Becker73d7d792018-12-11 10:35:51 +00001265 int ret, s;
1266 MPI_VALIDATE_RET( X != NULL );
1267 MPI_VALIDATE_RET( A != NULL );
1268 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001269
Hanno Becker73d7d792018-12-11 10:35:51 +00001270 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001271 if( A->s * B->s < 0 )
1272 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001274 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001276 X->s = s;
1277 }
1278 else
1279 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001281 X->s = -s;
1282 }
1283 }
1284 else
1285 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001286 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001287 X->s = s;
1288 }
1289
1290cleanup:
1291
1292 return( ret );
1293}
1294
1295/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001296 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001297 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001298int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001299{
Hanno Becker73d7d792018-12-11 10:35:51 +00001300 int ret, s;
1301 MPI_VALIDATE_RET( X != NULL );
1302 MPI_VALIDATE_RET( A != NULL );
1303 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001304
Hanno Becker73d7d792018-12-11 10:35:51 +00001305 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001306 if( A->s * B->s > 0 )
1307 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001308 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001309 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001310 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001311 X->s = s;
1312 }
1313 else
1314 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001316 X->s = -s;
1317 }
1318 }
1319 else
1320 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001322 X->s = s;
1323 }
1324
1325cleanup:
1326
1327 return( ret );
1328}
1329
1330/*
1331 * Signed addition: X = A + b
1332 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001333int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001334{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001335 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001337 MPI_VALIDATE_RET( X != NULL );
1338 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001339
1340 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001341 B.s = ( b < 0 ) ? -1 : 1;
1342 B.n = 1;
1343 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001345 return( mbedtls_mpi_add_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001346}
1347
1348/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001349 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001352{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001353 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001355 MPI_VALIDATE_RET( X != NULL );
1356 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
1358 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001359 B.s = ( b < 0 ) ? -1 : 1;
1360 B.n = 1;
1361 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001363 return( mbedtls_mpi_sub_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364}
1365
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001366/** Helper for mbedtls_mpi multiplication.
1367 *
1368 * Add \p b * \p s to \p d.
1369 *
1370 * \param i The number of limbs of \p s.
1371 * \param[in] s A bignum to multiply, of size \p i.
1372 * It may overlap with \p d, but only if
1373 * \p d <= \p s.
1374 * Its leading limb must not be \c 0.
1375 * \param[in,out] d The bignum to add to.
1376 * It must be sufficiently large to store the
1377 * result of the multiplication. This means
1378 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1379 * is not known a priori.
1380 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001381 */
1382static
1383#if defined(__APPLE__) && defined(__arm__)
1384/*
1385 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1386 * appears to need this to prevent bad ARM code generation at -O3.
1387 */
1388__attribute__ ((noinline))
1389#endif
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001390void mpi_mul_hlp( size_t i,
1391 const mbedtls_mpi_uint *s,
1392 mbedtls_mpi_uint *d,
1393 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001394{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
1397#if defined(MULADDC_HUIT)
1398 for( ; i >= 8; i -= 8 )
1399 {
1400 MULADDC_INIT
1401 MULADDC_HUIT
1402 MULADDC_STOP
1403 }
1404
1405 for( ; i > 0; i-- )
1406 {
1407 MULADDC_INIT
1408 MULADDC_CORE
1409 MULADDC_STOP
1410 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001411#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001412 for( ; i >= 16; i -= 16 )
1413 {
1414 MULADDC_INIT
1415 MULADDC_CORE MULADDC_CORE
1416 MULADDC_CORE MULADDC_CORE
1417 MULADDC_CORE MULADDC_CORE
1418 MULADDC_CORE MULADDC_CORE
1419
1420 MULADDC_CORE MULADDC_CORE
1421 MULADDC_CORE MULADDC_CORE
1422 MULADDC_CORE MULADDC_CORE
1423 MULADDC_CORE MULADDC_CORE
1424 MULADDC_STOP
1425 }
1426
1427 for( ; i >= 8; i -= 8 )
1428 {
1429 MULADDC_INIT
1430 MULADDC_CORE MULADDC_CORE
1431 MULADDC_CORE MULADDC_CORE
1432
1433 MULADDC_CORE MULADDC_CORE
1434 MULADDC_CORE MULADDC_CORE
1435 MULADDC_STOP
1436 }
1437
1438 for( ; i > 0; i-- )
1439 {
1440 MULADDC_INIT
1441 MULADDC_CORE
1442 MULADDC_STOP
1443 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001444#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001445
1446 t++;
1447
Gilles Peskine8e464c42020-07-24 00:08:38 +02001448 while( c != 0 )
1449 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001450 *d += c; c = ( *d < c ); d++;
1451 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001452}
1453
1454/*
1455 * Baseline multiplication: X = A * B (HAC 14.12)
1456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001458{
Janos Follath24eed8d2019-11-22 13:21:35 +00001459 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001460 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 mbedtls_mpi TA, TB;
Gilles Peskined65b5002021-06-15 21:44:32 +02001462 int result_is_zero = 0;
Hanno Becker73d7d792018-12-11 10:35:51 +00001463 MPI_VALIDATE_RET( X != NULL );
1464 MPI_VALIDATE_RET( A != NULL );
1465 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001467 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1470 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001471
Paul Bakker23986e52011-04-24 08:57:21 +00001472 for( i = A->n; i > 0; i-- )
1473 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001474 break;
Gilles Peskine38a384d2021-06-17 14:35:25 +02001475 if( i == 0 )
Gilles Peskined65b5002021-06-15 21:44:32 +02001476 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
Paul Bakker23986e52011-04-24 08:57:21 +00001478 for( j = B->n; j > 0; j-- )
1479 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001480 break;
Gilles Peskine38a384d2021-06-17 14:35:25 +02001481 if( j == 0 )
Gilles Peskined65b5002021-06-15 21:44:32 +02001482 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1485 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001487 for( ; j > 0; j-- )
1488 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001490 /* If the result is 0, we don't shortcut the operation, which reduces
1491 * but does not eliminate side channels leaking the zero-ness. We do
1492 * need to take care to set the sign bit properly since the library does
1493 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskined65b5002021-06-15 21:44:32 +02001494 if( result_is_zero )
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001495 X->s = 1;
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001496 else
1497 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001498
1499cleanup:
1500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001502
1503 return( ret );
1504}
1505
1506/*
1507 * Baseline multiplication: X = A * b
1508 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001510{
Hanno Becker73d7d792018-12-11 10:35:51 +00001511 MPI_VALIDATE_RET( X != NULL );
1512 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001514 /* mpi_mul_hlp can't deal with a leading 0. */
1515 size_t n = A->n;
1516 while( n > 0 && A->p[n - 1] == 0 )
1517 --n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001518
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001519 /* The general method below doesn't work if n==0 or b==0. By chance
1520 * calculating the result is trivial in those cases. */
1521 if( b == 0 || n == 0 )
1522 {
Paul Elliott986b55a2021-04-20 21:46:29 +01001523 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001524 }
1525
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001526 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001527 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001528 /* In general, A * b requires 1 limb more than b. If
1529 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1530 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001531 * copy() will take care of the growth if needed. However, experimentally,
1532 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001533 * calls to calloc() in ECP code, presumably because it reuses the
1534 * same mpi for a while and this way the mpi is more likely to directly
1535 * grow to its final size. */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001536 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
1537 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1538 mpi_mul_hlp( n, A->p, X->p, b - 1 );
1539
1540cleanup:
1541 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001542}
1543
1544/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001545 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1546 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001547 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001548static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1549 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001550{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001551#if defined(MBEDTLS_HAVE_UDBL)
1552 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001553#else
Simon Butcher9803d072016-01-03 00:24:34 +00001554 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1555 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001556 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1557 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001558 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001559#endif
1560
Simon Butcher15b15d12015-11-26 19:35:03 +00001561 /*
1562 * Check for overflow
1563 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001564 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001565 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001566 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001567
Simon Butcherf5ba0452015-12-27 23:01:55 +00001568 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001569 }
1570
1571#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001572 dividend = (mbedtls_t_udbl) u1 << biL;
1573 dividend |= (mbedtls_t_udbl) u0;
1574 quotient = dividend / d;
1575 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1576 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1577
1578 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001579 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001580
1581 return (mbedtls_mpi_uint) quotient;
1582#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001583
1584 /*
1585 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1586 * Vol. 2 - Seminumerical Algorithms, Knuth
1587 */
1588
1589 /*
1590 * Normalize the divisor, d, and dividend, u0, u1
1591 */
1592 s = mbedtls_clz( d );
1593 d = d << s;
1594
1595 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001596 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001597 u0 = u0 << s;
1598
1599 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001600 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001601
1602 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001603 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001604
1605 /*
1606 * Find the first quotient and remainder
1607 */
1608 q1 = u1 / d1;
1609 r0 = u1 - d1 * q1;
1610
1611 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1612 {
1613 q1 -= 1;
1614 r0 += d1;
1615
1616 if ( r0 >= radix ) break;
1617 }
1618
Simon Butcherf5ba0452015-12-27 23:01:55 +00001619 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001620 q0 = rAX / d1;
1621 r0 = rAX - q0 * d1;
1622
1623 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1624 {
1625 q0 -= 1;
1626 r0 += d1;
1627
1628 if ( r0 >= radix ) break;
1629 }
1630
1631 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001632 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001633
1634 quotient = q1 * radix + q0;
1635
1636 return quotient;
1637#endif
1638}
1639
1640/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001642 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001643int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1644 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001645{
Janos Follath24eed8d2019-11-22 13:21:35 +00001646 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001647 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001649 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001650 MPI_VALIDATE_RET( A != NULL );
1651 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1654 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001656 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001657 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001658 /*
1659 * Avoid dynamic memory allocations for constant-size T2.
1660 *
1661 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1662 * so nobody increase the size of the MPI and we're safe to use an on-stack
1663 * buffer.
1664 */
Alexander K35d6d462019-10-31 14:46:45 +03001665 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001666 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1667 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1672 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673 return( 0 );
1674 }
1675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 X.s = Y.s = 1;
1679
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1681 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001682 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001684 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001685 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 {
1687 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 }
1691 else k = 0;
1692
1693 n = X.n - 1;
1694 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001695 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 {
1699 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001701 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
1704 for( i = n; i > t ; i-- )
1705 {
1706 if( X.p[i] >= Y.p[t] )
1707 Z.p[i - t - 1] = ~0;
1708 else
1709 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001710 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1711 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 }
1713
Alexander K35d6d462019-10-31 14:46:45 +03001714 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1715 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1716 T2.p[2] = X.p[i];
1717
Paul Bakker5121ce52009-01-03 21:22:43 +00001718 Z.p[i - t - 1]++;
1719 do
1720 {
1721 Z.p[i - t - 1]--;
1722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001724 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001725 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001726 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1731 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1732 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001735 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1737 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1738 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 Z.p[i - t - 1]--;
1740 }
1741 }
1742
1743 if( Q != NULL )
1744 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001746 Q->s = A->s * B->s;
1747 }
1748
1749 if( R != NULL )
1750 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001751 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001752 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 R->s = 1;
1757 }
1758
1759cleanup:
1760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001762 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001763 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001764
1765 return( ret );
1766}
1767
1768/*
1769 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001770 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001771int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1772 const mbedtls_mpi *A,
1773 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001774{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001775 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001777 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
1779 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001780 B.s = ( b < 0 ) ? -1 : 1;
1781 B.n = 1;
1782 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001783
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001784 return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785}
1786
1787/*
1788 * Modulo: R = A mod B
1789 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001791{
Janos Follath24eed8d2019-11-22 13:21:35 +00001792 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001793 MPI_VALIDATE_RET( R != NULL );
1794 MPI_VALIDATE_RET( A != NULL );
1795 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1798 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1803 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1806 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
1808cleanup:
1809
1810 return( ret );
1811}
1812
1813/*
1814 * Modulo: r = A mod b
1815 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001817{
Paul Bakker23986e52011-04-24 08:57:21 +00001818 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001820 MPI_VALIDATE_RET( r != NULL );
1821 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001822
1823 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
1826 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
1829 /*
1830 * handle trivial cases
1831 */
1832 if( b == 1 )
1833 {
1834 *r = 0;
1835 return( 0 );
1836 }
1837
1838 if( b == 2 )
1839 {
1840 *r = A->p[0] & 1;
1841 return( 0 );
1842 }
1843
1844 /*
1845 * general case
1846 */
Paul Bakker23986e52011-04-24 08:57:21 +00001847 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001848 {
Paul Bakker23986e52011-04-24 08:57:21 +00001849 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 y = ( y << biH ) | ( x >> biH );
1851 z = y / b;
1852 y -= z * b;
1853
1854 x <<= biH;
1855 y = ( y << biH ) | ( x >> biH );
1856 z = y / b;
1857 y -= z * b;
1858 }
1859
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001860 /*
1861 * If A is negative, then the current y represents a negative value.
1862 * Flipping it to the positive side.
1863 */
1864 if( A->s < 0 && y != 0 )
1865 y = b - y;
1866
Paul Bakker5121ce52009-01-03 21:22:43 +00001867 *r = y;
1868
1869 return( 0 );
1870}
1871
1872/*
1873 * Fast Montgomery initialization (thanks to Tom St Denis)
1874 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001876{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001878 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001879
1880 x = m0;
1881 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001883 for( i = biL; i >= 8; i /= 2 )
1884 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
1886 *mm = ~x + 1;
1887}
1888
Gilles Peskine2a82f722020-06-04 15:00:49 +02001889/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1890 *
1891 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02001892 * It must have at least as many limbs as N
1893 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02001894 * On successful completion, A contains the result of
1895 * the multiplication A * B * R^-1 mod N where
1896 * R = (2^ciL)^n.
1897 * \param[in] B One of the numbers to multiply.
1898 * It must be nonzero and must not have more limbs than N
1899 * (B->n <= N->n).
1900 * \param[in] N The modulo. N must be odd.
1901 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1902 * This is -N^-1 mod 2^ciL.
1903 * \param[in,out] T A bignum for temporary storage.
1904 * It must be at least twice the limb size of N plus 2
1905 * (T->n >= 2 * (N->n + 1)).
1906 * Its initial content is unused and
1907 * its final content is indeterminate.
1908 * Note that unlike the usual convention in the library
1909 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001910 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001911static 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 +02001912 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001913{
Paul Bakker23986e52011-04-24 08:57:21 +00001914 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001916
1917 memset( T->p, 0, T->n * ciL );
1918
1919 d = T->p;
1920 n = N->n;
1921 m = ( B->n < n ) ? B->n : n;
1922
1923 for( i = 0; i < n; i++ )
1924 {
1925 /*
1926 * T = (T + u0*B + u1*N) / 2^biL
1927 */
1928 u0 = A->p[i];
1929 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1930
1931 mpi_mul_hlp( m, B->p, d, u0 );
1932 mpi_mul_hlp( n, N->p, d, u1 );
1933
1934 *d++ = u0; d[n + 1] = 0;
1935 }
1936
Gilles Peskine221626f2020-06-08 22:37:50 +02001937 /* At this point, d is either the desired result or the desired result
1938 * plus N. We now potentially subtract N, avoiding leaking whether the
1939 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
Gilles Peskine221626f2020-06-08 22:37:50 +02001941 /* Copy the n least significant limbs of d to A, so that
1942 * A = d if d < N (recall that N has n limbs). */
1943 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001944 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02001945 * do the calculation without using conditional tests. */
1946 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02001947 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001948 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02001949 /* If d0 < N then d < (2^biL)^n
1950 * so d[n] == 0 and we want to keep A as it is.
1951 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
1952 * so d[n] == 1 and we want to set A to the result of the subtraction
1953 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
1954 * This exactly corresponds to a conditional assignment. */
Gabor Mezei18a44942021-10-20 11:59:27 +02001955 mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956}
1957
1958/*
1959 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001960 *
1961 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02001963static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1964 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001965{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 mbedtls_mpi_uint z = 1;
1967 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001968
Paul Bakker8ddb6452013-02-27 14:56:33 +01001969 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001970 U.p = &z;
1971
Gilles Peskine4e91d472020-06-04 20:55:15 +02001972 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973}
1974
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01001975/**
1976 * Select an MPI from a table without leaking the index.
1977 *
1978 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1979 * reads the entire table in order to avoid leaking the value of idx to an
1980 * attacker able to observe memory access patterns.
1981 *
1982 * \param[out] R Where to write the selected MPI.
1983 * \param[in] T The table to read from.
1984 * \param[in] T_size The number of elements in the table.
1985 * \param[in] idx The index of the element to select;
1986 * this must satisfy 0 <= idx < T_size.
1987 *
1988 * \return \c 0 on success, or a negative error code.
1989 */
1990static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
1991{
1992 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1993
1994 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02001995 {
1996 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
Gabor Mezei18a44942021-10-20 11:59:27 +02001997 (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02001998 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01001999
2000cleanup:
2001 return( ret );
2002}
2003
Paul Bakker5121ce52009-01-03 21:22:43 +00002004/*
2005 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2006 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002007int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2008 const mbedtls_mpi *E, const mbedtls_mpi *N,
Yuto Takano284857e2021-07-14 10:20:09 +01002009 mbedtls_mpi *prec_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002010{
Janos Follath24eed8d2019-11-22 13:21:35 +00002011 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002012 size_t wbits, wsize, one = 1;
2013 size_t i, j, nblimbs;
2014 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002016 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002017 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
Hanno Becker73d7d792018-12-11 10:35:51 +00002019 MPI_VALIDATE_RET( X != NULL );
2020 MPI_VALIDATE_RET( A != NULL );
2021 MPI_VALIDATE_RET( E != NULL );
2022 MPI_VALIDATE_RET( N != NULL );
2023
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002024 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2028 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002029
Chris Jones9246d042020-11-25 15:12:39 +00002030 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2031 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2032 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2033
Paul Bakkerf6198c12012-05-16 08:02:29 +00002034 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002035 * Init temps and window size
2036 */
2037 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2039 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002040 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002041 memset( W, 0, sizeof( W ) );
2042
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002043 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002044
2045 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2046 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2047
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002048#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2050 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002051#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002052
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 j = N->n + 1;
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002054 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2055 * and mpi_montred() calls later. Here we ensure that W[1] and X are
2056 * large enough, and later we'll grow other W[i] to the same length.
2057 * They must not be shrunk midway through this function!
2058 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2060 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2061 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062
2063 /*
Paul Bakker50546922012-05-19 08:40:49 +00002064 * Compensate for negative A (and correct at the end)
2065 */
2066 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002067 if( neg )
2068 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002070 Apos.s = 1;
2071 A = &Apos;
2072 }
2073
2074 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002075 * If 1st call, pre-compute R^2 mod N
2076 */
Yuto Takano284857e2021-07-14 10:20:09 +01002077 if( prec_RR == NULL || prec_RR->p == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00002078 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2080 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2081 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002082
Yuto Takano284857e2021-07-14 10:20:09 +01002083 if( prec_RR != NULL )
2084 memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002085 }
2086 else
Yuto Takano284857e2021-07-14 10:20:09 +01002087 memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002088
2089 /*
2090 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2091 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002093 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002095 /* This should be a no-op because W[1] is already that large before
2096 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2097 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine0759cad2021-06-15 21:22:48 +02002098 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002099 }
Paul Bakkerc2024f42014-01-23 20:38:35 +01002100 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002102
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002103 /* Note that this is safe because W[1] always has at least N->n limbs
2104 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002105 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
2107 /*
2108 * X = R^2 * R^-1 mod N = R mod N
2109 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002111 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
2113 if( wsize > 1 )
2114 {
2115 /*
2116 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2117 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002118 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2121 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
2123 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002124 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002125
Paul Bakker5121ce52009-01-03 21:22:43 +00002126 /*
2127 * W[i] = W[i - 1] * W[1]
2128 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002129 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002130 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002131 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2132 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
Gilles Peskine4e91d472020-06-04 20:55:15 +02002134 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002135 }
2136 }
2137
2138 nblimbs = E->n;
2139 bufsize = 0;
2140 nbits = 0;
2141 wbits = 0;
2142 state = 0;
2143
2144 while( 1 )
2145 {
2146 if( bufsize == 0 )
2147 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002148 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002149 break;
2150
Paul Bakker0d7702c2013-10-29 16:18:35 +01002151 nblimbs--;
2152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002154 }
2155
2156 bufsize--;
2157
2158 ei = (E->p[nblimbs] >> bufsize) & 1;
2159
2160 /*
2161 * skip leading 0s
2162 */
2163 if( ei == 0 && state == 0 )
2164 continue;
2165
2166 if( ei == 0 && state == 1 )
2167 {
2168 /*
2169 * out of window, square X
2170 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002171 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002172 continue;
2173 }
2174
2175 /*
2176 * add ei to current window
2177 */
2178 state = 2;
2179
2180 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002181 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002182
2183 if( nbits == wsize )
2184 {
2185 /*
2186 * X = X^wsize R^-1 mod N
2187 */
2188 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002189 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
2191 /*
2192 * X = X * W[wbits] R^-1 mod N
2193 */
Manuel Pégourié-Gonnard0b3bde52021-06-10 09:34:00 +02002194 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002195 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002196
2197 state--;
2198 nbits = 0;
2199 wbits = 0;
2200 }
2201 }
2202
2203 /*
2204 * process the remaining bits
2205 */
2206 for( i = 0; i < nbits; i++ )
2207 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002208 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002209
2210 wbits <<= 1;
2211
Paul Bakker66d5d072014-06-17 16:39:18 +02002212 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002213 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214 }
2215
2216 /*
2217 * X = A^E * R * R^-1 mod N = A^E mod N
2218 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002219 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220
Hanno Beckera4af1c42017-04-18 09:07:45 +01002221 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002222 {
2223 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002225 }
2226
Paul Bakker5121ce52009-01-03 21:22:43 +00002227cleanup:
2228
Paul Bakker66d5d072014-06-17 16:39:18 +02002229 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002233 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002234
Yuto Takano284857e2021-07-14 10:20:09 +01002235 if( prec_RR == NULL || prec_RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
2238 return( ret );
2239}
2240
Paul Bakker5121ce52009-01-03 21:22:43 +00002241/*
2242 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2243 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002245{
Janos Follath24eed8d2019-11-22 13:21:35 +00002246 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002247 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002248 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002249
Hanno Becker73d7d792018-12-11 10:35:51 +00002250 MPI_VALIDATE_RET( G != NULL );
2251 MPI_VALIDATE_RET( A != NULL );
2252 MPI_VALIDATE_RET( B != NULL );
2253
Alexander Ke8ad49f2019-08-16 16:16:07 +03002254 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2257 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 lz = mbedtls_mpi_lsb( &TA );
2260 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002261
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002262 /* The loop below gives the correct result when A==0 but not when B==0.
2263 * So have a special case for B==0. Leverage the fact that we just
2264 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2265 * slightly more efficient than cmp_int(). */
2266 if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2267 {
2268 ret = mbedtls_mpi_copy( G, A );
2269 goto cleanup;
2270 }
2271
Paul Bakker66d5d072014-06-17 16:39:18 +02002272 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002273 lz = lzt;
2274
Paul Bakker5121ce52009-01-03 21:22:43 +00002275 TA.s = TB.s = 1;
2276
Gilles Peskineea9aa142021-06-16 13:42:04 +02002277 /* We mostly follow the procedure described in HAC 14.54, but with some
2278 * minor differences:
2279 * - Sequences of multiplications or divisions by 2 are grouped into a
2280 * single shift operation.
Gilles Peskine37d690c2021-06-21 18:58:39 +02002281 * - The procedure in HAC assumes that 0 < TB <= TA.
2282 * - The condition TB <= TA is not actually necessary for correctness.
2283 * TA and TB have symmetric roles except for the loop termination
2284 * condition, and the shifts at the beginning of the loop body
2285 * remove any significance from the ordering of TA vs TB before
2286 * the shifts.
2287 * - If TA = 0, the loop goes through 0 iterations and the result is
2288 * correctly TB.
2289 * - The case TB = 0 was short-circuited above.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002290 *
2291 * For the correctness proof below, decompose the original values of
2292 * A and B as
2293 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2294 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2295 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2296 * and gcd(A',B') is odd or 0.
2297 *
2298 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2299 * The code maintains the following invariant:
2300 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine6537bdb2021-06-15 22:09:39 +02002301 */
2302
Gilles Peskineea9aa142021-06-16 13:42:04 +02002303 /* Proof that the loop terminates:
2304 * At each iteration, either the right-shift by 1 is made on a nonzero
2305 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2306 * by at least 1, or the right-shift by 1 is made on zero and then
2307 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2308 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2309 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002311 {
Gilles Peskineea9aa142021-06-16 13:42:04 +02002312 /* Divisions by 2 preserve the invariant (I). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2314 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
Gilles Peskineea9aa142021-06-16 13:42:04 +02002316 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2317 * TA-TB is even so the division by 2 has an integer result.
2318 * Invariant (I) is preserved since any odd divisor of both TA and TB
2319 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2320 * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
2321 * divides TA.
2322 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2326 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 }
2328 else
2329 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2331 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 }
Gilles Peskineea9aa142021-06-16 13:42:04 +02002333 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002334 }
2335
Gilles Peskineea9aa142021-06-16 13:42:04 +02002336 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2337 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2338 * - If there was at least one loop iteration, then one of TA or TB is odd,
2339 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2340 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2341 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskineb798b352021-06-21 11:40:38 +02002342 * 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 +02002343 */
2344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2346 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002347
2348cleanup:
2349
Alexander Ke8ad49f2019-08-16 16:16:07 +03002350 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
2352 return( ret );
2353}
2354
Gilles Peskine8f454702021-04-01 15:57:18 +02002355/* Fill X with n_bytes random bytes.
2356 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002357 * The ordering of the bytes returned from the RNG is suitable for
2358 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002359 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002360 * n_bytes must not be 0.
2361 */
2362static int mpi_fill_random_internal(
2363 mbedtls_mpi *X, size_t n_bytes,
2364 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2365{
2366 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2367 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2368 const size_t overhead = ( limbs * ciL ) - n_bytes;
2369
2370 if( X->n < limbs )
2371 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine8f454702021-04-01 15:57:18 +02002372
Gilles Peskinea16001e2021-04-13 21:55:35 +02002373 memset( X->p, 0, overhead );
2374 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine8f454702021-04-01 15:57:18 +02002375 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2376 mpi_bigendian_to_host( X->p, limbs );
2377
2378cleanup:
2379 return( ret );
2380}
2381
Paul Bakker33dc46b2014-04-30 16:11:39 +02002382/*
2383 * Fill X with size bytes of random.
2384 *
2385 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002386 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002387 * deterministic, eg for tests).
2388 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002390 int (*f_rng)(void *, unsigned char *, size_t),
2391 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002392{
Janos Follath24eed8d2019-11-22 13:21:35 +00002393 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002394 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002395
Hanno Becker8ce11a32018-12-19 16:18:52 +00002396 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002397 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002398
Hanno Beckerda1655a2017-10-18 14:21:44 +01002399 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002400 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002401 if( size == 0 )
2402 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002403
Gilles Peskine8f454702021-04-01 15:57:18 +02002404 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002405
2406cleanup:
2407 return( ret );
2408}
2409
Gilles Peskine4699fa42021-03-29 22:02:55 +02002410int mbedtls_mpi_random( mbedtls_mpi *X,
2411 mbedtls_mpi_sint min,
2412 const mbedtls_mpi *N,
2413 int (*f_rng)(void *, unsigned char *, size_t),
2414 void *p_rng )
2415{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002416 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002417 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002418 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002419 size_t n_bits = mbedtls_mpi_bitlen( N );
2420 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002421 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002422
Gilles Peskine9312ba52021-03-29 22:14:51 +02002423 if( min < 0 )
2424 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2425 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2426 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2427
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002428 /*
2429 * When min == 0, each try has at worst a probability 1/2 of failing
2430 * (the msb has a probability 1/2 of being 0, and then the result will
2431 * be < N), so after 30 tries failure probability is a most 2**(-30).
2432 *
2433 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002434 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002435 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002436 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002437 * a probability of failing that is almost 1/2.
2438 *
2439 * The probabilities are almost the same if min is nonzero but negligible
2440 * compared to N. This is always the case when N is crypto-sized, but
2441 * it's convenient to support small N for testing purposes. When N
2442 * is small, use a higher repeat count, otherwise the probability of
2443 * failure is macroscopic.
2444 */
Gilles Peskine11779072021-06-02 21:18:59 +02002445 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002446
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002447 mbedtls_mpi_init( &lower_bound );
2448
Gilles Peskine8f454702021-04-01 15:57:18 +02002449 /* Ensure that target MPI has exactly the same number of limbs
2450 * as the upper bound, even if the upper bound has leading zeros.
2451 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002452 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002453 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2454 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002455
Gilles Peskine4699fa42021-03-29 22:02:55 +02002456 /*
2457 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2458 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2459 * - use the same byte ordering;
2460 * - keep the leftmost n_bits bits of the generated octet string;
2461 * - try until result is in the desired range.
2462 * This also avoids any bias, which is especially important for ECDSA.
2463 */
2464 do
2465 {
Gilles Peskine8f454702021-04-01 15:57:18 +02002466 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002467 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2468
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002469 if( --count == 0 )
Gilles Peskine4699fa42021-03-29 22:02:55 +02002470 {
2471 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2472 goto cleanup;
2473 }
2474
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002475 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2476 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002477 }
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002478 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002479
2480cleanup:
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002481 mbedtls_mpi_free( &lower_bound );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002482 return( ret );
2483}
2484
Paul Bakker5121ce52009-01-03 21:22:43 +00002485/*
2486 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2487 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002489{
Janos Follath24eed8d2019-11-22 13:21:35 +00002490 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002491 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002492 MPI_VALIDATE_RET( X != NULL );
2493 MPI_VALIDATE_RET( A != NULL );
2494 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002495
Hanno Becker4bcb4912017-04-18 15:49:39 +01002496 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2500 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2501 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002506 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002508 goto cleanup;
2509 }
2510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2512 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2513 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2514 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002516 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2517 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2518 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2519 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002520
2521 do
2522 {
2523 while( ( TU.p[0] & 1 ) == 0 )
2524 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002526
2527 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2528 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2530 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002531 }
2532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2534 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002535 }
2536
2537 while( ( TV.p[0] & 1 ) == 0 )
2538 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002539 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002540
2541 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2542 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2544 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002545 }
2546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2548 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002549 }
2550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002551 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002552 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002553 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2554 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2555 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002556 }
2557 else
2558 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2560 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2561 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002562 }
2563 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2567 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2570 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002571
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002573
2574cleanup:
2575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2577 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2578 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002579
2580 return( ret );
2581}
2582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002583#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002584
Paul Bakker5121ce52009-01-03 21:22:43 +00002585static const int small_prime[] =
2586{
2587 3, 5, 7, 11, 13, 17, 19, 23,
2588 29, 31, 37, 41, 43, 47, 53, 59,
2589 61, 67, 71, 73, 79, 83, 89, 97,
2590 101, 103, 107, 109, 113, 127, 131, 137,
2591 139, 149, 151, 157, 163, 167, 173, 179,
2592 181, 191, 193, 197, 199, 211, 223, 227,
2593 229, 233, 239, 241, 251, 257, 263, 269,
2594 271, 277, 281, 283, 293, 307, 311, 313,
2595 317, 331, 337, 347, 349, 353, 359, 367,
2596 373, 379, 383, 389, 397, 401, 409, 419,
2597 421, 431, 433, 439, 443, 449, 457, 461,
2598 463, 467, 479, 487, 491, 499, 503, 509,
2599 521, 523, 541, 547, 557, 563, 569, 571,
2600 577, 587, 593, 599, 601, 607, 613, 617,
2601 619, 631, 641, 643, 647, 653, 659, 661,
2602 673, 677, 683, 691, 701, 709, 719, 727,
2603 733, 739, 743, 751, 757, 761, 769, 773,
2604 787, 797, 809, 811, 821, 823, 827, 829,
2605 839, 853, 857, 859, 863, 877, 881, 883,
2606 887, 907, 911, 919, 929, 937, 941, 947,
2607 953, 967, 971, 977, 983, 991, 997, -103
2608};
2609
2610/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002611 * Small divisors test (X must be positive)
2612 *
2613 * Return values:
2614 * 0: no small factor (possible prime, more tests needed)
2615 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002616 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002617 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002618 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002620{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002621 int ret = 0;
2622 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002623 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002624
Paul Bakker5121ce52009-01-03 21:22:43 +00002625 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002627
2628 for( i = 0; small_prime[i] > 0; i++ )
2629 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002631 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002632
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002633 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002634
2635 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002636 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002637 }
2638
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002639cleanup:
2640 return( ret );
2641}
2642
2643/*
2644 * Miller-Rabin pseudo-primality test (HAC 4.24)
2645 */
Janos Follathda31fa12018-09-03 14:45:23 +01002646static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002647 int (*f_rng)(void *, unsigned char *, size_t),
2648 void *p_rng )
2649{
Pascal Junodb99183d2015-03-11 16:49:45 +01002650 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002651 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002652 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002653
Hanno Becker8ce11a32018-12-19 16:18:52 +00002654 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002655 MPI_VALIDATE_RET( f_rng != NULL );
2656
2657 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2658 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002659 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002660
Paul Bakker5121ce52009-01-03 21:22:43 +00002661 /*
2662 * W = |X| - 1
2663 * R = W >> lsb( W )
2664 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2666 s = mbedtls_mpi_lsb( &W );
2667 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2668 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002669
Janos Follathda31fa12018-09-03 14:45:23 +01002670 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002671 {
2672 /*
2673 * pick a random A, 1 < A < |X| - 1
2674 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002675 count = 0;
2676 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002677 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002678
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002679 j = mbedtls_mpi_bitlen( &A );
2680 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002681 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002682 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002683 }
2684
2685 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002686 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2687 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002688 }
2689
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002690 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2691 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002692
2693 /*
2694 * A = A^R mod |X|
2695 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002696 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2699 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002700 continue;
2701
2702 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002703 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002704 {
2705 /*
2706 * A = A * A mod |X|
2707 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2709 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002712 break;
2713
2714 j++;
2715 }
2716
2717 /*
2718 * not prime if A != |X| - 1 or A == 1
2719 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002720 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2721 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002723 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002724 break;
2725 }
2726 }
2727
2728cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002729 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2730 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002732
2733 return( ret );
2734}
2735
2736/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002737 * Pseudo-primality test: small factors, then Miller-Rabin
2738 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002739int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2740 int (*f_rng)(void *, unsigned char *, size_t),
2741 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002742{
Janos Follath24eed8d2019-11-22 13:21:35 +00002743 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002745 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002746 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002747
2748 XX.s = 1;
2749 XX.n = X->n;
2750 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002751
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2753 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2754 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002757 return( 0 );
2758
2759 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2760 {
2761 if( ret == 1 )
2762 return( 0 );
2763
2764 return( ret );
2765 }
2766
Janos Follathda31fa12018-09-03 14:45:23 +01002767 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002768}
2769
Janos Follatha0b67c22018-09-18 14:48:23 +01002770#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002771/*
2772 * Pseudo-primality test, error probability 2^-80
2773 */
2774int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2775 int (*f_rng)(void *, unsigned char *, size_t),
2776 void *p_rng )
2777{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002778 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002779 MPI_VALIDATE_RET( f_rng != NULL );
2780
Janos Follatha0b67c22018-09-18 14:48:23 +01002781 /*
2782 * In the past our key generation aimed for an error rate of at most
2783 * 2^-80. Since this function is deprecated, aim for the same certainty
2784 * here as well.
2785 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002786 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002787}
Janos Follatha0b67c22018-09-18 14:48:23 +01002788#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002789
2790/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002791 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002792 *
Janos Follathf301d232018-08-14 13:34:01 +01002793 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2794 * be either 1024 bits or 1536 bits long, and flags must contain
2795 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002796 */
Janos Follath7c025a92018-08-14 11:08:41 +01002797int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002798 int (*f_rng)(void *, unsigned char *, size_t),
2799 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002800{
Jethro Beekman66689272018-02-14 19:24:10 -08002801#ifdef MBEDTLS_HAVE_INT64
2802// ceil(2^63.5)
2803#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2804#else
2805// ceil(2^31.5)
2806#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2807#endif
2808 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002809 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002810 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811 mbedtls_mpi_uint r;
2812 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002813
Hanno Becker8ce11a32018-12-19 16:18:52 +00002814 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002815 MPI_VALIDATE_RET( f_rng != NULL );
2816
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2818 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002819
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002820 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002821
2822 n = BITS_TO_LIMBS( nbits );
2823
Janos Follathda31fa12018-09-03 14:45:23 +01002824 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2825 {
2826 /*
2827 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2828 */
2829 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2830 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2831 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2832 }
2833 else
2834 {
2835 /*
2836 * 2^-100 error probability, number of rounds computed based on HAC,
2837 * fact 4.48
2838 */
2839 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2840 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2841 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2842 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2843 }
2844
Jethro Beekman66689272018-02-14 19:24:10 -08002845 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002846 {
Jethro Beekman66689272018-02-14 19:24:10 -08002847 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2848 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2849 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2850
2851 k = n * biL;
2852 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2853 X->p[0] |= 1;
2854
Janos Follath7c025a92018-08-14 11:08:41 +01002855 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002856 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002857 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002859 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002860 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002861 }
Jethro Beekman66689272018-02-14 19:24:10 -08002862 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002863 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002864 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002865 * An necessary condition for Y and X = 2Y + 1 to be prime
2866 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2867 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002868 */
Jethro Beekman66689272018-02-14 19:24:10 -08002869
2870 X->p[0] |= 2;
2871
2872 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2873 if( r == 0 )
2874 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2875 else if( r == 1 )
2876 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2877
2878 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2879 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2880 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2881
2882 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002883 {
Jethro Beekman66689272018-02-14 19:24:10 -08002884 /*
2885 * First, check small factors for X and Y
2886 * before doing Miller-Rabin on any of them
2887 */
2888 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2889 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002890 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002891 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002892 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002893 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002894 goto cleanup;
2895
2896 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2897 goto cleanup;
2898
2899 /*
2900 * Next candidates. We want to preserve Y = (X-1) / 2 and
2901 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2902 * so up Y by 6 and X by 12.
2903 */
2904 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2905 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002906 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002907 }
2908 }
2909
2910cleanup:
2911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002912 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002913
2914 return( ret );
2915}
2916
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002917#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002918
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002919#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002920
Paul Bakker23986e52011-04-24 08:57:21 +00002921#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002922
2923static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2924{
2925 { 693, 609, 21 },
2926 { 1764, 868, 28 },
2927 { 768454923, 542167814, 1 }
2928};
2929
Paul Bakker5121ce52009-01-03 21:22:43 +00002930/*
2931 * Checkup routine
2932 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002933int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002934{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002935 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002936 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002938 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2939 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002941 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002942 "EFE021C2645FD1DC586E69184AF4A31E" \
2943 "D5F53E93B5F123FA41680867BA110131" \
2944 "944FE7952E2517337780CB0DB80E61AA" \
2945 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2946
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002947 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002948 "B2E7EFD37075B9F03FF989C7C5051C20" \
2949 "34D2A323810251127E7BF8625A4F49A5" \
2950 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2951 "5B5C25763222FEFCCFC38B832366C29E" ) );
2952
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002953 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002954 "0066A198186C18C10B2F5ED9B522752A" \
2955 "9830B69916E535C8F047518A889A43A5" \
2956 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002958 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002960 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002961 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2962 "9E857EA95A03512E2BAE7391688D264A" \
2963 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2964 "8001B72E848A38CAE1C65F78E56ABDEF" \
2965 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2966 "ECF677152EF804370C1A305CAF3B5BF1" \
2967 "30879B56C61DE584A0F53A2447A51E" ) );
2968
2969 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002970 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002972 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002973 {
2974 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002975 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002976
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002977 ret = 1;
2978 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002979 }
2980
2981 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002982 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002983
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002984 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002985
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002986 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002987 "256567336059E52CAE22925474705F39A94" ) );
2988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002989 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002990 "6613F26162223DF488E9CD48CC132C7A" \
2991 "0AC93C701B001B092E4E5B9F73BCD27B" \
2992 "9EE50D0657C77F374E903CDFA4C642" ) );
2993
2994 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002995 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002996
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002997 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2998 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002999 {
3000 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003001 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003002
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003003 ret = 1;
3004 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003005 }
3006
3007 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003008 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003010 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003011
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003012 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003013 "36E139AEA55215609D2816998ED020BB" \
3014 "BD96C37890F65171D948E9BC7CBAA4D9" \
3015 "325D24D6A3C12710F10A09FA08AB87" ) );
3016
3017 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003018 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003020 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003021 {
3022 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003023 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003024
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003025 ret = 1;
3026 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003027 }
3028
3029 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003030 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003032 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003034 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003035 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3036 "C3DBA76456363A10869622EAC2DD84EC" \
3037 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3038
3039 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003040 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003042 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003043 {
3044 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003045 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003046
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003047 ret = 1;
3048 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003049 }
3050
3051 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003052 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003053
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003054 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003055 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003056
Paul Bakker66d5d072014-06-17 16:39:18 +02003057 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003058 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003059 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3060 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003061
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003062 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003063
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003064 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003065 {
3066 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003067 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003068
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003069 ret = 1;
3070 goto cleanup;
3071 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003072 }
3073
3074 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003075 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003076
Paul Bakker5121ce52009-01-03 21:22:43 +00003077cleanup:
3078
3079 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003080 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003082 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3083 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003084
3085 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003086 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003087
3088 return( ret );
3089}
3090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003091#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003093#endif /* MBEDTLS_BIGNUM_C */