blob: 2c364568924cc3a9e5493d88c1ec016c1b46a0af [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
2129/*
2130 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2131 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002132int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2133 const mbedtls_mpi *E, const mbedtls_mpi *N,
2134 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002135{
Janos Follath24eed8d2019-11-22 13:21:35 +00002136 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002137 size_t wbits, wsize, one = 1;
2138 size_t i, j, nblimbs;
2139 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 mbedtls_mpi_uint ei, mm, state;
Daniel Otte388f9b22020-08-21 12:34:29 +02002141 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002142 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
Hanno Becker73d7d792018-12-11 10:35:51 +00002144 MPI_VALIDATE_RET( X != NULL );
2145 MPI_VALIDATE_RET( A != NULL );
2146 MPI_VALIDATE_RET( E != NULL );
2147 MPI_VALIDATE_RET( N != NULL );
2148
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002149 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2153 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002154
Chris Jones9246d042020-11-25 15:12:39 +00002155 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2156 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2157 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2158
Paul Bakkerf6198c12012-05-16 08:02:29 +00002159 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002160 * Init temps and window size
2161 */
2162 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2164 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 memset( W, 0, sizeof( W ) );
2166
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002167 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002168
2169 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2170 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2171
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002172#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2174 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002175#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002176
Paul Bakker5121ce52009-01-03 21:22:43 +00002177 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2179 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2180 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
2182 /*
Paul Bakker50546922012-05-19 08:40:49 +00002183 * Compensate for negative A (and correct at the end)
2184 */
2185 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002186 if( neg )
2187 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002189 Apos.s = 1;
2190 A = &Apos;
2191 }
2192
2193 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 * If 1st call, pre-compute R^2 mod N
2195 */
2196 if( _RR == NULL || _RR->p == NULL )
2197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2200 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
2202 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204 }
2205 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207
2208 /*
2209 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2210 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2212 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002213 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002215
Gilles Peskine4e91d472020-06-04 20:55:15 +02002216 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
2218 /*
2219 * X = R^2 * R^-1 mod N = R mod N
2220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002222 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002223
2224 if( wsize > 1 )
2225 {
2226 /*
2227 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2228 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002229 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2232 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
2234 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002235 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002236
Paul Bakker5121ce52009-01-03 21:22:43 +00002237 /*
2238 * W[i] = W[i - 1] * W[1]
2239 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002240 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002241 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2243 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002244
Gilles Peskine4e91d472020-06-04 20:55:15 +02002245 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002246 }
2247 }
2248
2249 nblimbs = E->n;
2250 bufsize = 0;
2251 nbits = 0;
2252 wbits = 0;
2253 state = 0;
2254
2255 while( 1 )
2256 {
2257 if( bufsize == 0 )
2258 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002259 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002260 break;
2261
Paul Bakker0d7702c2013-10-29 16:18:35 +01002262 nblimbs--;
2263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002265 }
2266
2267 bufsize--;
2268
2269 ei = (E->p[nblimbs] >> bufsize) & 1;
2270
2271 /*
2272 * skip leading 0s
2273 */
2274 if( ei == 0 && state == 0 )
2275 continue;
2276
2277 if( ei == 0 && state == 1 )
2278 {
2279 /*
2280 * out of window, square X
2281 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002282 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 continue;
2284 }
2285
2286 /*
2287 * add ei to current window
2288 */
2289 state = 2;
2290
2291 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002292 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002293
2294 if( nbits == wsize )
2295 {
2296 /*
2297 * X = X^wsize R^-1 mod N
2298 */
2299 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002300 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002301
2302 /*
2303 * X = X * W[wbits] R^-1 mod N
2304 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002305 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
2307 state--;
2308 nbits = 0;
2309 wbits = 0;
2310 }
2311 }
2312
2313 /*
2314 * process the remaining bits
2315 */
2316 for( i = 0; i < nbits; i++ )
2317 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002318 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319
2320 wbits <<= 1;
2321
Paul Bakker66d5d072014-06-17 16:39:18 +02002322 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002323 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 }
2325
2326 /*
2327 * X = A^E * R * R^-1 mod N = A^E mod N
2328 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002329 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002330
Hanno Beckera4af1c42017-04-18 09:07:45 +01002331 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002332 {
2333 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002335 }
2336
Paul Bakker5121ce52009-01-03 21:22:43 +00002337cleanup:
2338
Paul Bakker66d5d072014-06-17 16:39:18 +02002339 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002343
Paul Bakker75a28602014-03-31 12:08:17 +02002344 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
2347 return( ret );
2348}
2349
Paul Bakker5121ce52009-01-03 21:22:43 +00002350/*
2351 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002354{
Janos Follath24eed8d2019-11-22 13:21:35 +00002355 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002356 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002357 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002358
Hanno Becker73d7d792018-12-11 10:35:51 +00002359 MPI_VALIDATE_RET( G != NULL );
2360 MPI_VALIDATE_RET( A != NULL );
2361 MPI_VALIDATE_RET( B != NULL );
2362
Alexander Ke8ad49f2019-08-16 16:16:07 +03002363 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2366 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 lz = mbedtls_mpi_lsb( &TA );
2369 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002370
Paul Bakker66d5d072014-06-17 16:39:18 +02002371 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002372 lz = lzt;
2373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2375 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002376
Paul Bakker5121ce52009-01-03 21:22:43 +00002377 TA.s = TB.s = 1;
2378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002380 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2382 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002385 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2387 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002388 }
2389 else
2390 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2392 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 }
2394 }
2395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2397 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002398
2399cleanup:
2400
Alexander Ke8ad49f2019-08-16 16:16:07 +03002401 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
2403 return( ret );
2404}
2405
Gilles Peskine8f454702021-04-01 15:57:18 +02002406/* Fill X with n_bytes random bytes.
2407 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002408 * The ordering of the bytes returned from the RNG is suitable for
2409 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002410 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002411 * n_bytes must not be 0.
2412 */
2413static int mpi_fill_random_internal(
2414 mbedtls_mpi *X, size_t n_bytes,
2415 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2416{
2417 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2418 const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2419 const size_t overhead = ( limbs * ciL ) - n_bytes;
2420
2421 if( X->n < limbs )
2422 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Gilles Peskine8f454702021-04-01 15:57:18 +02002423
Gilles Peskinea16001e2021-04-13 21:55:35 +02002424 memset( X->p, 0, overhead );
2425 memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
Gilles Peskine8f454702021-04-01 15:57:18 +02002426 MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2427 mpi_bigendian_to_host( X->p, limbs );
2428
2429cleanup:
2430 return( ret );
2431}
2432
Paul Bakker33dc46b2014-04-30 16:11:39 +02002433/*
2434 * Fill X with size bytes of random.
2435 *
2436 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002437 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002438 * deterministic, eg for tests).
2439 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002441 int (*f_rng)(void *, unsigned char *, size_t),
2442 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002443{
Janos Follath24eed8d2019-11-22 13:21:35 +00002444 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002445 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002446
Hanno Becker8ce11a32018-12-19 16:18:52 +00002447 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002448 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002449
Hanno Beckerda1655a2017-10-18 14:21:44 +01002450 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002451 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002452 if( size == 0 )
2453 return( 0 );
Paul Bakker287781a2011-03-26 13:18:49 +00002454
Gilles Peskine8f454702021-04-01 15:57:18 +02002455 ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
Paul Bakker287781a2011-03-26 13:18:49 +00002456
2457cleanup:
2458 return( ret );
2459}
2460
Gilles Peskine4699fa42021-03-29 22:02:55 +02002461int mbedtls_mpi_random( mbedtls_mpi *X,
2462 mbedtls_mpi_sint min,
2463 const mbedtls_mpi *N,
2464 int (*f_rng)(void *, unsigned char *, size_t),
2465 void *p_rng )
2466{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002467 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002468 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002469 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002470 size_t n_bits = mbedtls_mpi_bitlen( N );
2471 size_t n_bytes = ( n_bits + 7 ) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002472 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002473
Gilles Peskine9312ba52021-03-29 22:14:51 +02002474 if( min < 0 )
2475 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2476 if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2478
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002479 /*
2480 * When min == 0, each try has at worst a probability 1/2 of failing
2481 * (the msb has a probability 1/2 of being 0, and then the result will
2482 * be < N), so after 30 tries failure probability is a most 2**(-30).
2483 *
2484 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002485 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002486 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002487 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002488 * a probability of failing that is almost 1/2.
2489 *
2490 * The probabilities are almost the same if min is nonzero but negligible
2491 * compared to N. This is always the case when N is crypto-sized, but
2492 * it's convenient to support small N for testing purposes. When N
2493 * is small, use a higher repeat count, otherwise the probability of
2494 * failure is macroscopic.
2495 */
Gilles Peskine11779072021-06-02 21:18:59 +02002496 count = ( n_bytes > 4 ? 30 : 250 );
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002497
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002498 mbedtls_mpi_init( &lower_bound );
2499
Gilles Peskine8f454702021-04-01 15:57:18 +02002500 /* Ensure that target MPI has exactly the same number of limbs
2501 * as the upper bound, even if the upper bound has leading zeros.
2502 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine3130ce22021-06-02 22:17:52 +02002503 MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002504 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2505 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
Gilles Peskine8f454702021-04-01 15:57:18 +02002506
Gilles Peskine4699fa42021-03-29 22:02:55 +02002507 /*
2508 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2509 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2510 * - use the same byte ordering;
2511 * - keep the leftmost n_bits bits of the generated octet string;
2512 * - try until result is in the desired range.
2513 * This also avoids any bias, which is especially important for ECDSA.
2514 */
2515 do
2516 {
Gilles Peskine8f454702021-04-01 15:57:18 +02002517 MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002518 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2519
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002520 if( --count == 0 )
Gilles Peskine4699fa42021-03-29 22:02:55 +02002521 {
2522 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2523 goto cleanup;
2524 }
2525
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002526 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2527 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002528 }
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002529 while( lt_lower != 0 || lt_upper == 0 );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002530
2531cleanup:
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002532 mbedtls_mpi_free( &lower_bound );
Gilles Peskine4699fa42021-03-29 22:02:55 +02002533 return( ret );
2534}
2535
Paul Bakker5121ce52009-01-03 21:22:43 +00002536/*
2537 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2538 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002539int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002540{
Janos Follath24eed8d2019-11-22 13:21:35 +00002541 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002543 MPI_VALIDATE_RET( X != NULL );
2544 MPI_VALIDATE_RET( A != NULL );
2545 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002546
Hanno Becker4bcb4912017-04-18 15:49:39 +01002547 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2551 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2552 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002557 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002558 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002559 goto cleanup;
2560 }
2561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2563 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2564 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2565 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002567 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2568 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2569 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2570 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002571
2572 do
2573 {
2574 while( ( TU.p[0] & 1 ) == 0 )
2575 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002577
2578 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2579 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002580 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2581 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002582 }
2583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2585 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002586 }
2587
2588 while( ( TV.p[0] & 1 ) == 0 )
2589 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
2592 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2593 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2595 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 }
2597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2599 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002600 }
2601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002602 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002603 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2605 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2606 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002607 }
2608 else
2609 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2611 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2612 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002613 }
2614 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2618 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002620 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2621 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002622
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002624
2625cleanup:
2626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002627 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2628 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2629 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002630
2631 return( ret );
2632}
2633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002635
Paul Bakker5121ce52009-01-03 21:22:43 +00002636static const int small_prime[] =
2637{
2638 3, 5, 7, 11, 13, 17, 19, 23,
2639 29, 31, 37, 41, 43, 47, 53, 59,
2640 61, 67, 71, 73, 79, 83, 89, 97,
2641 101, 103, 107, 109, 113, 127, 131, 137,
2642 139, 149, 151, 157, 163, 167, 173, 179,
2643 181, 191, 193, 197, 199, 211, 223, 227,
2644 229, 233, 239, 241, 251, 257, 263, 269,
2645 271, 277, 281, 283, 293, 307, 311, 313,
2646 317, 331, 337, 347, 349, 353, 359, 367,
2647 373, 379, 383, 389, 397, 401, 409, 419,
2648 421, 431, 433, 439, 443, 449, 457, 461,
2649 463, 467, 479, 487, 491, 499, 503, 509,
2650 521, 523, 541, 547, 557, 563, 569, 571,
2651 577, 587, 593, 599, 601, 607, 613, 617,
2652 619, 631, 641, 643, 647, 653, 659, 661,
2653 673, 677, 683, 691, 701, 709, 719, 727,
2654 733, 739, 743, 751, 757, 761, 769, 773,
2655 787, 797, 809, 811, 821, 823, 827, 829,
2656 839, 853, 857, 859, 863, 877, 881, 883,
2657 887, 907, 911, 919, 929, 937, 941, 947,
2658 953, 967, 971, 977, 983, 991, 997, -103
2659};
2660
2661/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002662 * Small divisors test (X must be positive)
2663 *
2664 * Return values:
2665 * 0: no small factor (possible prime, more tests needed)
2666 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002668 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002669 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002670static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002671{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002672 int ret = 0;
2673 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002674 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002675
Paul Bakker5121ce52009-01-03 21:22:43 +00002676 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002678
2679 for( i = 0; small_prime[i] > 0; i++ )
2680 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002681 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002682 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002685
2686 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002688 }
2689
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002690cleanup:
2691 return( ret );
2692}
2693
2694/*
2695 * Miller-Rabin pseudo-primality test (HAC 4.24)
2696 */
Janos Follathda31fa12018-09-03 14:45:23 +01002697static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002698 int (*f_rng)(void *, unsigned char *, size_t),
2699 void *p_rng )
2700{
Pascal Junodb99183d2015-03-11 16:49:45 +01002701 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002702 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002703 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002704
Hanno Becker8ce11a32018-12-19 16:18:52 +00002705 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002706 MPI_VALIDATE_RET( f_rng != NULL );
2707
2708 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2709 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002710 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002711
Paul Bakker5121ce52009-01-03 21:22:43 +00002712 /*
2713 * W = |X| - 1
2714 * R = W >> lsb( W )
2715 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002716 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2717 s = mbedtls_mpi_lsb( &W );
2718 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2719 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002720
Janos Follathda31fa12018-09-03 14:45:23 +01002721 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 {
2723 /*
2724 * pick a random A, 1 < A < |X| - 1
2725 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002726 count = 0;
2727 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002728 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002729
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002730 j = mbedtls_mpi_bitlen( &A );
2731 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002732 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002733 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002734 }
2735
2736 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002737 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2738 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002739 }
2740
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002741 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2742 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002743
2744 /*
2745 * A = A^R mod |X|
2746 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002749 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2750 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002751 continue;
2752
2753 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002755 {
2756 /*
2757 * A = A * A mod |X|
2758 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2760 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002761
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002762 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002763 break;
2764
2765 j++;
2766 }
2767
2768 /*
2769 * not prime if A != |X| - 1 or A == 1
2770 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002771 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2772 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002773 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002775 break;
2776 }
2777 }
2778
2779cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002780 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2781 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002782 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002783
2784 return( ret );
2785}
2786
2787/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002788 * Pseudo-primality test: small factors, then Miller-Rabin
2789 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002790int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2791 int (*f_rng)(void *, unsigned char *, size_t),
2792 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002793{
Janos Follath24eed8d2019-11-22 13:21:35 +00002794 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002796 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002797 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002798
2799 XX.s = 1;
2800 XX.n = X->n;
2801 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2804 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2805 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002808 return( 0 );
2809
2810 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2811 {
2812 if( ret == 1 )
2813 return( 0 );
2814
2815 return( ret );
2816 }
2817
Janos Follathda31fa12018-09-03 14:45:23 +01002818 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002819}
2820
Janos Follatha0b67c22018-09-18 14:48:23 +01002821#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002822/*
2823 * Pseudo-primality test, error probability 2^-80
2824 */
2825int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2826 int (*f_rng)(void *, unsigned char *, size_t),
2827 void *p_rng )
2828{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002829 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002830 MPI_VALIDATE_RET( f_rng != NULL );
2831
Janos Follatha0b67c22018-09-18 14:48:23 +01002832 /*
2833 * In the past our key generation aimed for an error rate of at most
2834 * 2^-80. Since this function is deprecated, aim for the same certainty
2835 * here as well.
2836 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002837 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002838}
Janos Follatha0b67c22018-09-18 14:48:23 +01002839#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002840
2841/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002842 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002843 *
Janos Follathf301d232018-08-14 13:34:01 +01002844 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2845 * be either 1024 bits or 1536 bits long, and flags must contain
2846 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002847 */
Janos Follath7c025a92018-08-14 11:08:41 +01002848int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002849 int (*f_rng)(void *, unsigned char *, size_t),
2850 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002851{
Jethro Beekman66689272018-02-14 19:24:10 -08002852#ifdef MBEDTLS_HAVE_INT64
2853// ceil(2^63.5)
2854#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2855#else
2856// ceil(2^31.5)
2857#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2858#endif
2859 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002860 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002861 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002862 mbedtls_mpi_uint r;
2863 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002864
Hanno Becker8ce11a32018-12-19 16:18:52 +00002865 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002866 MPI_VALIDATE_RET( f_rng != NULL );
2867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002868 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2869 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002871 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002872
2873 n = BITS_TO_LIMBS( nbits );
2874
Janos Follathda31fa12018-09-03 14:45:23 +01002875 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2876 {
2877 /*
2878 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2879 */
2880 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2881 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2882 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2883 }
2884 else
2885 {
2886 /*
2887 * 2^-100 error probability, number of rounds computed based on HAC,
2888 * fact 4.48
2889 */
2890 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2891 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2892 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2893 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2894 }
2895
Jethro Beekman66689272018-02-14 19:24:10 -08002896 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002897 {
Jethro Beekman66689272018-02-14 19:24:10 -08002898 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2899 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2900 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2901
2902 k = n * biL;
2903 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2904 X->p[0] |= 1;
2905
Janos Follath7c025a92018-08-14 11:08:41 +01002906 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002907 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002908 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002909
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002910 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002911 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002912 }
Jethro Beekman66689272018-02-14 19:24:10 -08002913 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002914 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002915 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002916 * An necessary condition for Y and X = 2Y + 1 to be prime
2917 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2918 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002919 */
Jethro Beekman66689272018-02-14 19:24:10 -08002920
2921 X->p[0] |= 2;
2922
2923 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2924 if( r == 0 )
2925 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2926 else if( r == 1 )
2927 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2928
2929 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2930 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2931 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2932
2933 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002934 {
Jethro Beekman66689272018-02-14 19:24:10 -08002935 /*
2936 * First, check small factors for X and Y
2937 * before doing Miller-Rabin on any of them
2938 */
2939 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2940 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002941 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002942 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002943 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002944 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002945 goto cleanup;
2946
2947 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2948 goto cleanup;
2949
2950 /*
2951 * Next candidates. We want to preserve Y = (X-1) / 2 and
2952 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2953 * so up Y by 6 and X by 12.
2954 */
2955 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2956 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002957 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002958 }
2959 }
2960
2961cleanup:
2962
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002963 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002964
2965 return( ret );
2966}
2967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002968#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002970#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002971
Paul Bakker23986e52011-04-24 08:57:21 +00002972#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002973
2974static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2975{
2976 { 693, 609, 21 },
2977 { 1764, 868, 28 },
2978 { 768454923, 542167814, 1 }
2979};
2980
Paul Bakker5121ce52009-01-03 21:22:43 +00002981/*
2982 * Checkup routine
2983 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002984int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002985{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002986 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002987 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002989 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2990 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002991
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002992 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002993 "EFE021C2645FD1DC586E69184AF4A31E" \
2994 "D5F53E93B5F123FA41680867BA110131" \
2995 "944FE7952E2517337780CB0DB80E61AA" \
2996 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2997
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002998 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002999 "B2E7EFD37075B9F03FF989C7C5051C20" \
3000 "34D2A323810251127E7BF8625A4F49A5" \
3001 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3002 "5B5C25763222FEFCCFC38B832366C29E" ) );
3003
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003004 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003005 "0066A198186C18C10B2F5ED9B522752A" \
3006 "9830B69916E535C8F047518A889A43A5" \
3007 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3008
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003009 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003011 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003012 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3013 "9E857EA95A03512E2BAE7391688D264A" \
3014 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3015 "8001B72E848A38CAE1C65F78E56ABDEF" \
3016 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3017 "ECF677152EF804370C1A305CAF3B5BF1" \
3018 "30879B56C61DE584A0F53A2447A51E" ) );
3019
3020 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003021 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003023 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003024 {
3025 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003026 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003027
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003028 ret = 1;
3029 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003030 }
3031
3032 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003033 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003035 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003036
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003037 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003038 "256567336059E52CAE22925474705F39A94" ) );
3039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003040 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003041 "6613F26162223DF488E9CD48CC132C7A" \
3042 "0AC93C701B001B092E4E5B9F73BCD27B" \
3043 "9EE50D0657C77F374E903CDFA4C642" ) );
3044
3045 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003046 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003048 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3049 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003050 {
3051 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003052 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003053
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003054 ret = 1;
3055 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003056 }
3057
3058 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003059 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003060
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003061 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003063 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003064 "36E139AEA55215609D2816998ED020BB" \
3065 "BD96C37890F65171D948E9BC7CBAA4D9" \
3066 "325D24D6A3C12710F10A09FA08AB87" ) );
3067
3068 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003069 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003071 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003072 {
3073 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003074 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003075
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003076 ret = 1;
3077 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003078 }
3079
3080 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003081 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003083 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003085 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003086 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3087 "C3DBA76456363A10869622EAC2DD84EC" \
3088 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3089
3090 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003091 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003093 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003094 {
3095 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003096 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003097
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003098 ret = 1;
3099 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003100 }
3101
3102 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003103 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003104
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003105 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003106 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003107
Paul Bakker66d5d072014-06-17 16:39:18 +02003108 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003109 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003110 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3111 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003113 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003114
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003115 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003116 {
3117 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003118 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003119
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003120 ret = 1;
3121 goto cleanup;
3122 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003123 }
3124
3125 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003126 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003127
Paul Bakker5121ce52009-01-03 21:22:43 +00003128cleanup:
3129
3130 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003131 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003133 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3134 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003135
3136 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003137 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003138
3139 return( ret );
3140}
3141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003142#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003144#endif /* MBEDTLS_BIGNUM_C */