blob: 70bd428660a85b0bfc65bb0c377ff87ae0b95ca4 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Paul Bakker5121ce52009-01-03 21:22:43 +000045 */
Simon Butcher15b15d12015-11-26 19:35:03 +000046
Paul Bakker5121ce52009-01-03 21:22:43 +000047/*
Simon Butcher15b15d12015-11-26 19:35:03 +000048 * The following sources were referenced in the design of this Multi-precision
49 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000050 *
Simon Butcher15b15d12015-11-26 19:35:03 +000051 * [1] Handbook of Applied Cryptography - 1997
52 * Menezes, van Oorschot and Vanstone
53 *
54 * [2] Multi-Precision Math
55 * Tom St Denis
56 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
57 *
58 * [3] GNU Multi-Precision Arithmetic Library
59 * https://gmplib.org/manual/index.html
60 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000061 */
Paul Bakker5121ce52009-01-03 21:22:43 +000062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000064#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020065#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020067#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000068
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000070
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000071#include "mbedtls/bignum.h"
72#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050073#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000074
Rich Evans00ab4702015-02-06 13:43:58 +000075#include <string.h>
76
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000078#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020079#else
Rich Evans00ab4702015-02-06 13:43:58 +000080#include <stdio.h>
81#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020083#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020085#endif
86
Hanno Becker73d7d792018-12-11 10:35:51 +000087#define MPI_VALIDATE_RET( cond ) \
88 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
89#define MPI_VALIDATE( cond ) \
90 MBEDTLS_INTERNAL_VALIDATE( cond )
91
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000093#define biL (ciL << 3) /* bits in limb */
94#define biH (ciL << 2) /* half limb size */
95
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010096#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
97
Paul Bakker5121ce52009-01-03 21:22:43 +000098/*
99 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200100 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +0000101 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200102#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
103#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500105/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -0500106static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
107{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500108 mbedtls_platform_zeroize( v, ciL * n );
109}
110
Paul Bakker5121ce52009-01-03 21:22:43 +0000111/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Hanno Becker73d7d792018-12-11 10:35:51 +0000116 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000117
Paul Bakker6c591fa2011-05-05 11:49:20 +0000118 X->s = 1;
119 X->n = 0;
120 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000121}
122
123/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000124 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000125 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000127{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000128 if( X == NULL )
129 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000130
Paul Bakker6c591fa2011-05-05 11:49:20 +0000131 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000132 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200133 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000135 }
136
Paul Bakker6c591fa2011-05-05 11:49:20 +0000137 X->s = 1;
138 X->n = 0;
139 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000140}
141
142/*
143 * Enlarge to the specified number of limbs
144 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000146{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000148 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200151 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000152
Paul Bakker5121ce52009-01-03 21:22:43 +0000153 if( X->n < nblimbs )
154 {
Simon Butcher29176892016-05-20 00:19:09 +0100155 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200156 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000157
Paul Bakker5121ce52009-01-03 21:22:43 +0000158 if( X->p != NULL )
159 {
160 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200161 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000163 }
164
165 X->n = nblimbs;
166 X->p = p;
167 }
168
169 return( 0 );
170}
171
172/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100173 * Resize down as much as possible,
174 * while keeping at least the specified number of limbs
175 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100177{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100179 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000180 MPI_VALIDATE_RET( X != NULL );
181
182 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
183 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100184
Gilles Peskine27c15c72020-01-20 21:17:43 +0100185 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100186 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine56427c22020-01-21 13:59:51 +0100188 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100189
190 for( i = X->n - 1; i > 0; i-- )
191 if( X->p[i] != 0 )
192 break;
193 i++;
194
195 if( i < nblimbs )
196 i = nblimbs;
197
Simon Butcher29176892016-05-20 00:19:09 +0100198 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200199 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100200
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100201 if( X->p != NULL )
202 {
203 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200204 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100206 }
207
208 X->n = i;
209 X->p = p;
210
211 return( 0 );
212}
213
214/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000215 * Copy the contents of Y into X
216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000218{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100219 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000220 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000221 MPI_VALIDATE_RET( X != NULL );
222 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
224 if( X == Y )
225 return( 0 );
226
Gilles Peskine3e9f5222020-01-20 21:12:50 +0100227 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200228 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200230 return( 0 );
231 }
232
Paul Bakker5121ce52009-01-03 21:22:43 +0000233 for( i = Y->n - 1; i > 0; i-- )
234 if( Y->p[i] != 0 )
235 break;
236 i++;
237
238 X->s = Y->s;
239
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100240 if( X->n < i )
241 {
242 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
243 }
244 else
245 {
246 memset( X->p + i, 0, ( X->n - i ) * ciL );
247 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000248
Paul Bakker5121ce52009-01-03 21:22:43 +0000249 memcpy( X->p, Y->p, i * ciL );
250
251cleanup:
252
253 return( ret );
254}
255
256/*
257 * Swap the contents of X and Y
258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000260{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000262 MPI_VALIDATE( X != NULL );
263 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 memcpy( &T, X, sizeof( mbedtls_mpi ) );
266 memcpy( X, Y, sizeof( mbedtls_mpi ) );
267 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000268}
269
Manuel Pégourié-Gonnarddc6a5f22021-06-07 09:51:00 +0200270/**
271 * Select between two sign values in constant-time.
272 *
273 * This is functionally equivalent to second ? a : b but uses only bit
274 * operations in order to avoid branches.
275 *
276 * \param[in] a The first sign; must be either +1 or -1.
277 * \param[in] b The second sign; must be either +1 or -1.
278 * \param[in] second Must be either 1 (return b) or 0 (return a).
279 *
280 * \return The selected sign value.
281 */
282static int mpi_safe_cond_select_sign( int a, int b, unsigned char second )
283{
284 /* In order to avoid questions about what we can reasonnably assume about
285 * the representations of signed integers, move everything to unsigned
286 * by taking advantage of the fact that a and b are either +1 or -1. */
287 unsigned ua = a + 1;
288 unsigned ub = b + 1;
289
290 /* MSVC has a warning about unary minus on unsigned integer types,
291 * but this is well-defined and precisely what we want to do here. */
292#if defined(_MSC_VER)
293#pragma warning( push )
294#pragma warning( disable : 4146 )
295#endif
296 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
297 const unsigned mask = -second;
298#if defined(_MSC_VER)
299#pragma warning( pop )
300#endif
301
302 /* select ua or ub */
303 unsigned ur = ( ua & ~mask ) | ( ub & mask );
304
305 /* ur is now 0 or 2, convert back to -1 or +1 */
306 return( (int) ur - 1 );
307}
308
Paul Bakker5121ce52009-01-03 21:22:43 +0000309/*
Gilles Peskinec81c5882020-06-04 19:14:58 +0200310 * Conditionally assign dest = src, without leaking information
311 * about whether the assignment was made or not.
312 * dest and src must be arrays of limbs of size n.
313 * assign must be 0 or 1.
314 */
315static void mpi_safe_cond_assign( size_t n,
316 mbedtls_mpi_uint *dest,
317 const mbedtls_mpi_uint *src,
318 unsigned char assign )
319{
320 size_t i;
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200321
322 /* MSVC has a warning about unary minus on unsigned integer types,
323 * but this is well-defined and precisely what we want to do here. */
324#if defined(_MSC_VER)
325#pragma warning( push )
326#pragma warning( disable : 4146 )
327#endif
328
329 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
330 const mbedtls_mpi_uint mask = -assign;
331
332#if defined(_MSC_VER)
333#pragma warning( pop )
334#endif
335
Gilles Peskinec81c5882020-06-04 19:14:58 +0200336 for( i = 0; i < n; i++ )
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200337 dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
Gilles Peskinec81c5882020-06-04 19:14:58 +0200338}
339
340/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100341 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100342 * about whether the assignment was made or not.
343 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100344 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100346{
347 int ret = 0;
348 size_t i;
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200349 mbedtls_mpi_uint limb_mask;
Hanno Becker73d7d792018-12-11 10:35:51 +0000350 MPI_VALIDATE_RET( X != NULL );
351 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100352
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200353 /* MSVC has a warning about unary minus on unsigned integer types,
354 * but this is well-defined and precisely what we want to do here. */
355#if defined(_MSC_VER)
356#pragma warning( push )
357#pragma warning( disable : 4146 )
358#endif
359
Pascal Junodb99183d2015-03-11 16:49:45 +0100360 /* make sure assign is 0 or 1 in a time-constant manner */
361 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200362 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200363 limb_mask = -assign;
364
365#if defined(_MSC_VER)
366#pragma warning( pop )
367#endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100370
Manuel Pégourié-Gonnarddc6a5f22021-06-07 09:51:00 +0200371 X->s = mpi_safe_cond_select_sign( X->s, Y->s, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100372
Gilles Peskinec81c5882020-06-04 19:14:58 +0200373 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100374
Gilles Peskinec81c5882020-06-04 19:14:58 +0200375 for( i = Y->n; i < X->n; i++ )
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200376 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100377
378cleanup:
379 return( ret );
380}
381
382/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100383 * Conditionally swap X and Y, without leaking information
384 * about whether the swap was made or not.
385 * Here it is not ok to simply swap the pointers, which whould lead to
386 * different memory access patterns when X and Y are used afterwards.
387 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100389{
390 int ret, s;
391 size_t i;
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200392 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000394 MPI_VALIDATE_RET( X != NULL );
395 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100396
397 if( X == Y )
398 return( 0 );
399
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200400 /* MSVC has a warning about unary minus on unsigned integer types,
401 * but this is well-defined and precisely what we want to do here. */
402#if defined(_MSC_VER)
403#pragma warning( push )
404#pragma warning( disable : 4146 )
405#endif
406
Pascal Junodb99183d2015-03-11 16:49:45 +0100407 /* make sure swap is 0 or 1 in a time-constant manner */
408 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200409 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200410 limb_mask = -swap;
411
412#if defined(_MSC_VER)
413#pragma warning( pop )
414#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
417 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100418
419 s = X->s;
Manuel Pégourié-Gonnarddc6a5f22021-06-07 09:51:00 +0200420 X->s = mpi_safe_cond_select_sign( X->s, Y->s, swap );
421 Y->s = mpi_safe_cond_select_sign( Y->s, s, swap );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100422
423
424 for( i = 0; i < X->n; i++ )
425 {
426 tmp = X->p[i];
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200427 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
428 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100429 }
430
431cleanup:
432 return( ret );
433}
434
435/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000436 * Set value from integer
437 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000439{
440 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000441 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444 memset( X->p, 0, X->n * ciL );
445
446 X->p[0] = ( z < 0 ) ? -z : z;
447 X->s = ( z < 0 ) ? -1 : 1;
448
449cleanup:
450
451 return( ret );
452}
453
454/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000455 * Get a specific bit
456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000458{
Hanno Becker73d7d792018-12-11 10:35:51 +0000459 MPI_VALIDATE_RET( X != NULL );
460
Paul Bakker2f5947e2011-05-18 15:47:11 +0000461 if( X->n * biL <= pos )
462 return( 0 );
463
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200464 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000465}
466
Gilles Peskine11cdb052018-11-20 16:47:47 +0100467/* Get a specific byte, without range checks. */
468#define GET_BYTE( X, i ) \
469 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
470
Paul Bakker2f5947e2011-05-18 15:47:11 +0000471/*
472 * Set a bit to a specific value of 0 or 1
473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000475{
476 int ret = 0;
477 size_t off = pos / biL;
478 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000479 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000480
481 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200483
Paul Bakker2f5947e2011-05-18 15:47:11 +0000484 if( X->n * biL <= pos )
485 {
486 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200487 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
493 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000494
495cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200496
Paul Bakker2f5947e2011-05-18 15:47:11 +0000497 return( ret );
498}
499
500/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200501 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000504{
Paul Bakker23986e52011-04-24 08:57:21 +0000505 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000506 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000507
508 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000509 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000510 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
511 return( count );
512
513 return( 0 );
514}
515
516/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000517 * Count leading zero bits in a given integer
518 */
519static size_t mbedtls_clz( const mbedtls_mpi_uint x )
520{
521 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100522 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000523
524 for( j = 0; j < biL; j++ )
525 {
526 if( x & mask ) break;
527
528 mask >>= 1;
529 }
530
531 return j;
532}
533
534/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200535 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000536 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200537size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000538{
Paul Bakker23986e52011-04-24 08:57:21 +0000539 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000540
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200541 if( X->n == 0 )
542 return( 0 );
543
Paul Bakker5121ce52009-01-03 21:22:43 +0000544 for( i = X->n - 1; i > 0; i-- )
545 if( X->p[i] != 0 )
546 break;
547
Simon Butcher15b15d12015-11-26 19:35:03 +0000548 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000549
Paul Bakker23986e52011-04-24 08:57:21 +0000550 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551}
552
553/*
554 * Return the total size in bytes
555 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000557{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200558 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559}
560
561/*
562 * Convert an ASCII character to digit value
563 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000565{
566 *d = 255;
567
568 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
569 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
570 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
571
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 if( *d >= (mbedtls_mpi_uint) radix )
573 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000574
575 return( 0 );
576}
577
578/*
579 * Import from an ASCII string
580 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000582{
Paul Bakker23986e52011-04-24 08:57:21 +0000583 int ret;
584 size_t i, j, slen, n;
Gilles Peskine984fd072021-04-03 18:26:13 +0200585 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_mpi_uint d;
587 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000588 MPI_VALIDATE_RET( X != NULL );
589 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000590
591 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000592 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
Gilles Peskine984fd072021-04-03 18:26:13 +0200596 if( s[0] == '-' )
597 {
598 ++s;
599 sign = -1;
600 }
601
Paul Bakkerff60ee62010-03-16 21:09:09 +0000602 slen = strlen( s );
603
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 if( radix == 16 )
605 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100606 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200607 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
608
Paul Bakkerff60ee62010-03-16 21:09:09 +0000609 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
612 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
Paul Bakker23986e52011-04-24 08:57:21 +0000614 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200617 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000618 }
619 }
620 else
621 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
Paul Bakkerff60ee62010-03-16 21:09:09 +0000624 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000625 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
627 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine984fd072021-04-03 18:26:13 +0200628 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000629 }
630 }
631
Gilles Peskine984fd072021-04-03 18:26:13 +0200632 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
633 X->s = -1;
634
Paul Bakker5121ce52009-01-03 21:22:43 +0000635cleanup:
636
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
639 return( ret );
640}
641
642/*
Ron Eldora16fa292018-11-20 14:07:01 +0200643 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000644 */
Ron Eldora16fa292018-11-20 14:07:01 +0200645static int mpi_write_hlp( mbedtls_mpi *X, int radix,
646 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000647{
648 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200650 size_t length = 0;
651 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
Ron Eldora16fa292018-11-20 14:07:01 +0200653 do
654 {
655 if( length >= buflen )
656 {
657 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
658 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
Ron Eldora16fa292018-11-20 14:07:01 +0200660 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
661 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
662 /*
663 * Write the residue in the current position, as an ASCII character.
664 */
665 if( r < 0xA )
666 *(--p_end) = (char)( '0' + r );
667 else
668 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
Ron Eldora16fa292018-11-20 14:07:01 +0200670 length++;
671 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000672
Ron Eldora16fa292018-11-20 14:07:01 +0200673 memmove( *p, p_end, length );
674 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000675
676cleanup:
677
678 return( ret );
679}
680
681/*
682 * Export into an ASCII string
683 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100684int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
685 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000686{
Paul Bakker23986e52011-04-24 08:57:21 +0000687 int ret = 0;
688 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000691 MPI_VALIDATE_RET( X != NULL );
692 MPI_VALIDATE_RET( olen != NULL );
693 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000694
695 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000696 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000698 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
699 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
700 * `n`. If radix > 4, this might be a strict
701 * overapproximation of the number of
702 * radix-adic digits needed to present `n`. */
703 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
704 * present `n`. */
705
Janos Follath870ed002019-03-06 13:43:02 +0000706 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000707 n += 1; /* Compensate for the divisions above, which round down `n`
708 * in case it's not even. */
709 n += 1; /* Potential '-'-sign. */
710 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
711 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000712
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100713 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000714 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100715 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000717 }
718
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100719 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000721
722 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000723 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000724 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000725 buflen--;
726 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000727
728 if( radix == 16 )
729 {
Paul Bakker23986e52011-04-24 08:57:21 +0000730 int c;
731 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
Paul Bakker23986e52011-04-24 08:57:21 +0000733 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 {
Paul Bakker23986e52011-04-24 08:57:21 +0000735 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000736 {
Paul Bakker23986e52011-04-24 08:57:21 +0000737 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
Paul Bakker6c343d72014-07-10 14:36:19 +0200739 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000740 continue;
741
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000742 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000743 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000744 k = 1;
745 }
746 }
747 }
748 else
749 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000751
752 if( T.s == -1 )
753 T.s = 1;
754
Ron Eldora16fa292018-11-20 14:07:01 +0200755 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000756 }
757
758 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100759 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000760
761cleanup:
762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
765 return( ret );
766}
767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000769/*
770 * Read X from an opened file
771 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200772int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000773{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000775 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000776 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000777 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000778 * Buffer should have space for (short) label and decimal formatted MPI,
779 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000780 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
Hanno Becker73d7d792018-12-11 10:35:51 +0000783 MPI_VALIDATE_RET( X != NULL );
784 MPI_VALIDATE_RET( fin != NULL );
785
786 if( radix < 2 || radix > 16 )
787 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
788
Paul Bakker5121ce52009-01-03 21:22:43 +0000789 memset( s, 0, sizeof( s ) );
790 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200791 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000792
793 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000794 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200795 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000796
Hanno Beckerb2034b72017-04-26 11:46:46 +0100797 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
798 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000799
800 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100801 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000802 if( mpi_get_digit( &d, radix, *p ) != 0 )
803 break;
804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000806}
807
808/*
809 * Write X into an opened file (or stdout if fout == NULL)
810 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000812{
Paul Bakker23986e52011-04-24 08:57:21 +0000813 int ret;
814 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000815 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000816 * Buffer should have space for (short) label and decimal formatted MPI,
817 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000820 MPI_VALIDATE_RET( X != NULL );
821
822 if( radix < 2 || radix > 16 )
823 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000824
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100825 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000826
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100827 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000828
829 if( p == NULL ) p = "";
830
831 plen = strlen( p );
832 slen = strlen( s );
833 s[slen++] = '\r';
834 s[slen++] = '\n';
835
836 if( fout != NULL )
837 {
838 if( fwrite( p, 1, plen, fout ) != plen ||
839 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000841 }
842 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200843 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000844
845cleanup:
846
847 return( ret );
848}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
Hanno Beckerda1655a2017-10-18 14:21:44 +0100851
852/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
853 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000854
855static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
856{
857 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100858 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000859 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100860
861 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
862 {
863 tmp <<= CHAR_BIT;
864 tmp |= (mbedtls_mpi_uint) *x_ptr;
865 }
866
Hanno Beckerf8720072018-11-08 11:53:49 +0000867 return( tmp );
868}
869
870static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
871{
872#if defined(__BYTE_ORDER__)
873
874/* Nothing to do on bigendian systems. */
875#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
876 return( x );
877#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
878
879#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
880
881/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000882#if defined(__GNUC__) && defined(__GNUC_PREREQ)
883#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000884#define have_bswap
885#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000886#endif
887
888#if defined(__clang__) && defined(__has_builtin)
889#if __has_builtin(__builtin_bswap32) && \
890 __has_builtin(__builtin_bswap64)
891#define have_bswap
892#endif
893#endif
894
Hanno Beckerf8720072018-11-08 11:53:49 +0000895#if defined(have_bswap)
896 /* The compiler is hopefully able to statically evaluate this! */
897 switch( sizeof(mbedtls_mpi_uint) )
898 {
899 case 4:
900 return( __builtin_bswap32(x) );
901 case 8:
902 return( __builtin_bswap64(x) );
903 }
904#endif
905#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
906#endif /* __BYTE_ORDER__ */
907
908 /* Fall back to C-based reordering if we don't know the byte order
909 * or we couldn't use a compiler-specific builtin. */
910 return( mpi_uint_bigendian_to_host_c( x ) );
911}
912
Hanno Becker2be8a552018-10-25 12:40:09 +0100913static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100914{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100915 mbedtls_mpi_uint *cur_limb_left;
916 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100917 if( limbs == 0 )
918 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100919
920 /*
921 * Traverse limbs and
922 * - adapt byte-order in each limb
923 * - swap the limbs themselves.
924 * For that, simultaneously traverse the limbs from left to right
925 * and from right to left, as long as the left index is not bigger
926 * than the right index (it's not a problem if limbs is odd and the
927 * indices coincide in the last iteration).
928 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100929 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
930 cur_limb_left <= cur_limb_right;
931 cur_limb_left++, cur_limb_right-- )
932 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000933 mbedtls_mpi_uint tmp;
934 /* Note that if cur_limb_left == cur_limb_right,
935 * this code effectively swaps the bytes only once. */
936 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
937 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
938 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100939 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100940}
941
Paul Bakker5121ce52009-01-03 21:22:43 +0000942/*
943 * Import X from unsigned binary data, big endian
944 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000946{
Paul Bakker23986e52011-04-24 08:57:21 +0000947 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100948 size_t const limbs = CHARS_TO_LIMBS( buflen );
949 size_t const overhead = ( limbs * ciL ) - buflen;
950 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
Hanno Becker8ce11a32018-12-19 16:18:52 +0000952 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000953 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
954
Hanno Becker073c1992017-10-17 15:17:27 +0100955 /* Ensure that target MPI has exactly the necessary number of limbs */
956 if( X->n != limbs )
957 {
958 mbedtls_mpi_free( X );
959 mbedtls_mpi_init( X );
960 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
961 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200962 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000963
Hanno Becker0e810b92019-01-03 17:13:11 +0000964 /* Avoid calling `memcpy` with NULL source argument,
965 * even if buflen is 0. */
966 if( buf != NULL )
967 {
968 Xp = (unsigned char*) X->p;
969 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100970
Hanno Becker0e810b92019-01-03 17:13:11 +0000971 mpi_bigendian_to_host( X->p, limbs );
972 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000973
974cleanup:
975
976 return( ret );
977}
978
979/*
980 * Export X into unsigned binary data, big endian
981 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100982int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
983 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000984{
Hanno Becker73d7d792018-12-11 10:35:51 +0000985 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100986 size_t bytes_to_copy;
987 unsigned char *p;
988 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000989
Hanno Becker73d7d792018-12-11 10:35:51 +0000990 MPI_VALIDATE_RET( X != NULL );
991 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
992
993 stored_bytes = X->n * ciL;
994
Gilles Peskine11cdb052018-11-20 16:47:47 +0100995 if( stored_bytes < buflen )
996 {
997 /* There is enough space in the output buffer. Write initial
998 * null bytes and record the position at which to start
999 * writing the significant bytes. In this case, the execution
1000 * trace of this function does not depend on the value of the
1001 * number. */
1002 bytes_to_copy = stored_bytes;
1003 p = buf + buflen - stored_bytes;
1004 memset( buf, 0, buflen - stored_bytes );
1005 }
1006 else
1007 {
1008 /* The output buffer is smaller than the allocated size of X.
1009 * However X may fit if its leading bytes are zero. */
1010 bytes_to_copy = buflen;
1011 p = buf;
1012 for( i = bytes_to_copy; i < stored_bytes; i++ )
1013 {
1014 if( GET_BYTE( X, i ) != 0 )
1015 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1016 }
1017 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001018
Gilles Peskine11cdb052018-11-20 16:47:47 +01001019 for( i = 0; i < bytes_to_copy; i++ )
1020 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021
1022 return( 0 );
1023}
1024
1025/*
1026 * Left-shift: X <<= count
1027 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001028int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001029{
Paul Bakker23986e52011-04-24 08:57:21 +00001030 int ret;
1031 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001032 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001033 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034
1035 v0 = count / (biL );
1036 t1 = count & (biL - 1);
1037
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001038 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001039
Paul Bakkerf9688572011-05-05 10:00:45 +00001040 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001042
1043 ret = 0;
1044
1045 /*
1046 * shift by count / limb_size
1047 */
1048 if( v0 > 0 )
1049 {
Paul Bakker23986e52011-04-24 08:57:21 +00001050 for( i = X->n; i > v0; i-- )
1051 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001052
Paul Bakker23986e52011-04-24 08:57:21 +00001053 for( ; i > 0; i-- )
1054 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 }
1056
1057 /*
1058 * shift by count % limb_size
1059 */
1060 if( t1 > 0 )
1061 {
1062 for( i = v0; i < X->n; i++ )
1063 {
1064 r1 = X->p[i] >> (biL - t1);
1065 X->p[i] <<= t1;
1066 X->p[i] |= r0;
1067 r0 = r1;
1068 }
1069 }
1070
1071cleanup:
1072
1073 return( ret );
1074}
1075
1076/*
1077 * Right-shift: X >>= count
1078 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001080{
Paul Bakker23986e52011-04-24 08:57:21 +00001081 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001083 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
1085 v0 = count / biL;
1086 v1 = count & (biL - 1);
1087
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001088 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001090
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 /*
1092 * shift by count / limb_size
1093 */
1094 if( v0 > 0 )
1095 {
1096 for( i = 0; i < X->n - v0; i++ )
1097 X->p[i] = X->p[i + v0];
1098
1099 for( ; i < X->n; i++ )
1100 X->p[i] = 0;
1101 }
1102
1103 /*
1104 * shift by count % limb_size
1105 */
1106 if( v1 > 0 )
1107 {
Paul Bakker23986e52011-04-24 08:57:21 +00001108 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001109 {
Paul Bakker23986e52011-04-24 08:57:21 +00001110 r1 = X->p[i - 1] << (biL - v1);
1111 X->p[i - 1] >>= v1;
1112 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001113 r0 = r1;
1114 }
1115 }
1116
1117 return( 0 );
1118}
1119
1120/*
1121 * Compare unsigned values
1122 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001124{
Paul Bakker23986e52011-04-24 08:57:21 +00001125 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001126 MPI_VALIDATE_RET( X != NULL );
1127 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001128
Paul Bakker23986e52011-04-24 08:57:21 +00001129 for( i = X->n; i > 0; i-- )
1130 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001131 break;
1132
Paul Bakker23986e52011-04-24 08:57:21 +00001133 for( j = Y->n; j > 0; j-- )
1134 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001135 break;
1136
Paul Bakker23986e52011-04-24 08:57:21 +00001137 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001138 return( 0 );
1139
1140 if( i > j ) return( 1 );
1141 if( j > i ) return( -1 );
1142
Paul Bakker23986e52011-04-24 08:57:21 +00001143 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 {
Paul Bakker23986e52011-04-24 08:57:21 +00001145 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1146 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001147 }
1148
1149 return( 0 );
1150}
1151
1152/*
1153 * Compare signed values
1154 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001155int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001156{
Paul Bakker23986e52011-04-24 08:57:21 +00001157 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001158 MPI_VALIDATE_RET( X != NULL );
1159 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001160
Paul Bakker23986e52011-04-24 08:57:21 +00001161 for( i = X->n; i > 0; i-- )
1162 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001163 break;
1164
Paul Bakker23986e52011-04-24 08:57:21 +00001165 for( j = Y->n; j > 0; j-- )
1166 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 break;
1168
Paul Bakker23986e52011-04-24 08:57:21 +00001169 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001170 return( 0 );
1171
1172 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001173 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
1175 if( X->s > 0 && Y->s < 0 ) return( 1 );
1176 if( Y->s > 0 && X->s < 0 ) return( -1 );
1177
Paul Bakker23986e52011-04-24 08:57:21 +00001178 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001179 {
Paul Bakker23986e52011-04-24 08:57:21 +00001180 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1181 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001182 }
1183
1184 return( 0 );
1185}
1186
Janos Follath45ec9902019-10-14 09:09:32 +01001187/** Decide if an integer is less than the other, without branches.
1188 *
1189 * \param x First integer.
1190 * \param y Second integer.
1191 *
1192 * \return 1 if \p x is less than \p y, 0 otherwise
1193 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001194static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1195 const mbedtls_mpi_uint y )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001196{
1197 mbedtls_mpi_uint ret;
1198 mbedtls_mpi_uint cond;
1199
1200 /*
1201 * Check if the most significant bits (MSB) of the operands are different.
1202 */
1203 cond = ( x ^ y );
1204 /*
1205 * If the MSB are the same then the difference x-y will be negative (and
1206 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1207 */
1208 ret = ( x - y ) & ~cond;
1209 /*
1210 * If the MSB are different, then the operand with the MSB of 1 is the
1211 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1212 * the MSB of y is 0.)
1213 */
1214 ret |= y & cond;
1215
1216
Janos Follath7a34bcf2019-10-14 08:59:14 +01001217 ret = ret >> ( biL - 1 );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001218
Janos Follath359a01e2019-10-29 15:08:46 +00001219 return (unsigned) ret;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001220}
1221
1222/*
1223 * Compare signed values in constant time
1224 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001225int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1226 unsigned *ret )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001227{
1228 size_t i;
Janos Follathbd87a592019-10-28 12:23:18 +00001229 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001230 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001231
1232 MPI_VALIDATE_RET( X != NULL );
1233 MPI_VALIDATE_RET( Y != NULL );
1234 MPI_VALIDATE_RET( ret != NULL );
1235
1236 if( X->n != Y->n )
1237 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1238
1239 /*
Janos Follath58525182019-10-28 12:12:15 +00001240 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1241 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001242 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001243 X_is_negative = ( X->s & 2 ) >> 1;
1244 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath867a3ab2019-10-11 14:21:53 +01001245
1246 /*
1247 * If the signs are different, then the positive operand is the bigger.
Janos Follath1f21c1d2019-10-28 12:31:34 +00001248 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1249 * is false if X is positive (X_is_negative == 0).
Janos Follath867a3ab2019-10-11 14:21:53 +01001250 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001251 cond = ( X_is_negative ^ Y_is_negative );
1252 *ret = cond & X_is_negative;
Janos Follath867a3ab2019-10-11 14:21:53 +01001253
1254 /*
Janos Follathbd87a592019-10-28 12:23:18 +00001255 * This is a constant-time function. We might have the result, but we still
Janos Follath867a3ab2019-10-11 14:21:53 +01001256 * need to go through the loop. Record if we have the result already.
1257 */
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001258 done = cond;
1259
1260 for( i = X->n; i > 0; i-- )
1261 {
1262 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001263 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1264 * X and Y are negative.
Janos Follath867a3ab2019-10-11 14:21:53 +01001265 *
1266 * Again even if we can make a decision, we just mark the result and
1267 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001268 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001269 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1270 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathfbe4c942019-10-28 12:37:21 +00001271 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001272
1273 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001274 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1275 * X and Y are positive.
Janos Follath867a3ab2019-10-11 14:21:53 +01001276 *
1277 * Again even if we can make a decision, we just mark the result and
1278 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001279 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001280 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1281 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathfbe4c942019-10-28 12:37:21 +00001282 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001283 }
1284
1285 return( 0 );
1286}
1287
Paul Bakker5121ce52009-01-03 21:22:43 +00001288/*
1289 * Compare signed values
1290 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001292{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293 mbedtls_mpi Y;
1294 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001295 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001296
1297 *p = ( z < 0 ) ? -z : z;
1298 Y.s = ( z < 0 ) ? -1 : 1;
1299 Y.n = 1;
1300 Y.p = p;
1301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001302 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001303}
1304
1305/*
1306 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001308int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001309{
Paul Bakker23986e52011-04-24 08:57:21 +00001310 int ret;
1311 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001312 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001313 MPI_VALIDATE_RET( X != NULL );
1314 MPI_VALIDATE_RET( A != NULL );
1315 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001316
1317 if( X == B )
1318 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001320 }
1321
1322 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001324
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001325 /*
1326 * X should always be positive as a result of unsigned additions.
1327 */
1328 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001329
Paul Bakker23986e52011-04-24 08:57:21 +00001330 for( j = B->n; j > 0; j-- )
1331 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 break;
1333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001335
1336 o = B->p; p = X->p; c = 0;
1337
Janos Follath6c922682015-10-30 17:43:11 +01001338 /*
1339 * tmp is used because it might happen that p == o
1340 */
Paul Bakker23986e52011-04-24 08:57:21 +00001341 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 {
Janos Follath6c922682015-10-30 17:43:11 +01001343 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001344 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001345 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001346 }
1347
1348 while( c != 0 )
1349 {
1350 if( i >= X->n )
1351 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353 p = X->p + i;
1354 }
1355
Paul Bakker2d319fd2012-09-16 21:34:26 +00001356 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001357 }
1358
1359cleanup:
1360
1361 return( ret );
1362}
1363
Gilles Peskinede719d52020-06-09 10:39:38 +02001364/**
Gilles Peskine36acd542020-06-08 21:58:22 +02001365 * Helper for mbedtls_mpi subtraction.
1366 *
1367 * Calculate d - s where d and s have the same size.
1368 * This function operates modulo (2^ciL)^n and returns the carry
1369 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1370 *
1371 * \param n Number of limbs of \p d and \p s.
1372 * \param[in,out] d On input, the left operand.
1373 * On output, the result of the subtraction:
Gilles Peskinede719d52020-06-09 10:39:38 +02001374 * \param[in] s The right operand.
Gilles Peskine36acd542020-06-08 21:58:22 +02001375 *
1376 * \return 1 if `d < s`.
1377 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 */
Gilles Peskine36acd542020-06-08 21:58:22 +02001379static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1380 mbedtls_mpi_uint *d,
1381 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001382{
Paul Bakker23986e52011-04-24 08:57:21 +00001383 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001385
1386 for( i = c = 0; i < n; i++, s++, d++ )
1387 {
1388 z = ( *d < c ); *d -= c;
1389 c = ( *d < *s ) + z; *d -= *s;
1390 }
1391
Gilles Peskine36acd542020-06-08 21:58:22 +02001392 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393}
1394
1395/*
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001396 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001399{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001401 int ret;
1402 size_t n;
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001403 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001404 MPI_VALIDATE_RET( X != NULL );
1405 MPI_VALIDATE_RET( A != NULL );
1406 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409
1410 if( X == B )
1411 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 B = &TB;
1414 }
1415
1416 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001418
Paul Bakker1ef7a532009-06-20 10:50:55 +00001419 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001420 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001421 */
1422 X->s = 1;
1423
Paul Bakker5121ce52009-01-03 21:22:43 +00001424 ret = 0;
1425
Paul Bakker23986e52011-04-24 08:57:21 +00001426 for( n = B->n; n > 0; n-- )
1427 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001428 break;
Gilles Peskine6260b702021-01-27 22:30:43 +01001429 if( n > A->n )
1430 {
1431 /* B >= (2^ciL)^n > A */
1432 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1433 goto cleanup;
1434 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001435
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001436 carry = mpi_sub_hlp( n, X->p, B->p );
1437 if( carry != 0 )
Gilles Peskine36acd542020-06-08 21:58:22 +02001438 {
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001439 /* Propagate the carry to the first nonzero limb of X. */
1440 for( ; n < X->n && X->p[n] == 0; n++ )
1441 --X->p[n];
1442 /* If we ran out of space for the carry, it means that the result
1443 * is negative. */
1444 if( n == X->n )
Gilles Peskine84697ca2020-07-23 01:16:46 +02001445 {
1446 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1447 goto cleanup;
1448 }
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001449 --X->p[n];
Gilles Peskine36acd542020-06-08 21:58:22 +02001450 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001451
1452cleanup:
1453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001454 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001455
1456 return( ret );
1457}
1458
1459/*
1460 * Signed addition: X = A + B
1461 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001463{
Hanno Becker73d7d792018-12-11 10:35:51 +00001464 int ret, s;
1465 MPI_VALIDATE_RET( X != NULL );
1466 MPI_VALIDATE_RET( A != NULL );
1467 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001468
Hanno Becker73d7d792018-12-11 10:35:51 +00001469 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001470 if( A->s * B->s < 0 )
1471 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001473 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001475 X->s = s;
1476 }
1477 else
1478 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001479 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001480 X->s = -s;
1481 }
1482 }
1483 else
1484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001486 X->s = s;
1487 }
1488
1489cleanup:
1490
1491 return( ret );
1492}
1493
1494/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001495 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001496 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001498{
Hanno Becker73d7d792018-12-11 10:35:51 +00001499 int ret, s;
1500 MPI_VALIDATE_RET( X != NULL );
1501 MPI_VALIDATE_RET( A != NULL );
1502 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001503
Hanno Becker73d7d792018-12-11 10:35:51 +00001504 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001505 if( A->s * B->s > 0 )
1506 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 X->s = s;
1511 }
1512 else
1513 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001515 X->s = -s;
1516 }
1517 }
1518 else
1519 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 X->s = s;
1522 }
1523
1524cleanup:
1525
1526 return( ret );
1527}
1528
1529/*
1530 * Signed addition: X = A + b
1531 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001532int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001533{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 mbedtls_mpi _B;
1535 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001536 MPI_VALIDATE_RET( X != NULL );
1537 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
1539 p[0] = ( b < 0 ) ? -b : b;
1540 _B.s = ( b < 0 ) ? -1 : 1;
1541 _B.n = 1;
1542 _B.p = p;
1543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001545}
1546
1547/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001548 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001549 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001551{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 mbedtls_mpi _B;
1553 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001554 MPI_VALIDATE_RET( X != NULL );
1555 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001556
1557 p[0] = ( b < 0 ) ? -b : b;
1558 _B.s = ( b < 0 ) ? -1 : 1;
1559 _B.n = 1;
1560 _B.p = p;
1561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001563}
1564
1565/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001567 */
1568static
1569#if defined(__APPLE__) && defined(__arm__)
1570/*
1571 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1572 * appears to need this to prevent bad ARM code generation at -O3.
1573 */
1574__attribute__ ((noinline))
1575#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001577{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001579
1580#if defined(MULADDC_HUIT)
1581 for( ; i >= 8; i -= 8 )
1582 {
1583 MULADDC_INIT
1584 MULADDC_HUIT
1585 MULADDC_STOP
1586 }
1587
1588 for( ; i > 0; i-- )
1589 {
1590 MULADDC_INIT
1591 MULADDC_CORE
1592 MULADDC_STOP
1593 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001594#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001595 for( ; i >= 16; i -= 16 )
1596 {
1597 MULADDC_INIT
1598 MULADDC_CORE MULADDC_CORE
1599 MULADDC_CORE MULADDC_CORE
1600 MULADDC_CORE MULADDC_CORE
1601 MULADDC_CORE MULADDC_CORE
1602
1603 MULADDC_CORE MULADDC_CORE
1604 MULADDC_CORE MULADDC_CORE
1605 MULADDC_CORE MULADDC_CORE
1606 MULADDC_CORE MULADDC_CORE
1607 MULADDC_STOP
1608 }
1609
1610 for( ; i >= 8; i -= 8 )
1611 {
1612 MULADDC_INIT
1613 MULADDC_CORE MULADDC_CORE
1614 MULADDC_CORE MULADDC_CORE
1615
1616 MULADDC_CORE MULADDC_CORE
1617 MULADDC_CORE MULADDC_CORE
1618 MULADDC_STOP
1619 }
1620
1621 for( ; i > 0; i-- )
1622 {
1623 MULADDC_INIT
1624 MULADDC_CORE
1625 MULADDC_STOP
1626 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001627#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001628
1629 t++;
1630
1631 do {
1632 *d += c; c = ( *d < c ); d++;
1633 }
1634 while( c != 0 );
1635}
1636
1637/*
1638 * Baseline multiplication: X = A * B (HAC 14.12)
1639 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001641{
Paul Bakker23986e52011-04-24 08:57:21 +00001642 int ret;
1643 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001645 MPI_VALIDATE_RET( X != NULL );
1646 MPI_VALIDATE_RET( A != NULL );
1647 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1652 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001653
Paul Bakker23986e52011-04-24 08:57:21 +00001654 for( i = A->n; i > 0; i-- )
1655 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001656 break;
1657
Paul Bakker23986e52011-04-24 08:57:21 +00001658 for( j = B->n; j > 0; j-- )
1659 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001660 break;
1661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1663 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001665 for( ; j > 0; j-- )
1666 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
1668 X->s = A->s * B->s;
1669
1670cleanup:
1671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001672 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
1674 return( ret );
1675}
1676
1677/*
1678 * Baseline multiplication: X = A * b
1679 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001681{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 mbedtls_mpi _B;
1683 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001684 MPI_VALIDATE_RET( X != NULL );
1685 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
1687 _B.s = 1;
1688 _B.n = 1;
1689 _B.p = p;
1690 p[0] = b;
1691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693}
1694
1695/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001696 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1697 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001698 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001699static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1700 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001701{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001702#if defined(MBEDTLS_HAVE_UDBL)
1703 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001704#else
Simon Butcher9803d072016-01-03 00:24:34 +00001705 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1706 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001707 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1708 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001709 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001710#endif
1711
Simon Butcher15b15d12015-11-26 19:35:03 +00001712 /*
1713 * Check for overflow
1714 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001715 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001716 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001717 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001718
Simon Butcherf5ba0452015-12-27 23:01:55 +00001719 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001720 }
1721
1722#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001723 dividend = (mbedtls_t_udbl) u1 << biL;
1724 dividend |= (mbedtls_t_udbl) u0;
1725 quotient = dividend / d;
1726 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1727 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1728
1729 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001730 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001731
1732 return (mbedtls_mpi_uint) quotient;
1733#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001734
1735 /*
1736 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1737 * Vol. 2 - Seminumerical Algorithms, Knuth
1738 */
1739
1740 /*
1741 * Normalize the divisor, d, and dividend, u0, u1
1742 */
1743 s = mbedtls_clz( d );
1744 d = d << s;
1745
1746 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001747 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001748 u0 = u0 << s;
1749
1750 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001751 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001752
1753 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001754 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001755
1756 /*
1757 * Find the first quotient and remainder
1758 */
1759 q1 = u1 / d1;
1760 r0 = u1 - d1 * q1;
1761
1762 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1763 {
1764 q1 -= 1;
1765 r0 += d1;
1766
1767 if ( r0 >= radix ) break;
1768 }
1769
Simon Butcherf5ba0452015-12-27 23:01:55 +00001770 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001771 q0 = rAX / d1;
1772 r0 = rAX - q0 * d1;
1773
1774 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1775 {
1776 q0 -= 1;
1777 r0 += d1;
1778
1779 if ( r0 >= radix ) break;
1780 }
1781
1782 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001783 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001784
1785 quotient = q1 * radix + q0;
1786
1787 return quotient;
1788#endif
1789}
1790
1791/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001793 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001794int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1795 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001796{
Paul Bakker23986e52011-04-24 08:57:21 +00001797 int ret;
1798 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001800 MPI_VALIDATE_RET( A != NULL );
1801 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1804 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001805
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1807 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001810 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1812 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001813 return( 0 );
1814 }
1815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1817 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001818 X.s = Y.s = 1;
1819
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1821 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1822 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1823 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001824
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001825 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001826 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001827 {
1828 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1830 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831 }
1832 else k = 0;
1833
1834 n = X.n - 1;
1835 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001839 {
1840 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844
1845 for( i = n; i > t ; i-- )
1846 {
1847 if( X.p[i] >= Y.p[t] )
1848 Z.p[i - t - 1] = ~0;
1849 else
1850 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001851 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1852 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 }
1854
1855 Z.p[i - t - 1]++;
1856 do
1857 {
1858 Z.p[i - t - 1]--;
1859
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001861 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001862 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001864
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001865 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001866 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1867 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001868 T2.p[2] = X.p[i];
1869 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1873 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1874 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001877 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1879 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 Z.p[i - t - 1]--;
1882 }
1883 }
1884
1885 if( Q != NULL )
1886 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888 Q->s = A->s * B->s;
1889 }
1890
1891 if( R != NULL )
1892 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001894 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001898 R->s = 1;
1899 }
1900
1901cleanup:
1902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1904 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001905
1906 return( ret );
1907}
1908
1909/*
1910 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001911 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001912int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1913 const mbedtls_mpi *A,
1914 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001915{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 mbedtls_mpi _B;
1917 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001918 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919
1920 p[0] = ( b < 0 ) ? -b : b;
1921 _B.s = ( b < 0 ) ? -1 : 1;
1922 _B.n = 1;
1923 _B.p = p;
1924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926}
1927
1928/*
1929 * Modulo: R = A mod B
1930 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001932{
1933 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001934 MPI_VALIDATE_RET( R != NULL );
1935 MPI_VALIDATE_RET( A != NULL );
1936 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1939 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1944 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1947 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948
1949cleanup:
1950
1951 return( ret );
1952}
1953
1954/*
1955 * Modulo: r = A mod b
1956 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001958{
Paul Bakker23986e52011-04-24 08:57:21 +00001959 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001961 MPI_VALIDATE_RET( r != NULL );
1962 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963
1964 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001965 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
1967 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 /*
1971 * handle trivial cases
1972 */
1973 if( b == 1 )
1974 {
1975 *r = 0;
1976 return( 0 );
1977 }
1978
1979 if( b == 2 )
1980 {
1981 *r = A->p[0] & 1;
1982 return( 0 );
1983 }
1984
1985 /*
1986 * general case
1987 */
Paul Bakker23986e52011-04-24 08:57:21 +00001988 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001989 {
Paul Bakker23986e52011-04-24 08:57:21 +00001990 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001991 y = ( y << biH ) | ( x >> biH );
1992 z = y / b;
1993 y -= z * b;
1994
1995 x <<= biH;
1996 y = ( y << biH ) | ( x >> biH );
1997 z = y / b;
1998 y -= z * b;
1999 }
2000
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002001 /*
2002 * If A is negative, then the current y represents a negative value.
2003 * Flipping it to the positive side.
2004 */
2005 if( A->s < 0 && y != 0 )
2006 y = b - y;
2007
Paul Bakker5121ce52009-01-03 21:22:43 +00002008 *r = y;
2009
2010 return( 0 );
2011}
2012
2013/*
2014 * Fast Montgomery initialization (thanks to Tom St Denis)
2015 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002017{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002019 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
2021 x = m0;
2022 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002023
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002024 for( i = biL; i >= 8; i /= 2 )
2025 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
2027 *mm = ~x + 1;
2028}
2029
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02002030/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2031 *
2032 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine635a3742020-06-08 22:37:50 +02002033 * It must have at least as many limbs as N
2034 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02002035 * On successful completion, A contains the result of
2036 * the multiplication A * B * R^-1 mod N where
2037 * R = (2^ciL)^n.
2038 * \param[in] B One of the numbers to multiply.
2039 * It must be nonzero and must not have more limbs than N
2040 * (B->n <= N->n).
2041 * \param[in] N The modulo. N must be odd.
2042 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2043 * This is -N^-1 mod 2^ciL.
2044 * \param[in,out] T A bignum for temporary storage.
2045 * It must be at least twice the limb size of N plus 2
2046 * (T->n >= 2 * (N->n + 1)).
2047 * Its initial content is unused and
2048 * its final content is indeterminate.
2049 * Note that unlike the usual convention in the library
2050 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002051 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002052static 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 +02002053 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002054{
Paul Bakker23986e52011-04-24 08:57:21 +00002055 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002057
2058 memset( T->p, 0, T->n * ciL );
2059
2060 d = T->p;
2061 n = N->n;
2062 m = ( B->n < n ) ? B->n : n;
2063
2064 for( i = 0; i < n; i++ )
2065 {
2066 /*
2067 * T = (T + u0*B + u1*N) / 2^biL
2068 */
2069 u0 = A->p[i];
2070 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2071
2072 mpi_mul_hlp( m, B->p, d, u0 );
2073 mpi_mul_hlp( n, N->p, d, u1 );
2074
2075 *d++ = u0; d[n + 1] = 0;
2076 }
2077
Gilles Peskine635a3742020-06-08 22:37:50 +02002078 /* At this point, d is either the desired result or the desired result
2079 * plus N. We now potentially subtract N, avoiding leaking whether the
2080 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
Gilles Peskine635a3742020-06-08 22:37:50 +02002082 /* Copy the n least significant limbs of d to A, so that
2083 * A = d if d < N (recall that N has n limbs). */
2084 memcpy( A->p, d, n * ciL );
Gilles Peskinede719d52020-06-09 10:39:38 +02002085 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine635a3742020-06-08 22:37:50 +02002086 * do the calculation without using conditional tests. */
2087 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine8f672662020-06-04 21:05:24 +02002088 d[n] += 1;
Gilles Peskine36acd542020-06-08 21:58:22 +02002089 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskine635a3742020-06-08 22:37:50 +02002090 /* If d0 < N then d < (2^biL)^n
2091 * so d[n] == 0 and we want to keep A as it is.
2092 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2093 * so d[n] == 1 and we want to set A to the result of the subtraction
2094 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2095 * This exactly corresponds to a conditional assignment. */
2096 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097}
2098
2099/*
2100 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02002101 *
2102 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002103 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002104static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2105 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002106{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 mbedtls_mpi_uint z = 1;
2108 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
Paul Bakker8ddb6452013-02-27 14:56:33 +01002110 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002111 U.p = &z;
2112
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002113 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114}
2115
Manuel Pégourié-Gonnard432ebba2021-06-03 10:42:46 +02002116/*
2117 * Constant-flow boolean "equal" comparison:
2118 * return x == y
2119 *
2120 * This function can be used to write constant-time code by replacing branches
2121 * with bit operations - it can be used in conjunction with
2122 * mbedtls_ssl_cf_mask_from_bit().
2123 *
2124 * This function is implemented without using comparison operators, as those
2125 * might be translated to branches by some compilers on some platforms.
2126 */
2127static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2128{
2129 /* diff = 0 if x == y, non-zero otherwise */
2130 const size_t diff = x ^ y;
2131
2132 /* MSVC has a warning about unary minus on unsigned integer types,
2133 * but this is well-defined and precisely what we want to do here. */
2134#if defined(_MSC_VER)
2135#pragma warning( push )
2136#pragma warning( disable : 4146 )
2137#endif
2138
2139 /* diff_msb's most significant bit is equal to x != y */
2140 const size_t diff_msb = ( diff | -diff );
2141
2142#if defined(_MSC_VER)
2143#pragma warning( pop )
2144#endif
2145
2146 /* diff1 = (x != y) ? 1 : 0 */
2147 const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2148
2149 return( 1 ^ diff1 );
2150}
2151
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002152/**
2153 * Select an MPI from a table without leaking the index.
2154 *
2155 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2156 * reads the entire table in order to avoid leaking the value of idx to an
2157 * attacker able to observe memory access patterns.
2158 *
2159 * \param[out] R Where to write the selected MPI.
2160 * \param[in] T The table to read from.
2161 * \param[in] T_size The number of elements in the table.
2162 * \param[in] idx The index of the element to select;
2163 * this must satisfy 0 <= idx < T_size.
2164 *
2165 * \return \c 0 on success, or a negative error code.
2166 */
2167static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2168{
2169 int ret;
2170
2171 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard432ebba2021-06-03 10:42:46 +02002172 {
2173 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
2174 mbedtls_mpi_cf_bool_eq( i, idx ) ) );
2175 }
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002176
2177cleanup:
2178 return( ret );
2179}
2180
Paul Bakker5121ce52009-01-03 21:22:43 +00002181/*
2182 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2183 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002184int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2185 const mbedtls_mpi *E, const mbedtls_mpi *N,
2186 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002187{
Paul Bakker23986e52011-04-24 08:57:21 +00002188 int ret;
2189 size_t wbits, wsize, one = 1;
2190 size_t i, j, nblimbs;
2191 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002193 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002194 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002195
Hanno Becker73d7d792018-12-11 10:35:51 +00002196 MPI_VALIDATE_RET( X != NULL );
2197 MPI_VALIDATE_RET( A != NULL );
2198 MPI_VALIDATE_RET( E != NULL );
2199 MPI_VALIDATE_RET( N != NULL );
2200
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002201 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2205 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002206
Chris Jonesad59a2a2020-11-25 15:12:39 +00002207 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2208 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2209 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2210
Paul Bakkerf6198c12012-05-16 08:02:29 +00002211 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 * Init temps and window size
2213 */
2214 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2216 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002217 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002218 memset( W, 0, sizeof( W ) );
2219
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002220 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002221
2222 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2223 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2224
Peter Kolbusb83d41d2018-12-11 14:01:44 -06002225#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2227 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06002228#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002229
Paul Bakker5121ce52009-01-03 21:22:43 +00002230 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2232 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2233 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002234
2235 /*
Paul Bakker50546922012-05-19 08:40:49 +00002236 * Compensate for negative A (and correct at the end)
2237 */
2238 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002239 if( neg )
2240 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002241 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002242 Apos.s = 1;
2243 A = &Apos;
2244 }
2245
2246 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002247 * If 1st call, pre-compute R^2 mod N
2248 */
2249 if( _RR == NULL || _RR->p == NULL )
2250 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2252 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2253 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002254
2255 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 }
2258 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002260
2261 /*
2262 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2265 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002266 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002269 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002270
2271 /*
2272 * X = R^2 * R^-1 mod N = R mod N
2273 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002275 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
2277 if( wsize > 1 )
2278 {
2279 /*
2280 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2281 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002282 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2285 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
2287 for( i = 0; i < wsize - 1; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002288 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002289
Paul Bakker5121ce52009-01-03 21:22:43 +00002290 /*
2291 * W[i] = W[i - 1] * W[1]
2292 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002293 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002294 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2296 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002298 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299 }
2300 }
2301
2302 nblimbs = E->n;
2303 bufsize = 0;
2304 nbits = 0;
2305 wbits = 0;
2306 state = 0;
2307
2308 while( 1 )
2309 {
2310 if( bufsize == 0 )
2311 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002312 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002313 break;
2314
Paul Bakker0d7702c2013-10-29 16:18:35 +01002315 nblimbs--;
2316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 }
2319
2320 bufsize--;
2321
2322 ei = (E->p[nblimbs] >> bufsize) & 1;
2323
2324 /*
2325 * skip leading 0s
2326 */
2327 if( ei == 0 && state == 0 )
2328 continue;
2329
2330 if( ei == 0 && state == 1 )
2331 {
2332 /*
2333 * out of window, square X
2334 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002335 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336 continue;
2337 }
2338
2339 /*
2340 * add ei to current window
2341 */
2342 state = 2;
2343
2344 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002345 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
2347 if( nbits == wsize )
2348 {
2349 /*
2350 * X = X^wsize R^-1 mod N
2351 */
2352 for( i = 0; i < wsize; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002353 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
2355 /*
2356 * X = X * W[wbits] R^-1 mod N
2357 */
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002358 MBEDTLS_MPI_CHK( mpi_select( &WW, W, 1 << wsize, wbits ) );
2359 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
2361 state--;
2362 nbits = 0;
2363 wbits = 0;
2364 }
2365 }
2366
2367 /*
2368 * process the remaining bits
2369 */
2370 for( i = 0; i < nbits; i++ )
2371 {
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002372 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373
2374 wbits <<= 1;
2375
Paul Bakker66d5d072014-06-17 16:39:18 +02002376 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002377 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002378 }
2379
2380 /*
2381 * X = A^E * R * R^-1 mod N = A^E mod N
2382 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002383 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Hanno Beckera4af1c42017-04-18 09:07:45 +01002385 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002386 {
2387 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002389 }
2390
Paul Bakker5121ce52009-01-03 21:22:43 +00002391cleanup:
2392
Paul Bakker66d5d072014-06-17 16:39:18 +02002393 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002397 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002398
Paul Bakker75a28602014-03-31 12:08:17 +02002399 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002401
2402 return( ret );
2403}
2404
Paul Bakker5121ce52009-01-03 21:22:43 +00002405/*
2406 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002409{
Paul Bakker23986e52011-04-24 08:57:21 +00002410 int ret;
2411 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002413
Hanno Becker73d7d792018-12-11 10:35:51 +00002414 MPI_VALIDATE_RET( G != NULL );
2415 MPI_VALIDATE_RET( A != NULL );
2416 MPI_VALIDATE_RET( B != NULL );
2417
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2421 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423 lz = mbedtls_mpi_lsb( &TA );
2424 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002425
Paul Bakker66d5d072014-06-17 16:39:18 +02002426 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002427 lz = lzt;
2428
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2430 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002431
Paul Bakker5121ce52009-01-03 21:22:43 +00002432 TA.s = TB.s = 1;
2433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002435 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2437 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002438
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002439 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002440 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2442 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002443 }
2444 else
2445 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2447 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 }
2449 }
2450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2452 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002453
2454cleanup:
2455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002457
2458 return( ret );
2459}
2460
Paul Bakker33dc46b2014-04-30 16:11:39 +02002461/*
2462 * Fill X with size bytes of random.
2463 *
2464 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002465 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002466 * deterministic, eg for tests).
2467 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002469 int (*f_rng)(void *, unsigned char *, size_t),
2470 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002471{
Paul Bakker23986e52011-04-24 08:57:21 +00002472 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002473 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002474 size_t const overhead = ( limbs * ciL ) - size;
2475 unsigned char *Xp;
2476
Hanno Becker8ce11a32018-12-19 16:18:52 +00002477 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002478 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002479
Hanno Beckerda1655a2017-10-18 14:21:44 +01002480 /* Ensure that target MPI has exactly the necessary number of limbs */
2481 if( X->n != limbs )
2482 {
2483 mbedtls_mpi_free( X );
2484 mbedtls_mpi_init( X );
2485 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2486 }
2487 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002488
Hanno Beckerda1655a2017-10-18 14:21:44 +01002489 Xp = (unsigned char*) X->p;
Gilles Peskine05251142020-11-25 16:15:14 +01002490 MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002491
Hanno Becker2be8a552018-10-25 12:40:09 +01002492 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002493
2494cleanup:
2495 return( ret );
2496}
2497
Paul Bakker5121ce52009-01-03 21:22:43 +00002498/*
2499 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2500 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002502{
2503 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002505 MPI_VALIDATE_RET( X != NULL );
2506 MPI_VALIDATE_RET( A != NULL );
2507 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002508
Hanno Becker4bcb4912017-04-18 15:49:39 +01002509 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002510 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2513 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2514 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002516 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002518 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002519 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002520 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002521 goto cleanup;
2522 }
2523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2525 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2526 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2527 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2530 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2531 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2532 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002533
2534 do
2535 {
2536 while( ( TU.p[0] & 1 ) == 0 )
2537 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002539
2540 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2541 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2543 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002544 }
2545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002546 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2547 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002548 }
2549
2550 while( ( TV.p[0] & 1 ) == 0 )
2551 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
2554 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2555 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2557 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002558 }
2559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002560 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2561 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002562 }
2563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002565 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2567 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2568 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002569 }
2570 else
2571 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2573 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2574 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002575 }
2576 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2580 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2583 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002586
2587cleanup:
2588
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2590 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2591 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002592
2593 return( ret );
2594}
2595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002596#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002597
Paul Bakker5121ce52009-01-03 21:22:43 +00002598static const int small_prime[] =
2599{
2600 3, 5, 7, 11, 13, 17, 19, 23,
2601 29, 31, 37, 41, 43, 47, 53, 59,
2602 61, 67, 71, 73, 79, 83, 89, 97,
2603 101, 103, 107, 109, 113, 127, 131, 137,
2604 139, 149, 151, 157, 163, 167, 173, 179,
2605 181, 191, 193, 197, 199, 211, 223, 227,
2606 229, 233, 239, 241, 251, 257, 263, 269,
2607 271, 277, 281, 283, 293, 307, 311, 313,
2608 317, 331, 337, 347, 349, 353, 359, 367,
2609 373, 379, 383, 389, 397, 401, 409, 419,
2610 421, 431, 433, 439, 443, 449, 457, 461,
2611 463, 467, 479, 487, 491, 499, 503, 509,
2612 521, 523, 541, 547, 557, 563, 569, 571,
2613 577, 587, 593, 599, 601, 607, 613, 617,
2614 619, 631, 641, 643, 647, 653, 659, 661,
2615 673, 677, 683, 691, 701, 709, 719, 727,
2616 733, 739, 743, 751, 757, 761, 769, 773,
2617 787, 797, 809, 811, 821, 823, 827, 829,
2618 839, 853, 857, 859, 863, 877, 881, 883,
2619 887, 907, 911, 919, 929, 937, 941, 947,
2620 953, 967, 971, 977, 983, 991, 997, -103
2621};
2622
2623/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002624 * Small divisors test (X must be positive)
2625 *
2626 * Return values:
2627 * 0: no small factor (possible prime, more tests needed)
2628 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002630 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002631 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002633{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002634 int ret = 0;
2635 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002636 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002637
Paul Bakker5121ce52009-01-03 21:22:43 +00002638 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002639 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002640
2641 for( i = 0; small_prime[i] > 0; i++ )
2642 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002644 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002645
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002646 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002647
2648 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002649 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002650 }
2651
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002652cleanup:
2653 return( ret );
2654}
2655
2656/*
2657 * Miller-Rabin pseudo-primality test (HAC 4.24)
2658 */
Janos Follathda31fa12018-09-03 14:45:23 +01002659static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002660 int (*f_rng)(void *, unsigned char *, size_t),
2661 void *p_rng )
2662{
Pascal Junodb99183d2015-03-11 16:49:45 +01002663 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002664 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002666
Hanno Becker8ce11a32018-12-19 16:18:52 +00002667 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002668 MPI_VALIDATE_RET( f_rng != NULL );
2669
2670 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2671 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002672 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002673
Paul Bakker5121ce52009-01-03 21:22:43 +00002674 /*
2675 * W = |X| - 1
2676 * R = W >> lsb( W )
2677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002678 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2679 s = mbedtls_mpi_lsb( &W );
2680 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2681 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002682
Janos Follathda31fa12018-09-03 14:45:23 +01002683 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002684 {
2685 /*
2686 * pick a random A, 1 < A < |X| - 1
2687 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002688 count = 0;
2689 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002690 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002691
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002692 j = mbedtls_mpi_bitlen( &A );
2693 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002694 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002695 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002696 }
2697
2698 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002699 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2700 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002701 }
2702
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002703 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2704 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002705
2706 /*
2707 * A = A^R mod |X|
2708 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002709 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2712 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002713 continue;
2714
2715 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002716 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002717 {
2718 /*
2719 * A = A * A mod |X|
2720 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002721 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2722 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002724 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002725 break;
2726
2727 j++;
2728 }
2729
2730 /*
2731 * not prime if A != |X| - 1 or A == 1
2732 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002733 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2734 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002735 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002736 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002737 break;
2738 }
2739 }
2740
2741cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002742 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2743 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002745
2746 return( ret );
2747}
2748
2749/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002750 * Pseudo-primality test: small factors, then Miller-Rabin
2751 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002752int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2753 int (*f_rng)(void *, unsigned char *, size_t),
2754 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002755{
2756 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002757 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002758 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002759 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002760
2761 XX.s = 1;
2762 XX.n = X->n;
2763 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002765 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2766 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2767 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002769 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002770 return( 0 );
2771
2772 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2773 {
2774 if( ret == 1 )
2775 return( 0 );
2776
2777 return( ret );
2778 }
2779
Janos Follathda31fa12018-09-03 14:45:23 +01002780 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002781}
2782
Janos Follatha0b67c22018-09-18 14:48:23 +01002783#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002784/*
2785 * Pseudo-primality test, error probability 2^-80
2786 */
2787int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2788 int (*f_rng)(void *, unsigned char *, size_t),
2789 void *p_rng )
2790{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002791 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002792 MPI_VALIDATE_RET( f_rng != NULL );
2793
Janos Follatha0b67c22018-09-18 14:48:23 +01002794 /*
2795 * In the past our key generation aimed for an error rate of at most
2796 * 2^-80. Since this function is deprecated, aim for the same certainty
2797 * here as well.
2798 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002799 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002800}
Janos Follatha0b67c22018-09-18 14:48:23 +01002801#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002802
2803/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002804 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002805 *
Janos Follathf301d232018-08-14 13:34:01 +01002806 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2807 * be either 1024 bits or 1536 bits long, and flags must contain
2808 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002809 */
Janos Follath7c025a92018-08-14 11:08:41 +01002810int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002811 int (*f_rng)(void *, unsigned char *, size_t),
2812 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002813{
Jethro Beekman66689272018-02-14 19:24:10 -08002814#ifdef MBEDTLS_HAVE_INT64
2815// ceil(2^63.5)
2816#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2817#else
2818// ceil(2^31.5)
2819#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2820#endif
2821 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002822 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002823 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002824 mbedtls_mpi_uint r;
2825 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002826
Hanno Becker8ce11a32018-12-19 16:18:52 +00002827 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002828 MPI_VALIDATE_RET( f_rng != NULL );
2829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002830 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2831 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002832
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002833 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002834
2835 n = BITS_TO_LIMBS( nbits );
2836
Janos Follathda31fa12018-09-03 14:45:23 +01002837 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2838 {
2839 /*
2840 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2841 */
2842 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2843 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2844 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2845 }
2846 else
2847 {
2848 /*
2849 * 2^-100 error probability, number of rounds computed based on HAC,
2850 * fact 4.48
2851 */
2852 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2853 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2854 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2855 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2856 }
2857
Jethro Beekman66689272018-02-14 19:24:10 -08002858 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002859 {
Jethro Beekman66689272018-02-14 19:24:10 -08002860 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2861 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2862 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2863
2864 k = n * biL;
2865 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2866 X->p[0] |= 1;
2867
Janos Follath7c025a92018-08-14 11:08:41 +01002868 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002869 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002870 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002872 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002873 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002874 }
Jethro Beekman66689272018-02-14 19:24:10 -08002875 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002876 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002877 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002878 * An necessary condition for Y and X = 2Y + 1 to be prime
2879 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2880 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002881 */
Jethro Beekman66689272018-02-14 19:24:10 -08002882
2883 X->p[0] |= 2;
2884
2885 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2886 if( r == 0 )
2887 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2888 else if( r == 1 )
2889 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2890
2891 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2892 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2893 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2894
2895 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002896 {
Jethro Beekman66689272018-02-14 19:24:10 -08002897 /*
2898 * First, check small factors for X and Y
2899 * before doing Miller-Rabin on any of them
2900 */
2901 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2902 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002903 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002904 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002905 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002906 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002907 goto cleanup;
2908
2909 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2910 goto cleanup;
2911
2912 /*
2913 * Next candidates. We want to preserve Y = (X-1) / 2 and
2914 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2915 * so up Y by 6 and X by 12.
2916 */
2917 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2918 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002919 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002920 }
2921 }
2922
2923cleanup:
2924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002925 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002926
2927 return( ret );
2928}
2929
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002930#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002931
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002932#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002933
Paul Bakker23986e52011-04-24 08:57:21 +00002934#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002935
2936static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2937{
2938 { 693, 609, 21 },
2939 { 1764, 868, 28 },
2940 { 768454923, 542167814, 1 }
2941};
2942
Paul Bakker5121ce52009-01-03 21:22:43 +00002943/*
2944 * Checkup routine
2945 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002946int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002947{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002948 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002949 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002950
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002951 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2952 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002954 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002955 "EFE021C2645FD1DC586E69184AF4A31E" \
2956 "D5F53E93B5F123FA41680867BA110131" \
2957 "944FE7952E2517337780CB0DB80E61AA" \
2958 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002960 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002961 "B2E7EFD37075B9F03FF989C7C5051C20" \
2962 "34D2A323810251127E7BF8625A4F49A5" \
2963 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2964 "5B5C25763222FEFCCFC38B832366C29E" ) );
2965
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002966 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002967 "0066A198186C18C10B2F5ED9B522752A" \
2968 "9830B69916E535C8F047518A889A43A5" \
2969 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2970
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002971 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002973 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002974 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2975 "9E857EA95A03512E2BAE7391688D264A" \
2976 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2977 "8001B72E848A38CAE1C65F78E56ABDEF" \
2978 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2979 "ECF677152EF804370C1A305CAF3B5BF1" \
2980 "30879B56C61DE584A0F53A2447A51E" ) );
2981
2982 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002983 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002985 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002986 {
2987 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002988 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002989
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002990 ret = 1;
2991 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002992 }
2993
2994 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002995 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002996
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002997 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002999 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003000 "256567336059E52CAE22925474705F39A94" ) );
3001
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003002 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003003 "6613F26162223DF488E9CD48CC132C7A" \
3004 "0AC93C701B001B092E4E5B9F73BCD27B" \
3005 "9EE50D0657C77F374E903CDFA4C642" ) );
3006
3007 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003008 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003010 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3011 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003012 {
3013 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003014 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003015
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003016 ret = 1;
3017 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003018 }
3019
3020 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003021 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003023 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003024
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003025 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003026 "36E139AEA55215609D2816998ED020BB" \
3027 "BD96C37890F65171D948E9BC7CBAA4D9" \
3028 "325D24D6A3C12710F10A09FA08AB87" ) );
3029
3030 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003031 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003033 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003034 {
3035 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003036 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003037
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003038 ret = 1;
3039 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003040 }
3041
3042 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003043 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003045 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003046
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003047 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003048 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3049 "C3DBA76456363A10869622EAC2DD84EC" \
3050 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3051
3052 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003053 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003055 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003056 {
3057 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003058 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003059
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003060 ret = 1;
3061 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003062 }
3063
3064 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003065 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003066
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003067 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003068 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003069
Paul Bakker66d5d072014-06-17 16:39:18 +02003070 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003072 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3073 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003074
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003075 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003077 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003078 {
3079 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003080 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003081
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003082 ret = 1;
3083 goto cleanup;
3084 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003085 }
3086
3087 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003088 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003089
Paul Bakker5121ce52009-01-03 21:22:43 +00003090cleanup:
3091
3092 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003093 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003094
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003095 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3096 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003097
3098 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003099 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003100
3101 return( ret );
3102}
3103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003104#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003106#endif /* MBEDTLS_BIGNUM_C */