blob: 81941479062f40678b77d34439a03c7abe357c53 [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"
Paul Bakker5121ce52009-01-03 21:22:43 +000044
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <string.h>
46
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000048#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020049#else
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <stdio.h>
51#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020053#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020055#endif
56
Hanno Becker73d7d792018-12-11 10:35:51 +000057#define MPI_VALIDATE_RET( cond ) \
58 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
59#define MPI_VALIDATE( cond ) \
60 MBEDTLS_INTERNAL_VALIDATE( cond )
61
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000063#define biL (ciL << 3) /* bits in limb */
64#define biH (ciL << 2) /* half limb size */
65
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010066#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
67
Paul Bakker5121ce52009-01-03 21:22:43 +000068/*
69 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020070 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000071 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020072#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
73#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000074
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050075/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050076static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
77{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050078 mbedtls_platform_zeroize( v, ciL * n );
79}
80
Paul Bakker5121ce52009-01-03 21:22:43 +000081/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000083 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000085{
Hanno Becker73d7d792018-12-11 10:35:51 +000086 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000087
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 X->s = 1;
89 X->n = 0;
90 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000091}
92
93/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000094 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 if( X == NULL )
99 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200103 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 }
106
Paul Bakker6c591fa2011-05-05 11:49:20 +0000107 X->s = 1;
108 X->n = 0;
109 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000110}
111
112/*
113 * Enlarge to the specified number of limbs
114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000116{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000118 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200121 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000122
Paul Bakker5121ce52009-01-03 21:22:43 +0000123 if( X->n < nblimbs )
124 {
Simon Butcher29176892016-05-20 00:19:09 +0100125 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->p != NULL )
129 {
130 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200131 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 }
134
135 X->n = nblimbs;
136 X->p = p;
137 }
138
139 return( 0 );
140}
141
142/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143 * Resize down as much as possible,
144 * while keeping at least the specified number of limbs
145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000150 MPI_VALIDATE_RET( X != NULL );
151
152 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
153 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100155 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100156 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100158 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 for( i = X->n - 1; i > 0; i-- )
161 if( X->p[i] != 0 )
162 break;
163 i++;
164
165 if( i < nblimbs )
166 i = nblimbs;
167
Simon Butcher29176892016-05-20 00:19:09 +0100168 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200169 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171 if( X->p != NULL )
172 {
173 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200174 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100176 }
177
178 X->n = i;
179 X->p = p;
180
181 return( 0 );
182}
183
Gilles Peskine3130ce22021-06-02 22:17:52 +0200184/* Resize X to have exactly n limbs and set it to 0. */
185static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
186{
187 if( limbs == 0 )
188 {
189 mbedtls_mpi_free( X );
190 return( 0 );
191 }
192 else if( X->n == limbs )
193 {
194 memset( X->p, 0, limbs * ciL );
195 X->s = 1;
196 return( 0 );
197 }
198 else
199 {
200 mbedtls_mpi_free( X );
201 return( mbedtls_mpi_grow( X, limbs ) );
202 }
203}
204
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100205/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000206 * Copy the contents of Y into X
207 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000209{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100210 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000211 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000212 MPI_VALIDATE_RET( X != NULL );
213 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
215 if( X == Y )
216 return( 0 );
217
Gilles Peskinedb420622020-01-20 21:12:50 +0100218 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200219 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200221 return( 0 );
222 }
223
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 for( i = Y->n - 1; i > 0; i-- )
225 if( Y->p[i] != 0 )
226 break;
227 i++;
228
229 X->s = Y->s;
230
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100231 if( X->n < i )
232 {
233 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
234 }
235 else
236 {
237 memset( X->p + i, 0, ( X->n - i ) * ciL );
238 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
Paul Bakker5121ce52009-01-03 21:22:43 +0000240 memcpy( X->p, Y->p, i * ciL );
241
242cleanup:
243
244 return( ret );
245}
246
247/*
248 * Swap the contents of X and Y
249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000251{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE( X != NULL );
254 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 memcpy( &T, X, sizeof( mbedtls_mpi ) );
257 memcpy( X, Y, sizeof( mbedtls_mpi ) );
258 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000259}
260
261/*
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200262 * Conditionally assign dest = src, without leaking information
263 * about whether the assignment was made or not.
264 * dest and src must be arrays of limbs of size n.
265 * assign must be 0 or 1.
266 */
267static void mpi_safe_cond_assign( size_t n,
268 mbedtls_mpi_uint *dest,
269 const mbedtls_mpi_uint *src,
270 unsigned char assign )
271{
272 size_t i;
273 for( i = 0; i < n; i++ )
274 dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
275}
276
277/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100278 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100279 * about whether the assignment was made or not.
280 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100281 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100283{
284 int ret = 0;
285 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000286 MPI_VALIDATE_RET( X != NULL );
287 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100288
Pascal Junodb99183d2015-03-11 16:49:45 +0100289 /* make sure assign is 0 or 1 in a time-constant manner */
290 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100293
Paul Bakker66d5d072014-06-17 16:39:18 +0200294 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200296 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100297
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200298 for( i = Y->n; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200299 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100300
301cleanup:
302 return( ret );
303}
304
305/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 * Conditionally swap X and Y, without leaking information
307 * about whether the swap was made or not.
308 * Here it is not ok to simply swap the pointers, which whould lead to
309 * different memory access patterns when X and Y are used afterwards.
310 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200311int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100312{
313 int ret, s;
314 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000316 MPI_VALIDATE_RET( X != NULL );
317 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100318
319 if( X == Y )
320 return( 0 );
321
Pascal Junodb99183d2015-03-11 16:49:45 +0100322 /* make sure swap is 0 or 1 in a time-constant manner */
323 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200325 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
326 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100327
328 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200329 X->s = X->s * ( 1 - swap ) + Y->s * swap;
330 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100331
332
333 for( i = 0; i < X->n; i++ )
334 {
335 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200336 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
337 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100338 }
339
340cleanup:
341 return( ret );
342}
343
344/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000345 * Set value from integer
346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348{
Janos Follath24eed8d2019-11-22 13:21:35 +0000349 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000350 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 memset( X->p, 0, X->n * ciL );
354
355 X->p[0] = ( z < 0 ) ? -z : z;
356 X->s = ( z < 0 ) ? -1 : 1;
357
358cleanup:
359
360 return( ret );
361}
362
363/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000364 * Get a specific bit
365 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367{
Hanno Becker73d7d792018-12-11 10:35:51 +0000368 MPI_VALIDATE_RET( X != NULL );
369
Paul Bakker2f5947e2011-05-18 15:47:11 +0000370 if( X->n * biL <= pos )
371 return( 0 );
372
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200373 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374}
375
Gilles Peskine11cdb052018-11-20 16:47:47 +0100376/* Get a specific byte, without range checks. */
377#define GET_BYTE( X, i ) \
378 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
379
Paul Bakker2f5947e2011-05-18 15:47:11 +0000380/*
381 * Set a bit to a specific value of 0 or 1
382 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000384{
385 int ret = 0;
386 size_t off = pos / biL;
387 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000388 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000389
390 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200392
Paul Bakker2f5947e2011-05-18 15:47:11 +0000393 if( X->n * biL <= pos )
394 {
395 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200396 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000397
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000399 }
400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
402 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000403
404cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200405
Paul Bakker2f5947e2011-05-18 15:47:11 +0000406 return( ret );
407}
408
409/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200410 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000411 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000413{
Paul Bakker23986e52011-04-24 08:57:21 +0000414 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000415 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000416
417 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000418 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000419 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
420 return( count );
421
422 return( 0 );
423}
424
425/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000426 * Count leading zero bits in a given integer
427 */
428static size_t mbedtls_clz( const mbedtls_mpi_uint x )
429{
430 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100431 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000432
433 for( j = 0; j < biL; j++ )
434 {
435 if( x & mask ) break;
436
437 mask >>= 1;
438 }
439
440 return j;
441}
442
443/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200444 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200446size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000447{
Paul Bakker23986e52011-04-24 08:57:21 +0000448 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200450 if( X->n == 0 )
451 return( 0 );
452
Paul Bakker5121ce52009-01-03 21:22:43 +0000453 for( i = X->n - 1; i > 0; i-- )
454 if( X->p[i] != 0 )
455 break;
456
Simon Butcher15b15d12015-11-26 19:35:03 +0000457 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Paul Bakker23986e52011-04-24 08:57:21 +0000459 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000460}
461
462/*
463 * Return the total size in bytes
464 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000466{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200467 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468}
469
470/*
471 * Convert an ASCII character to digit value
472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000474{
475 *d = 255;
476
477 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
478 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
479 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 if( *d >= (mbedtls_mpi_uint) radix )
482 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
484 return( 0 );
485}
486
487/*
488 * Import from an ASCII string
489 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000491{
Janos Follath24eed8d2019-11-22 13:21:35 +0000492 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000493 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200494 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 mbedtls_mpi_uint d;
496 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000497 MPI_VALIDATE_RET( X != NULL );
498 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
500 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000501 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000504
Gilles Peskine80f56732021-04-03 18:26:13 +0200505 if( s[0] == '-' )
506 {
507 ++s;
508 sign = -1;
509 }
510
Paul Bakkerff60ee62010-03-16 21:09:09 +0000511 slen = strlen( s );
512
Paul Bakker5121ce52009-01-03 21:22:43 +0000513 if( radix == 16 )
514 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100515 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200516 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
517
Paul Bakkerff60ee62010-03-16 21:09:09 +0000518 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
521 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
Paul Bakker23986e52011-04-24 08:57:21 +0000523 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000524 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200526 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000527 }
528 }
529 else
530 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
Paul Bakkerff60ee62010-03-16 21:09:09 +0000533 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
536 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine80f56732021-04-03 18:26:13 +0200537 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000538 }
539 }
540
Gilles Peskine80f56732021-04-03 18:26:13 +0200541 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
542 X->s = -1;
543
Paul Bakker5121ce52009-01-03 21:22:43 +0000544cleanup:
545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
548 return( ret );
549}
550
551/*
Ron Eldora16fa292018-11-20 14:07:01 +0200552 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000553 */
Ron Eldora16fa292018-11-20 14:07:01 +0200554static int mpi_write_hlp( mbedtls_mpi *X, int radix,
555 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000556{
Janos Follath24eed8d2019-11-22 13:21:35 +0000557 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200559 size_t length = 0;
560 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
Ron Eldora16fa292018-11-20 14:07:01 +0200562 do
563 {
564 if( length >= buflen )
565 {
566 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
567 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000568
Ron Eldora16fa292018-11-20 14:07:01 +0200569 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
570 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
571 /*
572 * Write the residue in the current position, as an ASCII character.
573 */
574 if( r < 0xA )
575 *(--p_end) = (char)( '0' + r );
576 else
577 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000578
Ron Eldora16fa292018-11-20 14:07:01 +0200579 length++;
580 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
Ron Eldora16fa292018-11-20 14:07:01 +0200582 memmove( *p, p_end, length );
583 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
585cleanup:
586
587 return( ret );
588}
589
590/*
591 * Export into an ASCII string
592 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100593int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
594 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000595{
Paul Bakker23986e52011-04-24 08:57:21 +0000596 int ret = 0;
597 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000598 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000600 MPI_VALIDATE_RET( X != NULL );
601 MPI_VALIDATE_RET( olen != NULL );
602 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603
604 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000605 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000606
Hanno Becker23cfea02019-02-04 09:45:07 +0000607 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
608 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
609 * `n`. If radix > 4, this might be a strict
610 * overapproximation of the number of
611 * radix-adic digits needed to present `n`. */
612 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
613 * present `n`. */
614
Janos Follath80470622019-03-06 13:43:02 +0000615 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000616 n += 1; /* Compensate for the divisions above, which round down `n`
617 * in case it's not even. */
618 n += 1; /* Potential '-'-sign. */
619 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
620 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100622 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100624 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000626 }
627
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100628 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
631 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000632 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000634 buflen--;
635 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000636
637 if( radix == 16 )
638 {
Paul Bakker23986e52011-04-24 08:57:21 +0000639 int c;
640 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
Paul Bakker23986e52011-04-24 08:57:21 +0000642 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 {
Paul Bakker23986e52011-04-24 08:57:21 +0000644 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000645 {
Paul Bakker23986e52011-04-24 08:57:21 +0000646 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
Paul Bakker6c343d72014-07-10 14:36:19 +0200648 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000649 continue;
650
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000651 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000652 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000653 k = 1;
654 }
655 }
656 }
657 else
658 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000660
661 if( T.s == -1 )
662 T.s = 1;
663
Ron Eldora16fa292018-11-20 14:07:01 +0200664 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000665 }
666
667 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100668 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
670cleanup:
671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673
674 return( ret );
675}
676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000678/*
679 * Read X from an opened file
680 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000682{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000684 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000685 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000686 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000687 * Buffer should have space for (short) label and decimal formatted MPI,
688 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
Hanno Becker73d7d792018-12-11 10:35:51 +0000692 MPI_VALIDATE_RET( X != NULL );
693 MPI_VALIDATE_RET( fin != NULL );
694
695 if( radix < 2 || radix > 16 )
696 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
697
Paul Bakker5121ce52009-01-03 21:22:43 +0000698 memset( s, 0, sizeof( s ) );
699 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000701
702 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000703 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000705
Hanno Beckerb2034b72017-04-26 11:46:46 +0100706 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
707 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
709 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100710 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711 if( mpi_get_digit( &d, radix, *p ) != 0 )
712 break;
713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000715}
716
717/*
718 * Write X into an opened file (or stdout if fout == NULL)
719 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000721{
Janos Follath24eed8d2019-11-22 13:21:35 +0000722 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000723 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000724 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000725 * Buffer should have space for (short) label and decimal formatted MPI,
726 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000727 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000729 MPI_VALIDATE_RET( X != NULL );
730
731 if( radix < 2 || radix > 16 )
732 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100734 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100736 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
738 if( p == NULL ) p = "";
739
740 plen = strlen( p );
741 slen = strlen( s );
742 s[slen++] = '\r';
743 s[slen++] = '\n';
744
745 if( fout != NULL )
746 {
747 if( fwrite( p, 1, plen, fout ) != plen ||
748 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000750 }
751 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000753
754cleanup:
755
756 return( ret );
757}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200758#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
Hanno Beckerda1655a2017-10-18 14:21:44 +0100760
761/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
762 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000763
764static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
765{
766 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100767 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000768 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100769
770 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
771 {
772 tmp <<= CHAR_BIT;
773 tmp |= (mbedtls_mpi_uint) *x_ptr;
774 }
775
Hanno Beckerf8720072018-11-08 11:53:49 +0000776 return( tmp );
777}
778
779static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
780{
781#if defined(__BYTE_ORDER__)
782
783/* Nothing to do on bigendian systems. */
784#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
785 return( x );
786#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
787
788#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
789
790/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000791#if defined(__GNUC__) && defined(__GNUC_PREREQ)
792#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000793#define have_bswap
794#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000795#endif
796
797#if defined(__clang__) && defined(__has_builtin)
798#if __has_builtin(__builtin_bswap32) && \
799 __has_builtin(__builtin_bswap64)
800#define have_bswap
801#endif
802#endif
803
Hanno Beckerf8720072018-11-08 11:53:49 +0000804#if defined(have_bswap)
805 /* The compiler is hopefully able to statically evaluate this! */
806 switch( sizeof(mbedtls_mpi_uint) )
807 {
808 case 4:
809 return( __builtin_bswap32(x) );
810 case 8:
811 return( __builtin_bswap64(x) );
812 }
813#endif
814#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
815#endif /* __BYTE_ORDER__ */
816
817 /* Fall back to C-based reordering if we don't know the byte order
818 * or we couldn't use a compiler-specific builtin. */
819 return( mpi_uint_bigendian_to_host_c( x ) );
820}
821
Hanno Becker2be8a552018-10-25 12:40:09 +0100822static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100823{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100824 mbedtls_mpi_uint *cur_limb_left;
825 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100826 if( limbs == 0 )
827 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100828
829 /*
830 * Traverse limbs and
831 * - adapt byte-order in each limb
832 * - swap the limbs themselves.
833 * For that, simultaneously traverse the limbs from left to right
834 * and from right to left, as long as the left index is not bigger
835 * than the right index (it's not a problem if limbs is odd and the
836 * indices coincide in the last iteration).
837 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100838 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
839 cur_limb_left <= cur_limb_right;
840 cur_limb_left++, cur_limb_right-- )
841 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000842 mbedtls_mpi_uint tmp;
843 /* Note that if cur_limb_left == cur_limb_right,
844 * this code effectively swaps the bytes only once. */
845 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
846 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
847 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100848 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100849}
850
Paul Bakker5121ce52009-01-03 21:22:43 +0000851/*
Janos Follatha778a942019-02-13 10:28:28 +0000852 * Import X from unsigned binary data, little endian
853 */
854int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
855 const unsigned char *buf, size_t buflen )
856{
Janos Follath24eed8d2019-11-22 13:21:35 +0000857 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000858 size_t i;
859 size_t const limbs = CHARS_TO_LIMBS( buflen );
860
861 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200862 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Janos Follatha778a942019-02-13 10:28:28 +0000863
864 for( i = 0; i < buflen; i++ )
865 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
866
867cleanup:
868
Janos Follath171a7ef2019-02-15 16:17:45 +0000869 /*
870 * This function is also used to import keys. However, wiping the buffers
871 * upon failure is not necessary because failure only can happen before any
872 * input is copied.
873 */
Janos Follatha778a942019-02-13 10:28:28 +0000874 return( ret );
875}
876
877/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000878 * Import X from unsigned binary data, big endian
879 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000881{
Janos Follath24eed8d2019-11-22 13:21:35 +0000882 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100883 size_t const limbs = CHARS_TO_LIMBS( buflen );
884 size_t const overhead = ( limbs * ciL ) - buflen;
885 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000886
Hanno Becker8ce11a32018-12-19 16:18:52 +0000887 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000888 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
889
Hanno Becker073c1992017-10-17 15:17:27 +0100890 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200891 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000892
Gilles Peskine3130ce22021-06-02 22:17:52 +0200893 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000894 * even if buflen is 0. */
Gilles Peskine3130ce22021-06-02 22:17:52 +0200895 if( buflen != 0 )
Hanno Becker0e810b92019-01-03 17:13:11 +0000896 {
897 Xp = (unsigned char*) X->p;
898 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100899
Hanno Becker0e810b92019-01-03 17:13:11 +0000900 mpi_bigendian_to_host( X->p, limbs );
901 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000902
903cleanup:
904
Janos Follath171a7ef2019-02-15 16:17:45 +0000905 /*
906 * This function is also used to import keys. However, wiping the buffers
907 * upon failure is not necessary because failure only can happen before any
908 * input is copied.
909 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000910 return( ret );
911}
912
913/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000914 * Export X into unsigned binary data, little endian
915 */
916int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
917 unsigned char *buf, size_t buflen )
918{
919 size_t stored_bytes = X->n * ciL;
920 size_t bytes_to_copy;
921 size_t i;
922
923 if( stored_bytes < buflen )
924 {
925 bytes_to_copy = stored_bytes;
926 }
927 else
928 {
929 bytes_to_copy = buflen;
930
931 /* The output buffer is smaller than the allocated size of X.
932 * However X may fit if its leading bytes are zero. */
933 for( i = bytes_to_copy; i < stored_bytes; i++ )
934 {
935 if( GET_BYTE( X, i ) != 0 )
936 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
937 }
938 }
939
940 for( i = 0; i < bytes_to_copy; i++ )
941 buf[i] = GET_BYTE( X, i );
942
943 if( stored_bytes < buflen )
944 {
945 /* Write trailing 0 bytes */
946 memset( buf + stored_bytes, 0, buflen - stored_bytes );
947 }
948
949 return( 0 );
950}
951
952/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000953 * Export X into unsigned binary data, big endian
954 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100955int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
956 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000957{
Hanno Becker73d7d792018-12-11 10:35:51 +0000958 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100959 size_t bytes_to_copy;
960 unsigned char *p;
961 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000962
Hanno Becker73d7d792018-12-11 10:35:51 +0000963 MPI_VALIDATE_RET( X != NULL );
964 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
965
966 stored_bytes = X->n * ciL;
967
Gilles Peskine11cdb052018-11-20 16:47:47 +0100968 if( stored_bytes < buflen )
969 {
970 /* There is enough space in the output buffer. Write initial
971 * null bytes and record the position at which to start
972 * writing the significant bytes. In this case, the execution
973 * trace of this function does not depend on the value of the
974 * number. */
975 bytes_to_copy = stored_bytes;
976 p = buf + buflen - stored_bytes;
977 memset( buf, 0, buflen - stored_bytes );
978 }
979 else
980 {
981 /* The output buffer is smaller than the allocated size of X.
982 * However X may fit if its leading bytes are zero. */
983 bytes_to_copy = buflen;
984 p = buf;
985 for( i = bytes_to_copy; i < stored_bytes; i++ )
986 {
987 if( GET_BYTE( X, i ) != 0 )
988 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
989 }
990 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000991
Gilles Peskine11cdb052018-11-20 16:47:47 +0100992 for( i = 0; i < bytes_to_copy; i++ )
993 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000994
995 return( 0 );
996}
997
998/*
999 * Left-shift: X <<= count
1000 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001002{
Janos Follath24eed8d2019-11-22 13:21:35 +00001003 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001004 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001005 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001006 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001007
1008 v0 = count / (biL );
1009 t1 = count & (biL - 1);
1010
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001011 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001012
Paul Bakkerf9688572011-05-05 10:00:45 +00001013 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001015
1016 ret = 0;
1017
1018 /*
1019 * shift by count / limb_size
1020 */
1021 if( v0 > 0 )
1022 {
Paul Bakker23986e52011-04-24 08:57:21 +00001023 for( i = X->n; i > v0; i-- )
1024 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001025
Paul Bakker23986e52011-04-24 08:57:21 +00001026 for( ; i > 0; i-- )
1027 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001028 }
1029
1030 /*
1031 * shift by count % limb_size
1032 */
1033 if( t1 > 0 )
1034 {
1035 for( i = v0; i < X->n; i++ )
1036 {
1037 r1 = X->p[i] >> (biL - t1);
1038 X->p[i] <<= t1;
1039 X->p[i] |= r0;
1040 r0 = r1;
1041 }
1042 }
1043
1044cleanup:
1045
1046 return( ret );
1047}
1048
1049/*
1050 * Right-shift: X >>= count
1051 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001053{
Paul Bakker23986e52011-04-24 08:57:21 +00001054 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001056 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001057
1058 v0 = count / biL;
1059 v1 = count & (biL - 1);
1060
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001061 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001063
Paul Bakker5121ce52009-01-03 21:22:43 +00001064 /*
1065 * shift by count / limb_size
1066 */
1067 if( v0 > 0 )
1068 {
1069 for( i = 0; i < X->n - v0; i++ )
1070 X->p[i] = X->p[i + v0];
1071
1072 for( ; i < X->n; i++ )
1073 X->p[i] = 0;
1074 }
1075
1076 /*
1077 * shift by count % limb_size
1078 */
1079 if( v1 > 0 )
1080 {
Paul Bakker23986e52011-04-24 08:57:21 +00001081 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 {
Paul Bakker23986e52011-04-24 08:57:21 +00001083 r1 = X->p[i - 1] << (biL - v1);
1084 X->p[i - 1] >>= v1;
1085 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001086 r0 = r1;
1087 }
1088 }
1089
1090 return( 0 );
1091}
1092
1093/*
1094 * Compare unsigned values
1095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001097{
Paul Bakker23986e52011-04-24 08:57:21 +00001098 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001099 MPI_VALIDATE_RET( X != NULL );
1100 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001101
Paul Bakker23986e52011-04-24 08:57:21 +00001102 for( i = X->n; i > 0; i-- )
1103 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001104 break;
1105
Paul Bakker23986e52011-04-24 08:57:21 +00001106 for( j = Y->n; j > 0; j-- )
1107 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001108 break;
1109
Paul Bakker23986e52011-04-24 08:57:21 +00001110 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001111 return( 0 );
1112
1113 if( i > j ) return( 1 );
1114 if( j > i ) return( -1 );
1115
Paul Bakker23986e52011-04-24 08:57:21 +00001116 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001117 {
Paul Bakker23986e52011-04-24 08:57:21 +00001118 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1119 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001120 }
1121
1122 return( 0 );
1123}
1124
1125/*
1126 * Compare signed values
1127 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001128int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001129{
Paul Bakker23986e52011-04-24 08:57:21 +00001130 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001131 MPI_VALIDATE_RET( X != NULL );
1132 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133
Paul Bakker23986e52011-04-24 08:57:21 +00001134 for( i = X->n; i > 0; i-- )
1135 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001136 break;
1137
Paul Bakker23986e52011-04-24 08:57:21 +00001138 for( j = Y->n; j > 0; j-- )
1139 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001140 break;
1141
Paul Bakker23986e52011-04-24 08:57:21 +00001142 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 return( 0 );
1144
1145 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001146 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001147
1148 if( X->s > 0 && Y->s < 0 ) return( 1 );
1149 if( Y->s > 0 && X->s < 0 ) return( -1 );
1150
Paul Bakker23986e52011-04-24 08:57:21 +00001151 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001152 {
Paul Bakker23986e52011-04-24 08:57:21 +00001153 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1154 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001155 }
1156
1157 return( 0 );
1158}
1159
Janos Follath3f6f0e42019-10-14 09:09:32 +01001160/** Decide if an integer is less than the other, without branches.
1161 *
1162 * \param x First integer.
1163 * \param y Second integer.
1164 *
1165 * \return 1 if \p x is less than \p y, 0 otherwise
1166 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001167static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1168 const mbedtls_mpi_uint y )
Janos Follathee6abce2019-09-05 14:47:19 +01001169{
1170 mbedtls_mpi_uint ret;
1171 mbedtls_mpi_uint cond;
1172
1173 /*
1174 * Check if the most significant bits (MSB) of the operands are different.
1175 */
1176 cond = ( x ^ y );
1177 /*
1178 * If the MSB are the same then the difference x-y will be negative (and
1179 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1180 */
1181 ret = ( x - y ) & ~cond;
1182 /*
1183 * If the MSB are different, then the operand with the MSB of 1 is the
1184 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1185 * the MSB of y is 0.)
1186 */
1187 ret |= y & cond;
1188
1189
Janos Follatha0f732b2019-10-14 08:59:14 +01001190 ret = ret >> ( biL - 1 );
Janos Follathee6abce2019-09-05 14:47:19 +01001191
Janos Follath67ce6472019-10-29 15:08:46 +00001192 return (unsigned) ret;
Janos Follathee6abce2019-09-05 14:47:19 +01001193}
1194
1195/*
1196 * Compare signed values in constant time
1197 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001198int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1199 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001200{
1201 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001202 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001203 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001204
1205 MPI_VALIDATE_RET( X != NULL );
1206 MPI_VALIDATE_RET( Y != NULL );
1207 MPI_VALIDATE_RET( ret != NULL );
1208
1209 if( X->n != Y->n )
1210 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1211
1212 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001213 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1214 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001215 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001216 X_is_negative = ( X->s & 2 ) >> 1;
1217 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001218
1219 /*
1220 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001221 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1222 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001223 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001224 cond = ( X_is_negative ^ Y_is_negative );
1225 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001226
1227 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001228 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001229 * need to go through the loop. Record if we have the result already.
1230 */
Janos Follathee6abce2019-09-05 14:47:19 +01001231 done = cond;
1232
1233 for( i = X->n; i > 0; i-- )
1234 {
1235 /*
Janos Follath30702422019-11-05 12:24:52 +00001236 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1237 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001238 *
1239 * Again even if we can make a decision, we just mark the result and
1240 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001241 */
Janos Follath30702422019-11-05 12:24:52 +00001242 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1243 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001244 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001245
1246 /*
Janos Follath30702422019-11-05 12:24:52 +00001247 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1248 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001249 *
1250 * Again even if we can make a decision, we just mark the result and
1251 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001252 */
Janos Follath30702422019-11-05 12:24:52 +00001253 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1254 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001255 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001256 }
1257
1258 return( 0 );
1259}
1260
Paul Bakker5121ce52009-01-03 21:22:43 +00001261/*
1262 * Compare signed values
1263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001265{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 mbedtls_mpi Y;
1267 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001268 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001269
1270 *p = ( z < 0 ) ? -z : z;
1271 Y.s = ( z < 0 ) ? -1 : 1;
1272 Y.n = 1;
1273 Y.p = p;
1274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001276}
1277
1278/*
1279 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001281int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001282{
Janos Follath24eed8d2019-11-22 13:21:35 +00001283 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001284 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001285 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001286 MPI_VALIDATE_RET( X != NULL );
1287 MPI_VALIDATE_RET( A != NULL );
1288 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001289
1290 if( X == B )
1291 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001293 }
1294
1295 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001296 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001297
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001298 /*
1299 * X should always be positive as a result of unsigned additions.
1300 */
1301 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001302
Paul Bakker23986e52011-04-24 08:57:21 +00001303 for( j = B->n; j > 0; j-- )
1304 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001305 break;
1306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001308
1309 o = B->p; p = X->p; c = 0;
1310
Janos Follath6c922682015-10-30 17:43:11 +01001311 /*
1312 * tmp is used because it might happen that p == o
1313 */
Paul Bakker23986e52011-04-24 08:57:21 +00001314 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001315 {
Janos Follath6c922682015-10-30 17:43:11 +01001316 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001317 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001318 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001319 }
1320
1321 while( c != 0 )
1322 {
1323 if( i >= X->n )
1324 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001326 p = X->p + i;
1327 }
1328
Paul Bakker2d319fd2012-09-16 21:34:26 +00001329 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 }
1331
1332cleanup:
1333
1334 return( ret );
1335}
1336
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001337/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001338 * Helper for mbedtls_mpi subtraction.
1339 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001340 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001341 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001342 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001343 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001344 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001345 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001346 * \param n Number of limbs of \p d, \p l and \p r.
1347 * \param[out] d The result of the subtraction.
1348 * \param[in] l The left operand.
1349 * \param[in] r The right operand.
1350 *
1351 * \return 1 if `l < r`.
1352 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001353 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001354static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1355 mbedtls_mpi_uint *d,
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001356 const mbedtls_mpi_uint *l,
1357 const mbedtls_mpi_uint *r )
Paul Bakker5121ce52009-01-03 21:22:43 +00001358{
Paul Bakker23986e52011-04-24 08:57:21 +00001359 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001360 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001362 for( i = 0; i < n; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001363 {
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001364 z = ( l[i] < c ); t = l[i] - c;
1365 c = ( t < r[i] ) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001366 }
1367
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001368 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001369}
1370
1371/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001372 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001375{
Janos Follath24eed8d2019-11-22 13:21:35 +00001376 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001377 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001378 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001379 MPI_VALIDATE_RET( X != NULL );
1380 MPI_VALIDATE_RET( A != NULL );
1381 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001382
Paul Bakker23986e52011-04-24 08:57:21 +00001383 for( n = B->n; n > 0; n-- )
1384 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001385 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001386 if( n > A->n )
1387 {
1388 /* B >= (2^ciL)^n > A */
1389 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1390 goto cleanup;
1391 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001392
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001393 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1394
1395 /* Set the high limbs of X to match A. Don't touch the lower limbs
1396 * because X might be aliased to B, and we must not overwrite the
1397 * significant digits of B. */
1398 if( A->n > n )
1399 memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1400 if( X->n > A->n )
1401 memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1402
1403 carry = mpi_sub_hlp( n, X->p, A->p, B->p );
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001404 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001405 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001406 /* Propagate the carry to the first nonzero limb of X. */
1407 for( ; n < X->n && X->p[n] == 0; n++ )
1408 --X->p[n];
1409 /* If we ran out of space for the carry, it means that the result
1410 * is negative. */
1411 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001412 {
1413 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1414 goto cleanup;
1415 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001416 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001417 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001418
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001419 /* X should always be positive as a result of unsigned subtractions. */
1420 X->s = 1;
1421
Paul Bakker5121ce52009-01-03 21:22:43 +00001422cleanup:
Paul Bakker5121ce52009-01-03 21:22:43 +00001423 return( ret );
1424}
1425
1426/*
1427 * Signed addition: X = A + B
1428 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001429int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001430{
Hanno Becker73d7d792018-12-11 10:35:51 +00001431 int ret, s;
1432 MPI_VALIDATE_RET( X != NULL );
1433 MPI_VALIDATE_RET( A != NULL );
1434 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001435
Hanno Becker73d7d792018-12-11 10:35:51 +00001436 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001437 if( A->s * B->s < 0 )
1438 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001441 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001442 X->s = s;
1443 }
1444 else
1445 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001447 X->s = -s;
1448 }
1449 }
1450 else
1451 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001453 X->s = s;
1454 }
1455
1456cleanup:
1457
1458 return( ret );
1459}
1460
1461/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001462 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001463 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001465{
Hanno Becker73d7d792018-12-11 10:35:51 +00001466 int ret, s;
1467 MPI_VALIDATE_RET( X != NULL );
1468 MPI_VALIDATE_RET( A != NULL );
1469 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001470
Hanno Becker73d7d792018-12-11 10:35:51 +00001471 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001472 if( A->s * B->s > 0 )
1473 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001475 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001477 X->s = s;
1478 }
1479 else
1480 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 X->s = -s;
1483 }
1484 }
1485 else
1486 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001487 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001488 X->s = s;
1489 }
1490
1491cleanup:
1492
1493 return( ret );
1494}
1495
1496/*
1497 * Signed addition: X = A + b
1498 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001500{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 mbedtls_mpi _B;
1502 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001503 MPI_VALIDATE_RET( X != NULL );
1504 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001505
1506 p[0] = ( b < 0 ) ? -b : b;
1507 _B.s = ( b < 0 ) ? -1 : 1;
1508 _B.n = 1;
1509 _B.p = p;
1510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001512}
1513
1514/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001515 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001516 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 mbedtls_mpi _B;
1520 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001521 MPI_VALIDATE_RET( X != NULL );
1522 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001523
1524 p[0] = ( b < 0 ) ? -b : b;
1525 _B.s = ( b < 0 ) ? -1 : 1;
1526 _B.n = 1;
1527 _B.p = p;
1528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001529 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001530}
1531
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001532/** Helper for mbedtls_mpi multiplication.
1533 *
1534 * Add \p b * \p s to \p d.
1535 *
1536 * \param i The number of limbs of \p s.
1537 * \param[in] s A bignum to multiply, of size \p i.
1538 * It may overlap with \p d, but only if
1539 * \p d <= \p s.
1540 * Its leading limb must not be \c 0.
1541 * \param[in,out] d The bignum to add to.
1542 * It must be sufficiently large to store the
1543 * result of the multiplication. This means
1544 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1545 * is not known a priori.
1546 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001547 */
1548static
1549#if defined(__APPLE__) && defined(__arm__)
1550/*
1551 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1552 * appears to need this to prevent bad ARM code generation at -O3.
1553 */
1554__attribute__ ((noinline))
1555#endif
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001556void mpi_mul_hlp( size_t i,
1557 const mbedtls_mpi_uint *s,
1558 mbedtls_mpi_uint *d,
1559 mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001560{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001561 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001562
1563#if defined(MULADDC_HUIT)
1564 for( ; i >= 8; i -= 8 )
1565 {
1566 MULADDC_INIT
1567 MULADDC_HUIT
1568 MULADDC_STOP
1569 }
1570
1571 for( ; i > 0; i-- )
1572 {
1573 MULADDC_INIT
1574 MULADDC_CORE
1575 MULADDC_STOP
1576 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001577#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001578 for( ; i >= 16; i -= 16 )
1579 {
1580 MULADDC_INIT
1581 MULADDC_CORE MULADDC_CORE
1582 MULADDC_CORE MULADDC_CORE
1583 MULADDC_CORE MULADDC_CORE
1584 MULADDC_CORE MULADDC_CORE
1585
1586 MULADDC_CORE MULADDC_CORE
1587 MULADDC_CORE MULADDC_CORE
1588 MULADDC_CORE MULADDC_CORE
1589 MULADDC_CORE MULADDC_CORE
1590 MULADDC_STOP
1591 }
1592
1593 for( ; i >= 8; i -= 8 )
1594 {
1595 MULADDC_INIT
1596 MULADDC_CORE MULADDC_CORE
1597 MULADDC_CORE MULADDC_CORE
1598
1599 MULADDC_CORE MULADDC_CORE
1600 MULADDC_CORE MULADDC_CORE
1601 MULADDC_STOP
1602 }
1603
1604 for( ; i > 0; i-- )
1605 {
1606 MULADDC_INIT
1607 MULADDC_CORE
1608 MULADDC_STOP
1609 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001610#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001611
1612 t++;
1613
Gilles Peskine8e464c42020-07-24 00:08:38 +02001614 while( c != 0 )
1615 {
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 *d += c; c = ( *d < c ); d++;
1617 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001618}
1619
1620/*
1621 * Baseline multiplication: X = A * B (HAC 14.12)
1622 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001624{
Janos Follath24eed8d2019-11-22 13:21:35 +00001625 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001626 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001628 MPI_VALIDATE_RET( X != NULL );
1629 MPI_VALIDATE_RET( A != NULL );
1630 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1635 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001636
Paul Bakker23986e52011-04-24 08:57:21 +00001637 for( i = A->n; i > 0; i-- )
1638 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001639 break;
1640
Paul Bakker23986e52011-04-24 08:57:21 +00001641 for( j = B->n; j > 0; j-- )
1642 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001643 break;
1644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001645 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1646 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001647
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001648 for( ; j > 0; j-- )
1649 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
1651 X->s = A->s * B->s;
1652
1653cleanup:
1654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656
1657 return( ret );
1658}
1659
1660/*
1661 * Baseline multiplication: X = A * b
1662 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001664{
Hanno Becker73d7d792018-12-11 10:35:51 +00001665 MPI_VALIDATE_RET( X != NULL );
1666 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001668 /* mpi_mul_hlp can't deal with a leading 0. */
1669 size_t n = A->n;
1670 while( n > 0 && A->p[n - 1] == 0 )
1671 --n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001673 /* The general method below doesn't work if n==0 or b==0. By chance
1674 * calculating the result is trivial in those cases. */
1675 if( b == 0 || n == 0 )
1676 {
Paul Elliott986b55a2021-04-20 21:46:29 +01001677 return( mbedtls_mpi_lset( X, 0 ) );
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001678 }
1679
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001680 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001681 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001682 /* In general, A * b requires 1 limb more than b. If
1683 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1684 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001685 * copy() will take care of the growth if needed. However, experimentally,
1686 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001687 * calls to calloc() in ECP code, presumably because it reuses the
1688 * same mpi for a while and this way the mpi is more likely to directly
1689 * grow to its final size. */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001690 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
1691 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1692 mpi_mul_hlp( n, A->p, X->p, b - 1 );
1693
1694cleanup:
1695 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696}
1697
1698/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001699 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1700 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001701 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001702static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1703 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001704{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001705#if defined(MBEDTLS_HAVE_UDBL)
1706 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001707#else
Simon Butcher9803d072016-01-03 00:24:34 +00001708 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1709 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001710 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1711 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001712 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001713#endif
1714
Simon Butcher15b15d12015-11-26 19:35:03 +00001715 /*
1716 * Check for overflow
1717 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001718 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001719 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001720 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001721
Simon Butcherf5ba0452015-12-27 23:01:55 +00001722 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001723 }
1724
1725#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001726 dividend = (mbedtls_t_udbl) u1 << biL;
1727 dividend |= (mbedtls_t_udbl) u0;
1728 quotient = dividend / d;
1729 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1730 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1731
1732 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001733 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001734
1735 return (mbedtls_mpi_uint) quotient;
1736#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001737
1738 /*
1739 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1740 * Vol. 2 - Seminumerical Algorithms, Knuth
1741 */
1742
1743 /*
1744 * Normalize the divisor, d, and dividend, u0, u1
1745 */
1746 s = mbedtls_clz( d );
1747 d = d << s;
1748
1749 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001750 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001751 u0 = u0 << s;
1752
1753 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001754 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001755
1756 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001757 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001758
1759 /*
1760 * Find the first quotient and remainder
1761 */
1762 q1 = u1 / d1;
1763 r0 = u1 - d1 * q1;
1764
1765 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1766 {
1767 q1 -= 1;
1768 r0 += d1;
1769
1770 if ( r0 >= radix ) break;
1771 }
1772
Simon Butcherf5ba0452015-12-27 23:01:55 +00001773 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001774 q0 = rAX / d1;
1775 r0 = rAX - q0 * d1;
1776
1777 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1778 {
1779 q0 -= 1;
1780 r0 += d1;
1781
1782 if ( r0 >= radix ) break;
1783 }
1784
1785 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001786 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001787
1788 quotient = q1 * radix + q0;
1789
1790 return quotient;
1791#endif
1792}
1793
1794/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001796 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001797int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1798 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001799{
Janos Follath24eed8d2019-11-22 13:21:35 +00001800 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001801 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001803 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001804 MPI_VALIDATE_RET( A != NULL );
1805 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1808 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001811 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001812 /*
1813 * Avoid dynamic memory allocations for constant-size T2.
1814 *
1815 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1816 * so nobody increase the size of the MPI and we're safe to use an on-stack
1817 * buffer.
1818 */
Alexander K35d6d462019-10-31 14:46:45 +03001819 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001820 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1821 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001824 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1826 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001827 return( 0 );
1828 }
1829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1831 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001832 X.s = Y.s = 1;
1833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1835 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
Gilles Peskine2536aa72020-07-24 00:12:59 +02001836 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001838 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001839 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001840 {
1841 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1843 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844 }
1845 else k = 0;
1846
1847 n = X.n - 1;
1848 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001850
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001851 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001852 {
1853 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857
1858 for( i = n; i > t ; i-- )
1859 {
1860 if( X.p[i] >= Y.p[t] )
1861 Z.p[i - t - 1] = ~0;
1862 else
1863 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001864 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1865 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001866 }
1867
Alexander K35d6d462019-10-31 14:46:45 +03001868 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1869 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1870 T2.p[2] = X.p[i];
1871
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 Z.p[i - t - 1]++;
1873 do
1874 {
1875 Z.p[i - t - 1]--;
1876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001878 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001879 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1885 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1891 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1892 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893 Z.p[i - t - 1]--;
1894 }
1895 }
1896
1897 if( Q != NULL )
1898 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900 Q->s = A->s * B->s;
1901 }
1902
1903 if( R != NULL )
1904 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001905 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001906 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001910 R->s = 1;
1911 }
1912
1913cleanup:
1914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001916 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001917 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001918
1919 return( ret );
1920}
1921
1922/*
1923 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001924 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001925int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1926 const mbedtls_mpi *A,
1927 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001928{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 mbedtls_mpi _B;
1930 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001931 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
1933 p[0] = ( b < 0 ) ? -b : b;
1934 _B.s = ( b < 0 ) ? -1 : 1;
1935 _B.n = 1;
1936 _B.p = p;
1937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001939}
1940
1941/*
1942 * Modulo: R = A mod B
1943 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001945{
Janos Follath24eed8d2019-11-22 13:21:35 +00001946 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001947 MPI_VALIDATE_RET( R != NULL );
1948 MPI_VALIDATE_RET( A != NULL );
1949 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1952 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1957 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1960 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
1962cleanup:
1963
1964 return( ret );
1965}
1966
1967/*
1968 * Modulo: r = A mod b
1969 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001971{
Paul Bakker23986e52011-04-24 08:57:21 +00001972 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001974 MPI_VALIDATE_RET( r != NULL );
1975 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
1977 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
1980 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
1983 /*
1984 * handle trivial cases
1985 */
1986 if( b == 1 )
1987 {
1988 *r = 0;
1989 return( 0 );
1990 }
1991
1992 if( b == 2 )
1993 {
1994 *r = A->p[0] & 1;
1995 return( 0 );
1996 }
1997
1998 /*
1999 * general case
2000 */
Paul Bakker23986e52011-04-24 08:57:21 +00002001 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00002002 {
Paul Bakker23986e52011-04-24 08:57:21 +00002003 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00002004 y = ( y << biH ) | ( x >> biH );
2005 z = y / b;
2006 y -= z * b;
2007
2008 x <<= biH;
2009 y = ( y << biH ) | ( x >> biH );
2010 z = y / b;
2011 y -= z * b;
2012 }
2013
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002014 /*
2015 * If A is negative, then the current y represents a negative value.
2016 * Flipping it to the positive side.
2017 */
2018 if( A->s < 0 && y != 0 )
2019 y = b - y;
2020
Paul Bakker5121ce52009-01-03 21:22:43 +00002021 *r = y;
2022
2023 return( 0 );
2024}
2025
2026/*
2027 * Fast Montgomery initialization (thanks to Tom St Denis)
2028 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002030{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002032 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002033
2034 x = m0;
2035 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002037 for( i = biL; i >= 8; i /= 2 )
2038 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
2040 *mm = ~x + 1;
2041}
2042
Gilles Peskine2a82f722020-06-04 15:00:49 +02002043/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2044 *
2045 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002046 * It must have at least as many limbs as N
2047 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002048 * On successful completion, A contains the result of
2049 * the multiplication A * B * R^-1 mod N where
2050 * R = (2^ciL)^n.
2051 * \param[in] B One of the numbers to multiply.
2052 * It must be nonzero and must not have more limbs than N
2053 * (B->n <= N->n).
2054 * \param[in] N The modulo. N must be odd.
2055 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2056 * This is -N^-1 mod 2^ciL.
2057 * \param[in,out] T A bignum for temporary storage.
2058 * It must be at least twice the limb size of N plus 2
2059 * (T->n >= 2 * (N->n + 1)).
2060 * Its initial content is unused and
2061 * its final content is indeterminate.
2062 * Note that unlike the usual convention in the library
2063 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002064 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002065static 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 +02002066 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002067{
Paul Bakker23986e52011-04-24 08:57:21 +00002068 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002070
2071 memset( T->p, 0, T->n * ciL );
2072
2073 d = T->p;
2074 n = N->n;
2075 m = ( B->n < n ) ? B->n : n;
2076
2077 for( i = 0; i < n; i++ )
2078 {
2079 /*
2080 * T = (T + u0*B + u1*N) / 2^biL
2081 */
2082 u0 = A->p[i];
2083 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2084
2085 mpi_mul_hlp( m, B->p, d, u0 );
2086 mpi_mul_hlp( n, N->p, d, u1 );
2087
2088 *d++ = u0; d[n + 1] = 0;
2089 }
2090
Gilles Peskine221626f2020-06-08 22:37:50 +02002091 /* At this point, d is either the desired result or the desired result
2092 * plus N. We now potentially subtract N, avoiding leaking whether the
2093 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002094
Gilles Peskine221626f2020-06-08 22:37:50 +02002095 /* Copy the n least significant limbs of d to A, so that
2096 * A = d if d < N (recall that N has n limbs). */
2097 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002098 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002099 * do the calculation without using conditional tests. */
2100 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002101 d[n] += 1;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02002102 d[n] -= mpi_sub_hlp( n, d, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02002103 /* If d0 < N then d < (2^biL)^n
2104 * so d[n] == 0 and we want to keep A as it is.
2105 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2106 * so d[n] == 1 and we want to set A to the result of the subtraction
2107 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2108 * This exactly corresponds to a conditional assignment. */
2109 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110}
2111
2112/*
2113 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002114 *
2115 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002116 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002117static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2118 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002119{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 mbedtls_mpi_uint z = 1;
2121 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
Paul Bakker8ddb6452013-02-27 14:56:33 +01002123 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002124 U.p = &z;
2125
Gilles Peskine4e91d472020-06-04 20:55:15 +02002126 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002127}
2128
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002129/*
2130 * Constant-flow boolean "equal" comparison:
2131 * return x == y
2132 *
2133 * This function can be used to write constant-time code by replacing branches
2134 * with bit operations - it can be used in conjunction with
2135 * mbedtls_ssl_cf_mask_from_bit().
2136 *
2137 * This function is implemented without using comparison operators, as those
2138 * might be translated to branches by some compilers on some platforms.
2139 */
2140static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2141{
2142 /* diff = 0 if x == y, non-zero otherwise */
2143 const size_t diff = x ^ y;
2144
2145 /* MSVC has a warning about unary minus on unsigned integer types,
2146 * but this is well-defined and precisely what we want to do here. */
2147#if defined(_MSC_VER)
2148#pragma warning( push )
2149#pragma warning( disable : 4146 )
2150#endif
2151
2152 /* diff_msb's most significant bit is equal to x != y */
2153 const size_t diff_msb = ( diff | -diff );
2154
2155#if defined(_MSC_VER)
2156#pragma warning( pop )
2157#endif
2158
2159 /* diff1 = (x != y) ? 1 : 0 */
2160 const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2161
2162 return( 1 ^ diff1 );
2163}
2164
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002165/**
2166 * Select an MPI from a table without leaking the index.
2167 *
2168 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2169 * reads the entire table in order to avoid leaking the value of idx to an
2170 * attacker able to observe memory access patterns.
2171 *
2172 * \param[out] R Where to write the selected MPI.
2173 * \param[in] T The table to read from.
2174 * \param[in] T_size The number of elements in the table.
2175 * \param[in] idx The index of the element to select;
2176 * this must satisfy 0 <= idx < T_size.
2177 *
2178 * \return \c 0 on success, or a negative error code.
2179 */
2180static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2181{
2182 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2183
2184 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002185 {
2186 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
2187 mbedtls_mpi_cf_bool_eq( i, idx ) ) );
2188 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002189
2190cleanup:
2191 return( ret );
2192}
2193
Paul Bakker5121ce52009-01-03 21:22:43 +00002194/*
2195 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2196 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002197int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2198 const mbedtls_mpi *E, const mbedtls_mpi *N,
2199 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002200{
Janos Follath24eed8d2019-11-22 13:21:35 +00002201 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002202 size_t wbits, wsize, one = 1;
2203 size_t i, j, nblimbs;
2204 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002206 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002207 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002208
Hanno Becker73d7d792018-12-11 10:35:51 +00002209 MPI_VALIDATE_RET( X != NULL );
2210 MPI_VALIDATE_RET( A != NULL );
2211 MPI_VALIDATE_RET( E != NULL );
2212 MPI_VALIDATE_RET( N != NULL );
2213
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002214 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2218 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002219
Chris Jones9246d042020-11-25 15:12:39 +00002220 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2221 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2222 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2223
Paul Bakkerf6198c12012-05-16 08:02:29 +00002224 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002225 * Init temps and window size
2226 */
2227 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2229 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002230 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231 memset( W, 0, sizeof( W ) );
2232
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002233 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002234
2235 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2236 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2237
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002238#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2240 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002241#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002242
Paul Bakker5121ce52009-01-03 21:22:43 +00002243 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2245 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2246 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002247
2248 /*
Paul Bakker50546922012-05-19 08:40:49 +00002249 * Compensate for negative A (and correct at the end)
2250 */
2251 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002252 if( neg )
2253 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002255 Apos.s = 1;
2256 A = &Apos;
2257 }
2258
2259 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002260 * If 1st call, pre-compute R^2 mod N
2261 */
2262 if( _RR == NULL || _RR->p == NULL )
2263 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2265 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2266 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
2268 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 }
2271 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 /*
2275 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2276 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2278 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002279 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
Gilles Peskine4e91d472020-06-04 20:55:15 +02002282 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283
2284 /*
2285 * X = R^2 * R^-1 mod N = R mod N
2286 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002288 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289
2290 if( wsize > 1 )
2291 {
2292 /*
2293 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2294 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002295 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002296
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2298 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299
2300 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002301 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002302
Paul Bakker5121ce52009-01-03 21:22:43 +00002303 /*
2304 * W[i] = W[i - 1] * W[1]
2305 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002306 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002307 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2309 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
Gilles Peskine4e91d472020-06-04 20:55:15 +02002311 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 }
2313 }
2314
2315 nblimbs = E->n;
2316 bufsize = 0;
2317 nbits = 0;
2318 wbits = 0;
2319 state = 0;
2320
2321 while( 1 )
2322 {
2323 if( bufsize == 0 )
2324 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002325 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002326 break;
2327
Paul Bakker0d7702c2013-10-29 16:18:35 +01002328 nblimbs--;
2329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 }
2332
2333 bufsize--;
2334
2335 ei = (E->p[nblimbs] >> bufsize) & 1;
2336
2337 /*
2338 * skip leading 0s
2339 */
2340 if( ei == 0 && state == 0 )
2341 continue;
2342
2343 if( ei == 0 && state == 1 )
2344 {
2345 /*
2346 * out of window, square X
2347 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002348 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349 continue;
2350 }
2351
2352 /*
2353 * add ei to current window
2354 */
2355 state = 2;
2356
2357 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002358 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002359
2360 if( nbits == wsize )
2361 {
2362 /*
2363 * X = X^wsize R^-1 mod N
2364 */
2365 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002366 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
2368 /*
2369 * X = X * W[wbits] R^-1 mod N
2370 */
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002371 MBEDTLS_MPI_CHK( mpi_select( &WW, W, 1 << wsize, wbits ) );
2372 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
2374 state--;
2375 nbits = 0;
2376 wbits = 0;
2377 }
2378 }
2379
2380 /*
2381 * process the remaining bits
2382 */
2383 for( i = 0; i < nbits; i++ )
2384 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002385 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002386
2387 wbits <<= 1;
2388
Paul Bakker66d5d072014-06-17 16:39:18 +02002389 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002390 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002391 }
2392
2393 /*
2394 * X = A^E * R * R^-1 mod N = A^E mod N
2395 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002396 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Hanno Beckera4af1c42017-04-18 09:07:45 +01002398 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002399 {
2400 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002402 }
2403
Paul Bakker5121ce52009-01-03 21:22:43 +00002404cleanup:
2405
Paul Bakker66d5d072014-06-17 16:39:18 +02002406 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002410 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002411
Paul Bakker75a28602014-03-31 12:08:17 +02002412 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002414
2415 return( ret );
2416}
2417
Paul Bakker5121ce52009-01-03 21:22:43 +00002418/*
2419 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2420 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002422{
Janos Follath24eed8d2019-11-22 13:21:35 +00002423 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002424 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002425 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002426
Hanno Becker73d7d792018-12-11 10:35:51 +00002427 MPI_VALIDATE_RET( G != NULL );
2428 MPI_VALIDATE_RET( A != NULL );
2429 MPI_VALIDATE_RET( B != NULL );
2430
Alexander Ke8ad49f2019-08-16 16:16:07 +03002431 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2434 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 lz = mbedtls_mpi_lsb( &TA );
2437 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002438
Paul Bakker66d5d072014-06-17 16:39:18 +02002439 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002440 lz = lzt;
2441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2443 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002444
Paul Bakker5121ce52009-01-03 21:22:43 +00002445 TA.s = TB.s = 1;
2446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002449 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2450 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002453 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002454 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2455 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002456 }
2457 else
2458 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2460 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002461 }
2462 }
2463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002464 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2465 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002466
2467cleanup:
2468
Alexander Ke8ad49f2019-08-16 16:16:07 +03002469 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002470
2471 return( ret );
2472}
2473
Gilles Peskine8f454702021-04-01 15:57:18 +02002474/* Fill X with n_bytes random bytes.
2475 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002476 * The ordering of the bytes returned from the RNG is suitable for
2477 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002478 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002479 * n_bytes must not be 0.
2480 */
2481static int mpi_fill_random_internal(
2482 mbedtls_mpi *X, size_t n_bytes,
2483 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2484{
2485 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2486 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2487 const size_t overhead = ( limbs * ciL ) - n_bytes;
2488
2489 if( X->n < limbs )
2490 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine8f454702021-04-01 15:57:18 +02002491
Gilles Peskinea16001e2021-04-13 21:55:35 +02002492 memset( X->p, 0, overhead );
2493 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine8f454702021-04-01 15:57:18 +02002494 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2495 mpi_bigendian_to_host( X->p, limbs );
2496
2497cleanup:
2498 return( ret );
2499}
2500
Paul Bakker33dc46b2014-04-30 16:11:39 +02002501/*
2502 * Fill X with size bytes of random.
2503 *
2504 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002505 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002506 * deterministic, eg for tests).
2507 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002509 int (*f_rng)(void *, unsigned char *, size_t),
2510 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002511{
Janos Follath24eed8d2019-11-22 13:21:35 +00002512 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002513 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002514
Hanno Becker8ce11a32018-12-19 16:18:52 +00002515 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002516 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002517
Hanno Beckerda1655a2017-10-18 14:21:44 +01002518 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002519 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002520 if( size == 0 )
2521 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002522
Gilles Peskine8f454702021-04-01 15:57:18 +02002523 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002524
2525cleanup:
2526 return( ret );
2527}
2528
Gilles Peskine4699fa42021-03-29 22:02:55 +02002529int mbedtls_mpi_random( mbedtls_mpi *X,
2530 mbedtls_mpi_sint min,
2531 const mbedtls_mpi *N,
2532 int (*f_rng)(void *, unsigned char *, size_t),
2533 void *p_rng )
2534{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002535 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002536 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002537 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002538 size_t n_bits = mbedtls_mpi_bitlen( N );
2539 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002540 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002541
Gilles Peskine9312ba52021-03-29 22:14:51 +02002542 if( min < 0 )
2543 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2544 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2545 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2546
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002547 /*
2548 * When min == 0, each try has at worst a probability 1/2 of failing
2549 * (the msb has a probability 1/2 of being 0, and then the result will
2550 * be < N), so after 30 tries failure probability is a most 2**(-30).
2551 *
2552 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002553 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002554 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002555 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002556 * a probability of failing that is almost 1/2.
2557 *
2558 * The probabilities are almost the same if min is nonzero but negligible
2559 * compared to N. This is always the case when N is crypto-sized, but
2560 * it's convenient to support small N for testing purposes. When N
2561 * is small, use a higher repeat count, otherwise the probability of
2562 * failure is macroscopic.
2563 */
Gilles Peskine11779072021-06-02 21:18:59 +02002564 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002565
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002566 mbedtls_mpi_init( &lower_bound );
2567
Gilles Peskine8f454702021-04-01 15:57:18 +02002568 /* Ensure that target MPI has exactly the same number of limbs
2569 * as the upper bound, even if the upper bound has leading zeros.
2570 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002571 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002572 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2573 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002574
Gilles Peskine4699fa42021-03-29 22:02:55 +02002575 /*
2576 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2577 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2578 * - use the same byte ordering;
2579 * - keep the leftmost n_bits bits of the generated octet string;
2580 * - try until result is in the desired range.
2581 * This also avoids any bias, which is especially important for ECDSA.
2582 */
2583 do
2584 {
Gilles Peskine8f454702021-04-01 15:57:18 +02002585 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002586 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2587
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002588 if( --count == 0 )
Gilles Peskine4699fa42021-03-29 22:02:55 +02002589 {
2590 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2591 goto cleanup;
2592 }
2593
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002594 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2595 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002596 }
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002597 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002598
2599cleanup:
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002600 mbedtls_mpi_free( &lower_bound );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002601 return( ret );
2602}
2603
Paul Bakker5121ce52009-01-03 21:22:43 +00002604/*
2605 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2606 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002607int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002608{
Janos Follath24eed8d2019-11-22 13:21:35 +00002609 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002611 MPI_VALIDATE_RET( X != NULL );
2612 MPI_VALIDATE_RET( A != NULL );
2613 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002614
Hanno Becker4bcb4912017-04-18 15:49:39 +01002615 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002616 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2619 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2620 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002623
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002625 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002627 goto cleanup;
2628 }
2629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2631 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2632 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2633 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2636 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2637 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2638 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002639
2640 do
2641 {
2642 while( ( TU.p[0] & 1 ) == 0 )
2643 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002644 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002645
2646 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2647 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002648 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2649 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002650 }
2651
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002652 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2653 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002654 }
2655
2656 while( ( TV.p[0] & 1 ) == 0 )
2657 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002658 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002659
2660 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2661 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002662 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2663 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002664 }
2665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002666 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2667 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002668 }
2669
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002670 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002671 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002672 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2673 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2674 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002675 }
2676 else
2677 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002678 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2679 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2680 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002681 }
2682 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002683 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002685 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2686 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002688 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2689 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002692
2693cleanup:
2694
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2696 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2697 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002698
2699 return( ret );
2700}
2701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002703
Paul Bakker5121ce52009-01-03 21:22:43 +00002704static const int small_prime[] =
2705{
2706 3, 5, 7, 11, 13, 17, 19, 23,
2707 29, 31, 37, 41, 43, 47, 53, 59,
2708 61, 67, 71, 73, 79, 83, 89, 97,
2709 101, 103, 107, 109, 113, 127, 131, 137,
2710 139, 149, 151, 157, 163, 167, 173, 179,
2711 181, 191, 193, 197, 199, 211, 223, 227,
2712 229, 233, 239, 241, 251, 257, 263, 269,
2713 271, 277, 281, 283, 293, 307, 311, 313,
2714 317, 331, 337, 347, 349, 353, 359, 367,
2715 373, 379, 383, 389, 397, 401, 409, 419,
2716 421, 431, 433, 439, 443, 449, 457, 461,
2717 463, 467, 479, 487, 491, 499, 503, 509,
2718 521, 523, 541, 547, 557, 563, 569, 571,
2719 577, 587, 593, 599, 601, 607, 613, 617,
2720 619, 631, 641, 643, 647, 653, 659, 661,
2721 673, 677, 683, 691, 701, 709, 719, 727,
2722 733, 739, 743, 751, 757, 761, 769, 773,
2723 787, 797, 809, 811, 821, 823, 827, 829,
2724 839, 853, 857, 859, 863, 877, 881, 883,
2725 887, 907, 911, 919, 929, 937, 941, 947,
2726 953, 967, 971, 977, 983, 991, 997, -103
2727};
2728
2729/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002730 * Small divisors test (X must be positive)
2731 *
2732 * Return values:
2733 * 0: no small factor (possible prime, more tests needed)
2734 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002735 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002736 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002737 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002738static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002739{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002740 int ret = 0;
2741 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002742 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002743
Paul Bakker5121ce52009-01-03 21:22:43 +00002744 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002745 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002746
2747 for( i = 0; small_prime[i] > 0; i++ )
2748 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002749 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002750 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002751
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002753
2754 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002755 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002756 }
2757
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002758cleanup:
2759 return( ret );
2760}
2761
2762/*
2763 * Miller-Rabin pseudo-primality test (HAC 4.24)
2764 */
Janos Follathda31fa12018-09-03 14:45:23 +01002765static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002766 int (*f_rng)(void *, unsigned char *, size_t),
2767 void *p_rng )
2768{
Pascal Junodb99183d2015-03-11 16:49:45 +01002769 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002770 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002771 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002772
Hanno Becker8ce11a32018-12-19 16:18:52 +00002773 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002774 MPI_VALIDATE_RET( f_rng != NULL );
2775
2776 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2777 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002778 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002779
Paul Bakker5121ce52009-01-03 21:22:43 +00002780 /*
2781 * W = |X| - 1
2782 * R = W >> lsb( W )
2783 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002784 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2785 s = mbedtls_mpi_lsb( &W );
2786 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2787 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002788
Janos Follathda31fa12018-09-03 14:45:23 +01002789 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002790 {
2791 /*
2792 * pick a random A, 1 < A < |X| - 1
2793 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002794 count = 0;
2795 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002796 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002797
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002798 j = mbedtls_mpi_bitlen( &A );
2799 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002800 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002801 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002802 }
2803
2804 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002805 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2806 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002807 }
2808
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002809 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2810 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002811
2812 /*
2813 * A = A^R mod |X|
2814 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002815 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002816
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2818 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002819 continue;
2820
2821 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002822 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002823 {
2824 /*
2825 * A = A * A mod |X|
2826 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002827 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2828 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002830 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002831 break;
2832
2833 j++;
2834 }
2835
2836 /*
2837 * not prime if A != |X| - 1 or A == 1
2838 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002839 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2840 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002841 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002842 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002843 break;
2844 }
2845 }
2846
2847cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002848 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2849 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002850 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002851
2852 return( ret );
2853}
2854
2855/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002856 * Pseudo-primality test: small factors, then Miller-Rabin
2857 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002858int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2859 int (*f_rng)(void *, unsigned char *, size_t),
2860 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002861{
Janos Follath24eed8d2019-11-22 13:21:35 +00002862 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002863 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002864 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002865 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002866
2867 XX.s = 1;
2868 XX.n = X->n;
2869 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002871 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2872 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2873 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002874
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002875 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002876 return( 0 );
2877
2878 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2879 {
2880 if( ret == 1 )
2881 return( 0 );
2882
2883 return( ret );
2884 }
2885
Janos Follathda31fa12018-09-03 14:45:23 +01002886 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002887}
2888
Janos Follatha0b67c22018-09-18 14:48:23 +01002889#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002890/*
2891 * Pseudo-primality test, error probability 2^-80
2892 */
2893int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2894 int (*f_rng)(void *, unsigned char *, size_t),
2895 void *p_rng )
2896{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002897 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002898 MPI_VALIDATE_RET( f_rng != NULL );
2899
Janos Follatha0b67c22018-09-18 14:48:23 +01002900 /*
2901 * In the past our key generation aimed for an error rate of at most
2902 * 2^-80. Since this function is deprecated, aim for the same certainty
2903 * here as well.
2904 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002905 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002906}
Janos Follatha0b67c22018-09-18 14:48:23 +01002907#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002908
2909/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002910 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002911 *
Janos Follathf301d232018-08-14 13:34:01 +01002912 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2913 * be either 1024 bits or 1536 bits long, and flags must contain
2914 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002915 */
Janos Follath7c025a92018-08-14 11:08:41 +01002916int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002917 int (*f_rng)(void *, unsigned char *, size_t),
2918 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002919{
Jethro Beekman66689272018-02-14 19:24:10 -08002920#ifdef MBEDTLS_HAVE_INT64
2921// ceil(2^63.5)
2922#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2923#else
2924// ceil(2^31.5)
2925#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2926#endif
2927 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002928 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002929 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002930 mbedtls_mpi_uint r;
2931 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002932
Hanno Becker8ce11a32018-12-19 16:18:52 +00002933 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002934 MPI_VALIDATE_RET( f_rng != NULL );
2935
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002936 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2937 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002938
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002939 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002940
2941 n = BITS_TO_LIMBS( nbits );
2942
Janos Follathda31fa12018-09-03 14:45:23 +01002943 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2944 {
2945 /*
2946 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2947 */
2948 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2949 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2950 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2951 }
2952 else
2953 {
2954 /*
2955 * 2^-100 error probability, number of rounds computed based on HAC,
2956 * fact 4.48
2957 */
2958 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2959 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2960 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2961 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2962 }
2963
Jethro Beekman66689272018-02-14 19:24:10 -08002964 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002965 {
Jethro Beekman66689272018-02-14 19:24:10 -08002966 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2967 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2968 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2969
2970 k = n * biL;
2971 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2972 X->p[0] |= 1;
2973
Janos Follath7c025a92018-08-14 11:08:41 +01002974 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002975 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002976 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002977
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002978 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002979 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002980 }
Jethro Beekman66689272018-02-14 19:24:10 -08002981 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002982 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002983 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002984 * An necessary condition for Y and X = 2Y + 1 to be prime
2985 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2986 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002987 */
Jethro Beekman66689272018-02-14 19:24:10 -08002988
2989 X->p[0] |= 2;
2990
2991 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2992 if( r == 0 )
2993 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2994 else if( r == 1 )
2995 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2996
2997 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2998 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2999 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
3000
3001 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003002 {
Jethro Beekman66689272018-02-14 19:24:10 -08003003 /*
3004 * First, check small factors for X and Y
3005 * before doing Miller-Rabin on any of them
3006 */
3007 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
3008 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003009 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003010 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01003011 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01003012 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08003013 goto cleanup;
3014
3015 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
3016 goto cleanup;
3017
3018 /*
3019 * Next candidates. We want to preserve Y = (X-1) / 2 and
3020 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3021 * so up Y by 6 and X by 12.
3022 */
3023 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
3024 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003025 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003026 }
3027 }
3028
3029cleanup:
3030
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003031 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00003032
3033 return( ret );
3034}
3035
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003036#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003038#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003039
Paul Bakker23986e52011-04-24 08:57:21 +00003040#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003041
3042static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3043{
3044 { 693, 609, 21 },
3045 { 1764, 868, 28 },
3046 { 768454923, 542167814, 1 }
3047};
3048
Paul Bakker5121ce52009-01-03 21:22:43 +00003049/*
3050 * Checkup routine
3051 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003052int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00003053{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003054 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003055 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003057 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
3058 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003060 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003061 "EFE021C2645FD1DC586E69184AF4A31E" \
3062 "D5F53E93B5F123FA41680867BA110131" \
3063 "944FE7952E2517337780CB0DB80E61AA" \
3064 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3065
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003066 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003067 "B2E7EFD37075B9F03FF989C7C5051C20" \
3068 "34D2A323810251127E7BF8625A4F49A5" \
3069 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3070 "5B5C25763222FEFCCFC38B832366C29E" ) );
3071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003072 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003073 "0066A198186C18C10B2F5ED9B522752A" \
3074 "9830B69916E535C8F047518A889A43A5" \
3075 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003077 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003079 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003080 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3081 "9E857EA95A03512E2BAE7391688D264A" \
3082 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3083 "8001B72E848A38CAE1C65F78E56ABDEF" \
3084 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3085 "ECF677152EF804370C1A305CAF3B5BF1" \
3086 "30879B56C61DE584A0F53A2447A51E" ) );
3087
3088 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003089 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003091 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003092 {
3093 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003094 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003095
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003096 ret = 1;
3097 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003098 }
3099
3100 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003101 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003102
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003103 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003105 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003106 "256567336059E52CAE22925474705F39A94" ) );
3107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003108 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003109 "6613F26162223DF488E9CD48CC132C7A" \
3110 "0AC93C701B001B092E4E5B9F73BCD27B" \
3111 "9EE50D0657C77F374E903CDFA4C642" ) );
3112
3113 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003114 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003116 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3117 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003118 {
3119 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003120 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003121
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003122 ret = 1;
3123 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003124 }
3125
3126 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003127 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003129 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003131 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003132 "36E139AEA55215609D2816998ED020BB" \
3133 "BD96C37890F65171D948E9BC7CBAA4D9" \
3134 "325D24D6A3C12710F10A09FA08AB87" ) );
3135
3136 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003137 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003139 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003140 {
3141 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003142 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003143
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003144 ret = 1;
3145 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003146 }
3147
3148 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003149 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003151 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003153 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003154 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3155 "C3DBA76456363A10869622EAC2DD84EC" \
3156 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3157
3158 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003159 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003161 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003162 {
3163 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003164 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003165
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003166 ret = 1;
3167 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003168 }
3169
3170 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003171 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003172
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003173 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003174 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003175
Paul Bakker66d5d072014-06-17 16:39:18 +02003176 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003177 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003178 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3179 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003181 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003183 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003184 {
3185 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003186 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003187
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003188 ret = 1;
3189 goto cleanup;
3190 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003191 }
3192
3193 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003194 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003195
Paul Bakker5121ce52009-01-03 21:22:43 +00003196cleanup:
3197
3198 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003199 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003201 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3202 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003203
3204 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003205 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003206
3207 return( ret );
3208}
3209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003210#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003212#endif /* MBEDTLS_BIGNUM_C */