blob: d9c1df3c6a800df3a045f9de75e8456802dfd3ea [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
270/*
Gilles Peskinec81c5882020-06-04 19:14:58 +0200271 * Conditionally assign dest = src, without leaking information
272 * about whether the assignment was made or not.
273 * dest and src must be arrays of limbs of size n.
274 * assign must be 0 or 1.
275 */
276static void mpi_safe_cond_assign( size_t n,
277 mbedtls_mpi_uint *dest,
278 const mbedtls_mpi_uint *src,
279 unsigned char assign )
280{
281 size_t i;
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200282
283 /* MSVC has a warning about unary minus on unsigned integer types,
284 * but this is well-defined and precisely what we want to do here. */
285#if defined(_MSC_VER)
286#pragma warning( push )
287#pragma warning( disable : 4146 )
288#endif
289
290 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
291 const mbedtls_mpi_uint mask = -assign;
292
293#if defined(_MSC_VER)
294#pragma warning( pop )
295#endif
296
Gilles Peskinec81c5882020-06-04 19:14:58 +0200297 for( i = 0; i < n; i++ )
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200298 dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
Gilles Peskinec81c5882020-06-04 19:14:58 +0200299}
300
301/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100302 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100303 * about whether the assignment was made or not.
304 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100305 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100307{
308 int ret = 0;
309 size_t i;
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200310 unsigned int mask;
311 mbedtls_mpi_uint limb_mask;
Hanno Becker73d7d792018-12-11 10:35:51 +0000312 MPI_VALIDATE_RET( X != NULL );
313 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100314
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200315 /* MSVC has a warning about unary minus on unsigned integer types,
316 * but this is well-defined and precisely what we want to do here. */
317#if defined(_MSC_VER)
318#pragma warning( push )
319#pragma warning( disable : 4146 )
320#endif
321
Pascal Junodb99183d2015-03-11 16:49:45 +0100322 /* make sure assign is 0 or 1 in a time-constant manner */
323 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200324 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
325 mask = -assign;
326 limb_mask = -assign;
327
328#if defined(_MSC_VER)
329#pragma warning( pop )
330#endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100333
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200334 X->s = ( X->s & ~mask ) | ( Y->s & mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100335
Gilles Peskinec81c5882020-06-04 19:14:58 +0200336 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100337
Gilles Peskinec81c5882020-06-04 19:14:58 +0200338 for( i = Y->n; i < X->n; i++ )
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200339 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100340
341cleanup:
342 return( ret );
343}
344
345/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100346 * Conditionally swap X and Y, without leaking information
347 * about whether the swap was made or not.
348 * Here it is not ok to simply swap the pointers, which whould lead to
349 * different memory access patterns when X and Y are used afterwards.
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100352{
353 int ret, s;
354 size_t i;
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200355 unsigned int sign_mask;
356 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000358 MPI_VALIDATE_RET( X != NULL );
359 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100360
361 if( X == Y )
362 return( 0 );
363
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200364 /* MSVC has a warning about unary minus on unsigned integer types,
365 * but this is well-defined and precisely what we want to do here. */
366#if defined(_MSC_VER)
367#pragma warning( push )
368#pragma warning( disable : 4146 )
369#endif
370
Pascal Junodb99183d2015-03-11 16:49:45 +0100371 /* make sure swap is 0 or 1 in a time-constant manner */
372 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200373 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
374 sign_mask = -swap;
375 limb_mask = -swap;
376
377#if defined(_MSC_VER)
378#pragma warning( pop )
379#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
382 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100383
384 s = X->s;
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200385 X->s = ( X->s & ~sign_mask ) | ( Y->s & sign_mask );
386 Y->s = ( Y->s & ~sign_mask ) | ( s & sign_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100387
388
389 for( i = 0; i < X->n; i++ )
390 {
391 tmp = X->p[i];
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200392 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
393 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100394 }
395
396cleanup:
397 return( ret );
398}
399
400/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000401 * Set value from integer
402 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000404{
405 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000406 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000409 memset( X->p, 0, X->n * ciL );
410
411 X->p[0] = ( z < 0 ) ? -z : z;
412 X->s = ( z < 0 ) ? -1 : 1;
413
414cleanup:
415
416 return( ret );
417}
418
419/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000420 * Get a specific bit
421 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000423{
Hanno Becker73d7d792018-12-11 10:35:51 +0000424 MPI_VALIDATE_RET( X != NULL );
425
Paul Bakker2f5947e2011-05-18 15:47:11 +0000426 if( X->n * biL <= pos )
427 return( 0 );
428
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200429 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000430}
431
Gilles Peskine11cdb052018-11-20 16:47:47 +0100432/* Get a specific byte, without range checks. */
433#define GET_BYTE( X, i ) \
434 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
435
Paul Bakker2f5947e2011-05-18 15:47:11 +0000436/*
437 * Set a bit to a specific value of 0 or 1
438 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000440{
441 int ret = 0;
442 size_t off = pos / biL;
443 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000444 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000445
446 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200448
Paul Bakker2f5947e2011-05-18 15:47:11 +0000449 if( X->n * biL <= pos )
450 {
451 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200452 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000455 }
456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
458 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000459
460cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200461
Paul Bakker2f5947e2011-05-18 15:47:11 +0000462 return( ret );
463}
464
465/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200466 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000467 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000469{
Paul Bakker23986e52011-04-24 08:57:21 +0000470 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000471 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
473 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000474 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000475 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
476 return( count );
477
478 return( 0 );
479}
480
481/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000482 * Count leading zero bits in a given integer
483 */
484static size_t mbedtls_clz( const mbedtls_mpi_uint x )
485{
486 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100487 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000488
489 for( j = 0; j < biL; j++ )
490 {
491 if( x & mask ) break;
492
493 mask >>= 1;
494 }
495
496 return j;
497}
498
499/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200500 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200502size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000503{
Paul Bakker23986e52011-04-24 08:57:21 +0000504 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000505
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200506 if( X->n == 0 )
507 return( 0 );
508
Paul Bakker5121ce52009-01-03 21:22:43 +0000509 for( i = X->n - 1; i > 0; i-- )
510 if( X->p[i] != 0 )
511 break;
512
Simon Butcher15b15d12015-11-26 19:35:03 +0000513 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514
Paul Bakker23986e52011-04-24 08:57:21 +0000515 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000516}
517
518/*
519 * Return the total size in bytes
520 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000522{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200523 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000524}
525
526/*
527 * Convert an ASCII character to digit value
528 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000530{
531 *d = 255;
532
533 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
534 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
535 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 if( *d >= (mbedtls_mpi_uint) radix )
538 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
540 return( 0 );
541}
542
543/*
544 * Import from an ASCII string
545 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000547{
Paul Bakker23986e52011-04-24 08:57:21 +0000548 int ret;
549 size_t i, j, slen, n;
Gilles Peskine984fd072021-04-03 18:26:13 +0200550 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 mbedtls_mpi_uint d;
552 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000553 MPI_VALIDATE_RET( X != NULL );
554 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
556 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000557 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200559 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Gilles Peskine984fd072021-04-03 18:26:13 +0200561 if( s[0] == '-' )
562 {
563 ++s;
564 sign = -1;
565 }
566
Paul Bakkerff60ee62010-03-16 21:09:09 +0000567 slen = strlen( s );
568
Paul Bakker5121ce52009-01-03 21:22:43 +0000569 if( radix == 16 )
570 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100571 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200572 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
573
Paul Bakkerff60ee62010-03-16 21:09:09 +0000574 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
577 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000578
Paul Bakker23986e52011-04-24 08:57:21 +0000579 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000580 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200582 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000583 }
584 }
585 else
586 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000588
Paul Bakkerff60ee62010-03-16 21:09:09 +0000589 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000590 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
592 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine984fd072021-04-03 18:26:13 +0200593 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594 }
595 }
596
Gilles Peskine984fd072021-04-03 18:26:13 +0200597 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
598 X->s = -1;
599
Paul Bakker5121ce52009-01-03 21:22:43 +0000600cleanup:
601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603
604 return( ret );
605}
606
607/*
Ron Eldora16fa292018-11-20 14:07:01 +0200608 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000609 */
Ron Eldora16fa292018-11-20 14:07:01 +0200610static int mpi_write_hlp( mbedtls_mpi *X, int radix,
611 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000612{
613 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200615 size_t length = 0;
616 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
Ron Eldora16fa292018-11-20 14:07:01 +0200618 do
619 {
620 if( length >= buflen )
621 {
622 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
623 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000624
Ron Eldora16fa292018-11-20 14:07:01 +0200625 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
626 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
627 /*
628 * Write the residue in the current position, as an ASCII character.
629 */
630 if( r < 0xA )
631 *(--p_end) = (char)( '0' + r );
632 else
633 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000634
Ron Eldora16fa292018-11-20 14:07:01 +0200635 length++;
636 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000637
Ron Eldora16fa292018-11-20 14:07:01 +0200638 memmove( *p, p_end, length );
639 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000640
641cleanup:
642
643 return( ret );
644}
645
646/*
647 * Export into an ASCII string
648 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100649int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
650 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000651{
Paul Bakker23986e52011-04-24 08:57:21 +0000652 int ret = 0;
653 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000654 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000656 MPI_VALIDATE_RET( X != NULL );
657 MPI_VALIDATE_RET( olen != NULL );
658 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
660 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000661 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000662
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000663 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
664 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
665 * `n`. If radix > 4, this might be a strict
666 * overapproximation of the number of
667 * radix-adic digits needed to present `n`. */
668 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
669 * present `n`. */
670
Janos Follath870ed002019-03-06 13:43:02 +0000671 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000672 n += 1; /* Compensate for the divisions above, which round down `n`
673 * in case it's not even. */
674 n += 1; /* Potential '-'-sign. */
675 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
676 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100678 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000679 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100680 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000682 }
683
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100684 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000688 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000690 buflen--;
691 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
693 if( radix == 16 )
694 {
Paul Bakker23986e52011-04-24 08:57:21 +0000695 int c;
696 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
Paul Bakker23986e52011-04-24 08:57:21 +0000698 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000699 {
Paul Bakker23986e52011-04-24 08:57:21 +0000700 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000701 {
Paul Bakker23986e52011-04-24 08:57:21 +0000702 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
Paul Bakker6c343d72014-07-10 14:36:19 +0200704 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000705 continue;
706
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000707 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000708 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000709 k = 1;
710 }
711 }
712 }
713 else
714 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000716
717 if( T.s == -1 )
718 T.s = 1;
719
Ron Eldora16fa292018-11-20 14:07:01 +0200720 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000721 }
722
723 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100724 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000725
726cleanup:
727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
730 return( ret );
731}
732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200733#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000734/*
735 * Read X from an opened file
736 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000738{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000740 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000741 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000742 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000743 * Buffer should have space for (short) label and decimal formatted MPI,
744 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000745 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000747
Hanno Becker73d7d792018-12-11 10:35:51 +0000748 MPI_VALIDATE_RET( X != NULL );
749 MPI_VALIDATE_RET( fin != NULL );
750
751 if( radix < 2 || radix > 16 )
752 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
753
Paul Bakker5121ce52009-01-03 21:22:43 +0000754 memset( s, 0, sizeof( s ) );
755 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
758 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000759 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000761
Hanno Beckerb2034b72017-04-26 11:46:46 +0100762 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
763 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
765 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100766 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000767 if( mpi_get_digit( &d, radix, *p ) != 0 )
768 break;
769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000771}
772
773/*
774 * Write X into an opened file (or stdout if fout == NULL)
775 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000777{
Paul Bakker23986e52011-04-24 08:57:21 +0000778 int ret;
779 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000780 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000781 * Buffer should have space for (short) label and decimal formatted MPI,
782 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000783 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200784 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000785 MPI_VALIDATE_RET( X != NULL );
786
787 if( radix < 2 || radix > 16 )
788 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000789
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100790 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000791
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100792 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000793
794 if( p == NULL ) p = "";
795
796 plen = strlen( p );
797 slen = strlen( s );
798 s[slen++] = '\r';
799 s[slen++] = '\n';
800
801 if( fout != NULL )
802 {
803 if( fwrite( p, 1, plen, fout ) != plen ||
804 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000806 }
807 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000809
810cleanup:
811
812 return( ret );
813}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
Hanno Beckerda1655a2017-10-18 14:21:44 +0100816
817/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
818 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000819
820static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
821{
822 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100823 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000824 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100825
826 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
827 {
828 tmp <<= CHAR_BIT;
829 tmp |= (mbedtls_mpi_uint) *x_ptr;
830 }
831
Hanno Beckerf8720072018-11-08 11:53:49 +0000832 return( tmp );
833}
834
835static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
836{
837#if defined(__BYTE_ORDER__)
838
839/* Nothing to do on bigendian systems. */
840#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
841 return( x );
842#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
843
844#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
845
846/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000847#if defined(__GNUC__) && defined(__GNUC_PREREQ)
848#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000849#define have_bswap
850#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000851#endif
852
853#if defined(__clang__) && defined(__has_builtin)
854#if __has_builtin(__builtin_bswap32) && \
855 __has_builtin(__builtin_bswap64)
856#define have_bswap
857#endif
858#endif
859
Hanno Beckerf8720072018-11-08 11:53:49 +0000860#if defined(have_bswap)
861 /* The compiler is hopefully able to statically evaluate this! */
862 switch( sizeof(mbedtls_mpi_uint) )
863 {
864 case 4:
865 return( __builtin_bswap32(x) );
866 case 8:
867 return( __builtin_bswap64(x) );
868 }
869#endif
870#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
871#endif /* __BYTE_ORDER__ */
872
873 /* Fall back to C-based reordering if we don't know the byte order
874 * or we couldn't use a compiler-specific builtin. */
875 return( mpi_uint_bigendian_to_host_c( x ) );
876}
877
Hanno Becker2be8a552018-10-25 12:40:09 +0100878static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100879{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100880 mbedtls_mpi_uint *cur_limb_left;
881 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100882 if( limbs == 0 )
883 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100884
885 /*
886 * Traverse limbs and
887 * - adapt byte-order in each limb
888 * - swap the limbs themselves.
889 * For that, simultaneously traverse the limbs from left to right
890 * and from right to left, as long as the left index is not bigger
891 * than the right index (it's not a problem if limbs is odd and the
892 * indices coincide in the last iteration).
893 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100894 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
895 cur_limb_left <= cur_limb_right;
896 cur_limb_left++, cur_limb_right-- )
897 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000898 mbedtls_mpi_uint tmp;
899 /* Note that if cur_limb_left == cur_limb_right,
900 * this code effectively swaps the bytes only once. */
901 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
902 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
903 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100904 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100905}
906
Paul Bakker5121ce52009-01-03 21:22:43 +0000907/*
908 * Import X from unsigned binary data, big endian
909 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000911{
Paul Bakker23986e52011-04-24 08:57:21 +0000912 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100913 size_t const limbs = CHARS_TO_LIMBS( buflen );
914 size_t const overhead = ( limbs * ciL ) - buflen;
915 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000916
Hanno Becker8ce11a32018-12-19 16:18:52 +0000917 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000918 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
919
Hanno Becker073c1992017-10-17 15:17:27 +0100920 /* Ensure that target MPI has exactly the necessary number of limbs */
921 if( X->n != limbs )
922 {
923 mbedtls_mpi_free( X );
924 mbedtls_mpi_init( X );
925 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
926 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000928
Hanno Becker0e810b92019-01-03 17:13:11 +0000929 /* Avoid calling `memcpy` with NULL source argument,
930 * even if buflen is 0. */
931 if( buf != NULL )
932 {
933 Xp = (unsigned char*) X->p;
934 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100935
Hanno Becker0e810b92019-01-03 17:13:11 +0000936 mpi_bigendian_to_host( X->p, limbs );
937 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000938
939cleanup:
940
941 return( ret );
942}
943
944/*
945 * Export X into unsigned binary data, big endian
946 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100947int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
948 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000949{
Hanno Becker73d7d792018-12-11 10:35:51 +0000950 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100951 size_t bytes_to_copy;
952 unsigned char *p;
953 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000954
Hanno Becker73d7d792018-12-11 10:35:51 +0000955 MPI_VALIDATE_RET( X != NULL );
956 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
957
958 stored_bytes = X->n * ciL;
959
Gilles Peskine11cdb052018-11-20 16:47:47 +0100960 if( stored_bytes < buflen )
961 {
962 /* There is enough space in the output buffer. Write initial
963 * null bytes and record the position at which to start
964 * writing the significant bytes. In this case, the execution
965 * trace of this function does not depend on the value of the
966 * number. */
967 bytes_to_copy = stored_bytes;
968 p = buf + buflen - stored_bytes;
969 memset( buf, 0, buflen - stored_bytes );
970 }
971 else
972 {
973 /* The output buffer is smaller than the allocated size of X.
974 * However X may fit if its leading bytes are zero. */
975 bytes_to_copy = buflen;
976 p = buf;
977 for( i = bytes_to_copy; i < stored_bytes; i++ )
978 {
979 if( GET_BYTE( X, i ) != 0 )
980 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
981 }
982 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000983
Gilles Peskine11cdb052018-11-20 16:47:47 +0100984 for( i = 0; i < bytes_to_copy; i++ )
985 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000986
987 return( 0 );
988}
989
990/*
991 * Left-shift: X <<= count
992 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200993int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000994{
Paul Bakker23986e52011-04-24 08:57:21 +0000995 int ret;
996 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000998 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000999
1000 v0 = count / (biL );
1001 t1 = count & (biL - 1);
1002
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001003 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001004
Paul Bakkerf9688572011-05-05 10:00:45 +00001005 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001006 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001007
1008 ret = 0;
1009
1010 /*
1011 * shift by count / limb_size
1012 */
1013 if( v0 > 0 )
1014 {
Paul Bakker23986e52011-04-24 08:57:21 +00001015 for( i = X->n; i > v0; i-- )
1016 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001017
Paul Bakker23986e52011-04-24 08:57:21 +00001018 for( ; i > 0; i-- )
1019 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 }
1021
1022 /*
1023 * shift by count % limb_size
1024 */
1025 if( t1 > 0 )
1026 {
1027 for( i = v0; i < X->n; i++ )
1028 {
1029 r1 = X->p[i] >> (biL - t1);
1030 X->p[i] <<= t1;
1031 X->p[i] |= r0;
1032 r0 = r1;
1033 }
1034 }
1035
1036cleanup:
1037
1038 return( ret );
1039}
1040
1041/*
1042 * Right-shift: X >>= count
1043 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001045{
Paul Bakker23986e52011-04-24 08:57:21 +00001046 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001048 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001049
1050 v0 = count / biL;
1051 v1 = count & (biL - 1);
1052
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001053 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001055
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 /*
1057 * shift by count / limb_size
1058 */
1059 if( v0 > 0 )
1060 {
1061 for( i = 0; i < X->n - v0; i++ )
1062 X->p[i] = X->p[i + v0];
1063
1064 for( ; i < X->n; i++ )
1065 X->p[i] = 0;
1066 }
1067
1068 /*
1069 * shift by count % limb_size
1070 */
1071 if( v1 > 0 )
1072 {
Paul Bakker23986e52011-04-24 08:57:21 +00001073 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001074 {
Paul Bakker23986e52011-04-24 08:57:21 +00001075 r1 = X->p[i - 1] << (biL - v1);
1076 X->p[i - 1] >>= v1;
1077 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001078 r0 = r1;
1079 }
1080 }
1081
1082 return( 0 );
1083}
1084
1085/*
1086 * Compare unsigned values
1087 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001089{
Paul Bakker23986e52011-04-24 08:57:21 +00001090 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001091 MPI_VALIDATE_RET( X != NULL );
1092 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001093
Paul Bakker23986e52011-04-24 08:57:21 +00001094 for( i = X->n; i > 0; i-- )
1095 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001096 break;
1097
Paul Bakker23986e52011-04-24 08:57:21 +00001098 for( j = Y->n; j > 0; j-- )
1099 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 break;
1101
Paul Bakker23986e52011-04-24 08:57:21 +00001102 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001103 return( 0 );
1104
1105 if( i > j ) return( 1 );
1106 if( j > i ) return( -1 );
1107
Paul Bakker23986e52011-04-24 08:57:21 +00001108 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001109 {
Paul Bakker23986e52011-04-24 08:57:21 +00001110 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1111 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001112 }
1113
1114 return( 0 );
1115}
1116
1117/*
1118 * Compare signed values
1119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001121{
Paul Bakker23986e52011-04-24 08:57:21 +00001122 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001123 MPI_VALIDATE_RET( X != NULL );
1124 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001125
Paul Bakker23986e52011-04-24 08:57:21 +00001126 for( i = X->n; i > 0; i-- )
1127 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001128 break;
1129
Paul Bakker23986e52011-04-24 08:57:21 +00001130 for( j = Y->n; j > 0; j-- )
1131 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001132 break;
1133
Paul Bakker23986e52011-04-24 08:57:21 +00001134 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001135 return( 0 );
1136
1137 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001138 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001139
1140 if( X->s > 0 && Y->s < 0 ) return( 1 );
1141 if( Y->s > 0 && X->s < 0 ) 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( X->s );
1146 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001147 }
1148
1149 return( 0 );
1150}
1151
Janos Follath45ec9902019-10-14 09:09:32 +01001152/** Decide if an integer is less than the other, without branches.
1153 *
1154 * \param x First integer.
1155 * \param y Second integer.
1156 *
1157 * \return 1 if \p x is less than \p y, 0 otherwise
1158 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001159static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1160 const mbedtls_mpi_uint y )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001161{
1162 mbedtls_mpi_uint ret;
1163 mbedtls_mpi_uint cond;
1164
1165 /*
1166 * Check if the most significant bits (MSB) of the operands are different.
1167 */
1168 cond = ( x ^ y );
1169 /*
1170 * If the MSB are the same then the difference x-y will be negative (and
1171 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1172 */
1173 ret = ( x - y ) & ~cond;
1174 /*
1175 * If the MSB are different, then the operand with the MSB of 1 is the
1176 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1177 * the MSB of y is 0.)
1178 */
1179 ret |= y & cond;
1180
1181
Janos Follath7a34bcf2019-10-14 08:59:14 +01001182 ret = ret >> ( biL - 1 );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001183
Janos Follath359a01e2019-10-29 15:08:46 +00001184 return (unsigned) ret;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001185}
1186
1187/*
1188 * Compare signed values in constant time
1189 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001190int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1191 unsigned *ret )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001192{
1193 size_t i;
Janos Follathbd87a592019-10-28 12:23:18 +00001194 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001195 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001196
1197 MPI_VALIDATE_RET( X != NULL );
1198 MPI_VALIDATE_RET( Y != NULL );
1199 MPI_VALIDATE_RET( ret != NULL );
1200
1201 if( X->n != Y->n )
1202 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1203
1204 /*
Janos Follath58525182019-10-28 12:12:15 +00001205 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1206 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001207 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001208 X_is_negative = ( X->s & 2 ) >> 1;
1209 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath867a3ab2019-10-11 14:21:53 +01001210
1211 /*
1212 * If the signs are different, then the positive operand is the bigger.
Janos Follath1f21c1d2019-10-28 12:31:34 +00001213 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1214 * is false if X is positive (X_is_negative == 0).
Janos Follath867a3ab2019-10-11 14:21:53 +01001215 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001216 cond = ( X_is_negative ^ Y_is_negative );
1217 *ret = cond & X_is_negative;
Janos Follath867a3ab2019-10-11 14:21:53 +01001218
1219 /*
Janos Follathbd87a592019-10-28 12:23:18 +00001220 * This is a constant-time function. We might have the result, but we still
Janos Follath867a3ab2019-10-11 14:21:53 +01001221 * need to go through the loop. Record if we have the result already.
1222 */
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001223 done = cond;
1224
1225 for( i = X->n; i > 0; i-- )
1226 {
1227 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001228 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1229 * X and Y are negative.
Janos Follath867a3ab2019-10-11 14:21:53 +01001230 *
1231 * Again even if we can make a decision, we just mark the result and
1232 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001233 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001234 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1235 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathfbe4c942019-10-28 12:37:21 +00001236 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001237
1238 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001239 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1240 * X and Y are positive.
Janos Follath867a3ab2019-10-11 14:21:53 +01001241 *
1242 * Again even if we can make a decision, we just mark the result and
1243 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001244 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001245 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1246 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathfbe4c942019-10-28 12:37:21 +00001247 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001248 }
1249
1250 return( 0 );
1251}
1252
Paul Bakker5121ce52009-01-03 21:22:43 +00001253/*
1254 * Compare signed values
1255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001256int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001257{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 mbedtls_mpi Y;
1259 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001260 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
1262 *p = ( z < 0 ) ? -z : z;
1263 Y.s = ( z < 0 ) ? -1 : 1;
1264 Y.n = 1;
1265 Y.p = p;
1266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001268}
1269
1270/*
1271 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1272 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001274{
Paul Bakker23986e52011-04-24 08:57:21 +00001275 int ret;
1276 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001277 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001278 MPI_VALIDATE_RET( X != NULL );
1279 MPI_VALIDATE_RET( A != NULL );
1280 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001281
1282 if( X == B )
1283 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001285 }
1286
1287 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001288 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001289
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001290 /*
1291 * X should always be positive as a result of unsigned additions.
1292 */
1293 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001294
Paul Bakker23986e52011-04-24 08:57:21 +00001295 for( j = B->n; j > 0; j-- )
1296 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001297 break;
1298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001300
1301 o = B->p; p = X->p; c = 0;
1302
Janos Follath6c922682015-10-30 17:43:11 +01001303 /*
1304 * tmp is used because it might happen that p == o
1305 */
Paul Bakker23986e52011-04-24 08:57:21 +00001306 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001307 {
Janos Follath6c922682015-10-30 17:43:11 +01001308 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001309 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001310 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001311 }
1312
1313 while( c != 0 )
1314 {
1315 if( i >= X->n )
1316 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001318 p = X->p + i;
1319 }
1320
Paul Bakker2d319fd2012-09-16 21:34:26 +00001321 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001322 }
1323
1324cleanup:
1325
1326 return( ret );
1327}
1328
Gilles Peskinede719d52020-06-09 10:39:38 +02001329/**
Gilles Peskine36acd542020-06-08 21:58:22 +02001330 * Helper for mbedtls_mpi subtraction.
1331 *
1332 * Calculate d - s where d and s have the same size.
1333 * This function operates modulo (2^ciL)^n and returns the carry
1334 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1335 *
1336 * \param n Number of limbs of \p d and \p s.
1337 * \param[in,out] d On input, the left operand.
1338 * On output, the result of the subtraction:
Gilles Peskinede719d52020-06-09 10:39:38 +02001339 * \param[in] s The right operand.
Gilles Peskine36acd542020-06-08 21:58:22 +02001340 *
1341 * \return 1 if `d < s`.
1342 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001343 */
Gilles Peskine36acd542020-06-08 21:58:22 +02001344static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1345 mbedtls_mpi_uint *d,
1346 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001347{
Paul Bakker23986e52011-04-24 08:57:21 +00001348 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001350
1351 for( i = c = 0; i < n; i++, s++, d++ )
1352 {
1353 z = ( *d < c ); *d -= c;
1354 c = ( *d < *s ) + z; *d -= *s;
1355 }
1356
Gilles Peskine36acd542020-06-08 21:58:22 +02001357 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001358}
1359
1360/*
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001361 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001364{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001366 int ret;
1367 size_t n;
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001368 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001369 MPI_VALIDATE_RET( X != NULL );
1370 MPI_VALIDATE_RET( A != NULL );
1371 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001373 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001374
1375 if( X == B )
1376 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 B = &TB;
1379 }
1380
1381 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383
Paul Bakker1ef7a532009-06-20 10:50:55 +00001384 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001385 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001386 */
1387 X->s = 1;
1388
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 ret = 0;
1390
Paul Bakker23986e52011-04-24 08:57:21 +00001391 for( n = B->n; n > 0; n-- )
1392 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 break;
Gilles Peskine6260b702021-01-27 22:30:43 +01001394 if( n > A->n )
1395 {
1396 /* B >= (2^ciL)^n > A */
1397 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1398 goto cleanup;
1399 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001401 carry = mpi_sub_hlp( n, X->p, B->p );
1402 if( carry != 0 )
Gilles Peskine36acd542020-06-08 21:58:22 +02001403 {
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001404 /* Propagate the carry to the first nonzero limb of X. */
1405 for( ; n < X->n && X->p[n] == 0; n++ )
1406 --X->p[n];
1407 /* If we ran out of space for the carry, it means that the result
1408 * is negative. */
1409 if( n == X->n )
Gilles Peskine84697ca2020-07-23 01:16:46 +02001410 {
1411 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1412 goto cleanup;
1413 }
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001414 --X->p[n];
Gilles Peskine36acd542020-06-08 21:58:22 +02001415 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001416
1417cleanup:
1418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001419 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001420
1421 return( ret );
1422}
1423
1424/*
1425 * Signed addition: X = A + B
1426 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001427int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001428{
Hanno Becker73d7d792018-12-11 10:35:51 +00001429 int ret, s;
1430 MPI_VALIDATE_RET( X != NULL );
1431 MPI_VALIDATE_RET( A != NULL );
1432 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001433
Hanno Becker73d7d792018-12-11 10:35:51 +00001434 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001435 if( A->s * B->s < 0 )
1436 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001438 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 X->s = s;
1441 }
1442 else
1443 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001445 X->s = -s;
1446 }
1447 }
1448 else
1449 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001450 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001451 X->s = s;
1452 }
1453
1454cleanup:
1455
1456 return( ret );
1457}
1458
1459/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001460 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462int mbedtls_mpi_sub_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/*
1495 * Signed addition: X = A + b
1496 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001498{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 mbedtls_mpi _B;
1500 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001501 MPI_VALIDATE_RET( X != NULL );
1502 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001503
1504 p[0] = ( b < 0 ) ? -b : b;
1505 _B.s = ( b < 0 ) ? -1 : 1;
1506 _B.n = 1;
1507 _B.p = p;
1508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510}
1511
1512/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001513 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001516{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517 mbedtls_mpi _B;
1518 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001519 MPI_VALIDATE_RET( X != NULL );
1520 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521
1522 p[0] = ( b < 0 ) ? -b : b;
1523 _B.s = ( b < 0 ) ? -1 : 1;
1524 _B.n = 1;
1525 _B.p = p;
1526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001527 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001528}
1529
1530/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001532 */
1533static
1534#if defined(__APPLE__) && defined(__arm__)
1535/*
1536 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1537 * appears to need this to prevent bad ARM code generation at -O3.
1538 */
1539__attribute__ ((noinline))
1540#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001541void 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 +00001542{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
1545#if defined(MULADDC_HUIT)
1546 for( ; i >= 8; i -= 8 )
1547 {
1548 MULADDC_INIT
1549 MULADDC_HUIT
1550 MULADDC_STOP
1551 }
1552
1553 for( ; i > 0; i-- )
1554 {
1555 MULADDC_INIT
1556 MULADDC_CORE
1557 MULADDC_STOP
1558 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001559#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001560 for( ; i >= 16; i -= 16 )
1561 {
1562 MULADDC_INIT
1563 MULADDC_CORE MULADDC_CORE
1564 MULADDC_CORE MULADDC_CORE
1565 MULADDC_CORE MULADDC_CORE
1566 MULADDC_CORE MULADDC_CORE
1567
1568 MULADDC_CORE MULADDC_CORE
1569 MULADDC_CORE MULADDC_CORE
1570 MULADDC_CORE MULADDC_CORE
1571 MULADDC_CORE MULADDC_CORE
1572 MULADDC_STOP
1573 }
1574
1575 for( ; i >= 8; i -= 8 )
1576 {
1577 MULADDC_INIT
1578 MULADDC_CORE MULADDC_CORE
1579 MULADDC_CORE MULADDC_CORE
1580
1581 MULADDC_CORE MULADDC_CORE
1582 MULADDC_CORE MULADDC_CORE
1583 MULADDC_STOP
1584 }
1585
1586 for( ; i > 0; i-- )
1587 {
1588 MULADDC_INIT
1589 MULADDC_CORE
1590 MULADDC_STOP
1591 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001592#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001593
1594 t++;
1595
1596 do {
1597 *d += c; c = ( *d < c ); d++;
1598 }
1599 while( c != 0 );
1600}
1601
1602/*
1603 * Baseline multiplication: X = A * B (HAC 14.12)
1604 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001606{
Paul Bakker23986e52011-04-24 08:57:21 +00001607 int ret;
1608 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001610 MPI_VALIDATE_RET( X != NULL );
1611 MPI_VALIDATE_RET( A != NULL );
1612 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001615
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1617 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001618
Paul Bakker23986e52011-04-24 08:57:21 +00001619 for( i = A->n; i > 0; i-- )
1620 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001621 break;
1622
Paul Bakker23986e52011-04-24 08:57:21 +00001623 for( j = B->n; j > 0; j-- )
1624 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001625 break;
1626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1628 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001629
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001630 for( ; j > 0; j-- )
1631 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001632
1633 X->s = A->s * B->s;
1634
1635cleanup:
1636
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001638
1639 return( ret );
1640}
1641
1642/*
1643 * Baseline multiplication: X = A * b
1644 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001645int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001646{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001647 mbedtls_mpi _B;
1648 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001649 MPI_VALIDATE_RET( X != NULL );
1650 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001651
1652 _B.s = 1;
1653 _B.n = 1;
1654 _B.p = p;
1655 p[0] = b;
1656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001658}
1659
1660/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001661 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1662 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001663 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001664static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1665 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001666{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001667#if defined(MBEDTLS_HAVE_UDBL)
1668 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001669#else
Simon Butcher9803d072016-01-03 00:24:34 +00001670 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1671 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001672 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1673 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001674 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001675#endif
1676
Simon Butcher15b15d12015-11-26 19:35:03 +00001677 /*
1678 * Check for overflow
1679 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001680 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001681 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001682 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001683
Simon Butcherf5ba0452015-12-27 23:01:55 +00001684 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001685 }
1686
1687#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001688 dividend = (mbedtls_t_udbl) u1 << biL;
1689 dividend |= (mbedtls_t_udbl) u0;
1690 quotient = dividend / d;
1691 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1692 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1693
1694 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001695 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001696
1697 return (mbedtls_mpi_uint) quotient;
1698#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001699
1700 /*
1701 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1702 * Vol. 2 - Seminumerical Algorithms, Knuth
1703 */
1704
1705 /*
1706 * Normalize the divisor, d, and dividend, u0, u1
1707 */
1708 s = mbedtls_clz( d );
1709 d = d << s;
1710
1711 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001712 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001713 u0 = u0 << s;
1714
1715 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001716 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001717
1718 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001719 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001720
1721 /*
1722 * Find the first quotient and remainder
1723 */
1724 q1 = u1 / d1;
1725 r0 = u1 - d1 * q1;
1726
1727 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1728 {
1729 q1 -= 1;
1730 r0 += d1;
1731
1732 if ( r0 >= radix ) break;
1733 }
1734
Simon Butcherf5ba0452015-12-27 23:01:55 +00001735 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001736 q0 = rAX / d1;
1737 r0 = rAX - q0 * d1;
1738
1739 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1740 {
1741 q0 -= 1;
1742 r0 += d1;
1743
1744 if ( r0 >= radix ) break;
1745 }
1746
1747 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001748 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001749
1750 quotient = q1 * radix + q0;
1751
1752 return quotient;
1753#endif
1754}
1755
1756/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001758 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001759int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1760 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001761{
Paul Bakker23986e52011-04-24 08:57:21 +00001762 int ret;
1763 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001764 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001765 MPI_VALIDATE_RET( A != NULL );
1766 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1769 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001771 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1772 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001775 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1777 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 return( 0 );
1779 }
1780
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001781 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1782 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001783 X.s = Y.s = 1;
1784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001785 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1786 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1787 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1788 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001790 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001791 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001792 {
1793 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1795 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796 }
1797 else k = 0;
1798
1799 n = X.n - 1;
1800 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001804 {
1805 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
1810 for( i = n; i > t ; i-- )
1811 {
1812 if( X.p[i] >= Y.p[t] )
1813 Z.p[i - t - 1] = ~0;
1814 else
1815 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001816 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1817 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001818 }
1819
1820 Z.p[i - t - 1]++;
1821 do
1822 {
1823 Z.p[i - t - 1]--;
1824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001826 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001827 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001831 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1832 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001833 T2.p[2] = X.p[i];
1834 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1838 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1839 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1844 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 Z.p[i - t - 1]--;
1847 }
1848 }
1849
1850 if( Q != NULL )
1851 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 Q->s = A->s * B->s;
1854 }
1855
1856 if( R != NULL )
1857 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001859 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 R->s = 1;
1864 }
1865
1866cleanup:
1867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1869 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001870
1871 return( ret );
1872}
1873
1874/*
1875 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001876 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001877int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1878 const mbedtls_mpi *A,
1879 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001880{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001881 mbedtls_mpi _B;
1882 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001883 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885 p[0] = ( b < 0 ) ? -b : b;
1886 _B.s = ( b < 0 ) ? -1 : 1;
1887 _B.n = 1;
1888 _B.p = p;
1889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891}
1892
1893/*
1894 * Modulo: R = A mod B
1895 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001897{
1898 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001899 MPI_VALIDATE_RET( R != NULL );
1900 MPI_VALIDATE_RET( A != NULL );
1901 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1904 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001905
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001908 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1909 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1912 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001913
1914cleanup:
1915
1916 return( ret );
1917}
1918
1919/*
1920 * Modulo: r = A mod b
1921 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001923{
Paul Bakker23986e52011-04-24 08:57:21 +00001924 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001926 MPI_VALIDATE_RET( r != NULL );
1927 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
1929 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001930 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931
1932 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001934
1935 /*
1936 * handle trivial cases
1937 */
1938 if( b == 1 )
1939 {
1940 *r = 0;
1941 return( 0 );
1942 }
1943
1944 if( b == 2 )
1945 {
1946 *r = A->p[0] & 1;
1947 return( 0 );
1948 }
1949
1950 /*
1951 * general case
1952 */
Paul Bakker23986e52011-04-24 08:57:21 +00001953 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001954 {
Paul Bakker23986e52011-04-24 08:57:21 +00001955 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001956 y = ( y << biH ) | ( x >> biH );
1957 z = y / b;
1958 y -= z * b;
1959
1960 x <<= biH;
1961 y = ( y << biH ) | ( x >> biH );
1962 z = y / b;
1963 y -= z * b;
1964 }
1965
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001966 /*
1967 * If A is negative, then the current y represents a negative value.
1968 * Flipping it to the positive side.
1969 */
1970 if( A->s < 0 && y != 0 )
1971 y = b - y;
1972
Paul Bakker5121ce52009-01-03 21:22:43 +00001973 *r = y;
1974
1975 return( 0 );
1976}
1977
1978/*
1979 * Fast Montgomery initialization (thanks to Tom St Denis)
1980 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001982{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001984 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
1986 x = m0;
1987 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001988
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001989 for( i = biL; i >= 8; i /= 2 )
1990 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
1992 *mm = ~x + 1;
1993}
1994
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02001995/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1996 *
1997 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine635a3742020-06-08 22:37:50 +02001998 * It must have at least as many limbs as N
1999 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02002000 * On successful completion, A contains the result of
2001 * the multiplication A * B * R^-1 mod N where
2002 * R = (2^ciL)^n.
2003 * \param[in] B One of the numbers to multiply.
2004 * It must be nonzero and must not have more limbs than N
2005 * (B->n <= N->n).
2006 * \param[in] N The modulo. N must be odd.
2007 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2008 * This is -N^-1 mod 2^ciL.
2009 * \param[in,out] T A bignum for temporary storage.
2010 * It must be at least twice the limb size of N plus 2
2011 * (T->n >= 2 * (N->n + 1)).
2012 * Its initial content is unused and
2013 * its final content is indeterminate.
2014 * Note that unlike the usual convention in the library
2015 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002016 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002017static 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 +02002018 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002019{
Paul Bakker23986e52011-04-24 08:57:21 +00002020 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 memset( T->p, 0, T->n * ciL );
2024
2025 d = T->p;
2026 n = N->n;
2027 m = ( B->n < n ) ? B->n : n;
2028
2029 for( i = 0; i < n; i++ )
2030 {
2031 /*
2032 * T = (T + u0*B + u1*N) / 2^biL
2033 */
2034 u0 = A->p[i];
2035 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2036
2037 mpi_mul_hlp( m, B->p, d, u0 );
2038 mpi_mul_hlp( n, N->p, d, u1 );
2039
2040 *d++ = u0; d[n + 1] = 0;
2041 }
2042
Gilles Peskine635a3742020-06-08 22:37:50 +02002043 /* At this point, d is either the desired result or the desired result
2044 * plus N. We now potentially subtract N, avoiding leaking whether the
2045 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
Gilles Peskine635a3742020-06-08 22:37:50 +02002047 /* Copy the n least significant limbs of d to A, so that
2048 * A = d if d < N (recall that N has n limbs). */
2049 memcpy( A->p, d, n * ciL );
Gilles Peskinede719d52020-06-09 10:39:38 +02002050 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine635a3742020-06-08 22:37:50 +02002051 * do the calculation without using conditional tests. */
2052 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine8f672662020-06-04 21:05:24 +02002053 d[n] += 1;
Gilles Peskine36acd542020-06-08 21:58:22 +02002054 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskine635a3742020-06-08 22:37:50 +02002055 /* If d0 < N then d < (2^biL)^n
2056 * so d[n] == 0 and we want to keep A as it is.
2057 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2058 * so d[n] == 1 and we want to set A to the result of the subtraction
2059 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2060 * This exactly corresponds to a conditional assignment. */
2061 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002062}
2063
2064/*
2065 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02002066 *
2067 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002068 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002069static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2070 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002071{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 mbedtls_mpi_uint z = 1;
2073 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
Paul Bakker8ddb6452013-02-27 14:56:33 +01002075 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002076 U.p = &z;
2077
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002078 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079}
2080
Manuel Pégourié-Gonnard432ebba2021-06-03 10:42:46 +02002081/*
2082 * Constant-flow boolean "equal" comparison:
2083 * return x == y
2084 *
2085 * This function can be used to write constant-time code by replacing branches
2086 * with bit operations - it can be used in conjunction with
2087 * mbedtls_ssl_cf_mask_from_bit().
2088 *
2089 * This function is implemented without using comparison operators, as those
2090 * might be translated to branches by some compilers on some platforms.
2091 */
2092static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2093{
2094 /* diff = 0 if x == y, non-zero otherwise */
2095 const size_t diff = x ^ y;
2096
2097 /* MSVC has a warning about unary minus on unsigned integer types,
2098 * but this is well-defined and precisely what we want to do here. */
2099#if defined(_MSC_VER)
2100#pragma warning( push )
2101#pragma warning( disable : 4146 )
2102#endif
2103
2104 /* diff_msb's most significant bit is equal to x != y */
2105 const size_t diff_msb = ( diff | -diff );
2106
2107#if defined(_MSC_VER)
2108#pragma warning( pop )
2109#endif
2110
2111 /* diff1 = (x != y) ? 1 : 0 */
2112 const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2113
2114 return( 1 ^ diff1 );
2115}
2116
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002117/**
2118 * Select an MPI from a table without leaking the index.
2119 *
2120 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2121 * reads the entire table in order to avoid leaking the value of idx to an
2122 * attacker able to observe memory access patterns.
2123 *
2124 * \param[out] R Where to write the selected MPI.
2125 * \param[in] T The table to read from.
2126 * \param[in] T_size The number of elements in the table.
2127 * \param[in] idx The index of the element to select;
2128 * this must satisfy 0 <= idx < T_size.
2129 *
2130 * \return \c 0 on success, or a negative error code.
2131 */
2132static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2133{
2134 int ret;
2135
2136 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard432ebba2021-06-03 10:42:46 +02002137 {
2138 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
2139 mbedtls_mpi_cf_bool_eq( i, idx ) ) );
2140 }
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002141
2142cleanup:
2143 return( ret );
2144}
2145
Paul Bakker5121ce52009-01-03 21:22:43 +00002146/*
2147 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2148 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002149int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2150 const mbedtls_mpi *E, const mbedtls_mpi *N,
2151 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002152{
Paul Bakker23986e52011-04-24 08:57:21 +00002153 int ret;
2154 size_t wbits, wsize, one = 1;
2155 size_t i, j, nblimbs;
2156 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002158 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002159 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
Hanno Becker73d7d792018-12-11 10:35:51 +00002161 MPI_VALIDATE_RET( X != NULL );
2162 MPI_VALIDATE_RET( A != NULL );
2163 MPI_VALIDATE_RET( E != NULL );
2164 MPI_VALIDATE_RET( N != NULL );
2165
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002166 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2170 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002171
Chris Jonesad59a2a2020-11-25 15:12:39 +00002172 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2173 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2174 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2175
Paul Bakkerf6198c12012-05-16 08:02:29 +00002176 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002177 * Init temps and window size
2178 */
2179 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2181 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002182 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183 memset( W, 0, sizeof( W ) );
2184
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002185 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
2187 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2188 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2189
Peter Kolbusb83d41d2018-12-11 14:01:44 -06002190#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2192 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06002193#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002194
Paul Bakker5121ce52009-01-03 21:22:43 +00002195 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2197 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2198 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
2200 /*
Paul Bakker50546922012-05-19 08:40:49 +00002201 * Compensate for negative A (and correct at the end)
2202 */
2203 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002204 if( neg )
2205 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002207 Apos.s = 1;
2208 A = &Apos;
2209 }
2210
2211 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 * If 1st call, pre-compute R^2 mod N
2213 */
2214 if( _RR == NULL || _RR->p == NULL )
2215 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002216 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2217 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2218 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219
2220 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002222 }
2223 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002225
2226 /*
2227 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2228 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2230 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002231 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002234 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002235
2236 /*
2237 * X = R^2 * R^-1 mod N = R mod N
2238 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002240 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002241
2242 if( wsize > 1 )
2243 {
2244 /*
2245 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2246 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002247 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2250 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002251
2252 for( i = 0; i < wsize - 1; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002253 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002254
Paul Bakker5121ce52009-01-03 21:22:43 +00002255 /*
2256 * W[i] = W[i - 1] * W[1]
2257 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002258 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2261 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002262
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002263 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 }
2265 }
2266
2267 nblimbs = E->n;
2268 bufsize = 0;
2269 nbits = 0;
2270 wbits = 0;
2271 state = 0;
2272
2273 while( 1 )
2274 {
2275 if( bufsize == 0 )
2276 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002277 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 break;
2279
Paul Bakker0d7702c2013-10-29 16:18:35 +01002280 nblimbs--;
2281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 }
2284
2285 bufsize--;
2286
2287 ei = (E->p[nblimbs] >> bufsize) & 1;
2288
2289 /*
2290 * skip leading 0s
2291 */
2292 if( ei == 0 && state == 0 )
2293 continue;
2294
2295 if( ei == 0 && state == 1 )
2296 {
2297 /*
2298 * out of window, square X
2299 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002300 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 continue;
2302 }
2303
2304 /*
2305 * add ei to current window
2306 */
2307 state = 2;
2308
2309 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002310 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
2312 if( nbits == wsize )
2313 {
2314 /*
2315 * X = X^wsize R^-1 mod N
2316 */
2317 for( i = 0; i < wsize; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002318 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319
2320 /*
2321 * X = X * W[wbits] R^-1 mod N
2322 */
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002323 MBEDTLS_MPI_CHK( mpi_select( &WW, W, 1 << wsize, wbits ) );
2324 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002325
2326 state--;
2327 nbits = 0;
2328 wbits = 0;
2329 }
2330 }
2331
2332 /*
2333 * process the remaining bits
2334 */
2335 for( i = 0; i < nbits; i++ )
2336 {
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002337 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
2339 wbits <<= 1;
2340
Paul Bakker66d5d072014-06-17 16:39:18 +02002341 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002342 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343 }
2344
2345 /*
2346 * X = A^E * R * R^-1 mod N = A^E mod N
2347 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002348 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
Hanno Beckera4af1c42017-04-18 09:07:45 +01002350 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002351 {
2352 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002354 }
2355
Paul Bakker5121ce52009-01-03 21:22:43 +00002356cleanup:
2357
Paul Bakker66d5d072014-06-17 16:39:18 +02002358 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002362 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002363
Paul Bakker75a28602014-03-31 12:08:17 +02002364 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
2367 return( ret );
2368}
2369
Paul Bakker5121ce52009-01-03 21:22:43 +00002370/*
2371 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2372 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002374{
Paul Bakker23986e52011-04-24 08:57:21 +00002375 int ret;
2376 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002377 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002378
Hanno Becker73d7d792018-12-11 10:35:51 +00002379 MPI_VALIDATE_RET( G != NULL );
2380 MPI_VALIDATE_RET( A != NULL );
2381 MPI_VALIDATE_RET( B != NULL );
2382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2386 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 lz = mbedtls_mpi_lsb( &TA );
2389 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002390
Paul Bakker66d5d072014-06-17 16:39:18 +02002391 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002392 lz = lzt;
2393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2395 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002396
Paul Bakker5121ce52009-01-03 21:22:43 +00002397 TA.s = TB.s = 1;
2398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2402 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2407 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002408 }
2409 else
2410 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2412 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002413 }
2414 }
2415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2417 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002418
2419cleanup:
2420
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
2423 return( ret );
2424}
2425
Paul Bakker33dc46b2014-04-30 16:11:39 +02002426/*
2427 * Fill X with size bytes of random.
2428 *
2429 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002430 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002431 * deterministic, eg for tests).
2432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002433int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002434 int (*f_rng)(void *, unsigned char *, size_t),
2435 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002436{
Paul Bakker23986e52011-04-24 08:57:21 +00002437 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002438 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002439 size_t const overhead = ( limbs * ciL ) - size;
2440 unsigned char *Xp;
2441
Hanno Becker8ce11a32018-12-19 16:18:52 +00002442 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002443 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002444
Hanno Beckerda1655a2017-10-18 14:21:44 +01002445 /* Ensure that target MPI has exactly the necessary number of limbs */
2446 if( X->n != limbs )
2447 {
2448 mbedtls_mpi_free( X );
2449 mbedtls_mpi_init( X );
2450 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2451 }
2452 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002453
Hanno Beckerda1655a2017-10-18 14:21:44 +01002454 Xp = (unsigned char*) X->p;
Gilles Peskine05251142020-11-25 16:15:14 +01002455 MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002456
Hanno Becker2be8a552018-10-25 12:40:09 +01002457 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002458
2459cleanup:
2460 return( ret );
2461}
2462
Paul Bakker5121ce52009-01-03 21:22:43 +00002463/*
2464 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2465 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002467{
2468 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002469 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002470 MPI_VALIDATE_RET( X != NULL );
2471 MPI_VALIDATE_RET( A != NULL );
2472 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002473
Hanno Becker4bcb4912017-04-18 15:49:39 +01002474 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2478 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2479 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002486 goto cleanup;
2487 }
2488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2490 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2491 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2492 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2495 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2496 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2497 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002498
2499 do
2500 {
2501 while( ( TU.p[0] & 1 ) == 0 )
2502 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002504
2505 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2506 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2508 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002509 }
2510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2512 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513 }
2514
2515 while( ( TV.p[0] & 1 ) == 0 )
2516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002518
2519 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2520 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2522 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002523 }
2524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2526 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002527 }
2528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002530 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002531 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2532 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2533 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002534 }
2535 else
2536 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2538 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2539 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002540 }
2541 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2545 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2548 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002551
2552cleanup:
2553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2555 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2556 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002557
2558 return( ret );
2559}
2560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002561#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002562
Paul Bakker5121ce52009-01-03 21:22:43 +00002563static const int small_prime[] =
2564{
2565 3, 5, 7, 11, 13, 17, 19, 23,
2566 29, 31, 37, 41, 43, 47, 53, 59,
2567 61, 67, 71, 73, 79, 83, 89, 97,
2568 101, 103, 107, 109, 113, 127, 131, 137,
2569 139, 149, 151, 157, 163, 167, 173, 179,
2570 181, 191, 193, 197, 199, 211, 223, 227,
2571 229, 233, 239, 241, 251, 257, 263, 269,
2572 271, 277, 281, 283, 293, 307, 311, 313,
2573 317, 331, 337, 347, 349, 353, 359, 367,
2574 373, 379, 383, 389, 397, 401, 409, 419,
2575 421, 431, 433, 439, 443, 449, 457, 461,
2576 463, 467, 479, 487, 491, 499, 503, 509,
2577 521, 523, 541, 547, 557, 563, 569, 571,
2578 577, 587, 593, 599, 601, 607, 613, 617,
2579 619, 631, 641, 643, 647, 653, 659, 661,
2580 673, 677, 683, 691, 701, 709, 719, 727,
2581 733, 739, 743, 751, 757, 761, 769, 773,
2582 787, 797, 809, 811, 821, 823, 827, 829,
2583 839, 853, 857, 859, 863, 877, 881, 883,
2584 887, 907, 911, 919, 929, 937, 941, 947,
2585 953, 967, 971, 977, 983, 991, 997, -103
2586};
2587
2588/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002589 * Small divisors test (X must be positive)
2590 *
2591 * Return values:
2592 * 0: no small factor (possible prime, more tests needed)
2593 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002595 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002598{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002599 int ret = 0;
2600 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002602
Paul Bakker5121ce52009-01-03 21:22:43 +00002603 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002605
2606 for( i = 0; small_prime[i] > 0; i++ )
2607 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002608 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002609 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002611 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002612
2613 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002614 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002615 }
2616
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002617cleanup:
2618 return( ret );
2619}
2620
2621/*
2622 * Miller-Rabin pseudo-primality test (HAC 4.24)
2623 */
Janos Follathda31fa12018-09-03 14:45:23 +01002624static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002625 int (*f_rng)(void *, unsigned char *, size_t),
2626 void *p_rng )
2627{
Pascal Junodb99183d2015-03-11 16:49:45 +01002628 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002629 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002631
Hanno Becker8ce11a32018-12-19 16:18:52 +00002632 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002633 MPI_VALIDATE_RET( f_rng != NULL );
2634
2635 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2636 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002637 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002638
Paul Bakker5121ce52009-01-03 21:22:43 +00002639 /*
2640 * W = |X| - 1
2641 * R = W >> lsb( W )
2642 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2644 s = mbedtls_mpi_lsb( &W );
2645 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2646 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002647
Janos Follathda31fa12018-09-03 14:45:23 +01002648 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002649 {
2650 /*
2651 * pick a random A, 1 < A < |X| - 1
2652 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002653 count = 0;
2654 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002655 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002656
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002657 j = mbedtls_mpi_bitlen( &A );
2658 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002659 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002660 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002661 }
2662
2663 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002664 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2665 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002666 }
2667
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002668 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2669 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002670
2671 /*
2672 * A = A^R mod |X|
2673 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002674 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002676 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2677 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002678 continue;
2679
2680 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002681 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002682 {
2683 /*
2684 * A = A * A mod |X|
2685 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002686 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2687 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002688
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002690 break;
2691
2692 j++;
2693 }
2694
2695 /*
2696 * not prime if A != |X| - 1 or A == 1
2697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2699 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002700 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002702 break;
2703 }
2704 }
2705
2706cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002707 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2708 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002709 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002710
2711 return( ret );
2712}
2713
2714/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002715 * Pseudo-primality test: small factors, then Miller-Rabin
2716 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002717int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2718 int (*f_rng)(void *, unsigned char *, size_t),
2719 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002720{
2721 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002722 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002723 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002724 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002725
2726 XX.s = 1;
2727 XX.n = X->n;
2728 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2731 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2732 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002734 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002735 return( 0 );
2736
2737 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2738 {
2739 if( ret == 1 )
2740 return( 0 );
2741
2742 return( ret );
2743 }
2744
Janos Follathda31fa12018-09-03 14:45:23 +01002745 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002746}
2747
Janos Follatha0b67c22018-09-18 14:48:23 +01002748#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002749/*
2750 * Pseudo-primality test, error probability 2^-80
2751 */
2752int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2753 int (*f_rng)(void *, unsigned char *, size_t),
2754 void *p_rng )
2755{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002756 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002757 MPI_VALIDATE_RET( f_rng != NULL );
2758
Janos Follatha0b67c22018-09-18 14:48:23 +01002759 /*
2760 * In the past our key generation aimed for an error rate of at most
2761 * 2^-80. Since this function is deprecated, aim for the same certainty
2762 * here as well.
2763 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002764 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002765}
Janos Follatha0b67c22018-09-18 14:48:23 +01002766#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002767
2768/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002769 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002770 *
Janos Follathf301d232018-08-14 13:34:01 +01002771 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2772 * be either 1024 bits or 1536 bits long, and flags must contain
2773 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002774 */
Janos Follath7c025a92018-08-14 11:08:41 +01002775int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002776 int (*f_rng)(void *, unsigned char *, size_t),
2777 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002778{
Jethro Beekman66689272018-02-14 19:24:10 -08002779#ifdef MBEDTLS_HAVE_INT64
2780// ceil(2^63.5)
2781#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2782#else
2783// ceil(2^31.5)
2784#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2785#endif
2786 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002787 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002788 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 mbedtls_mpi_uint r;
2790 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002791
Hanno Becker8ce11a32018-12-19 16:18:52 +00002792 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002793 MPI_VALIDATE_RET( f_rng != NULL );
2794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2796 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002797
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002798 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002799
2800 n = BITS_TO_LIMBS( nbits );
2801
Janos Follathda31fa12018-09-03 14:45:23 +01002802 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2803 {
2804 /*
2805 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2806 */
2807 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2808 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2809 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2810 }
2811 else
2812 {
2813 /*
2814 * 2^-100 error probability, number of rounds computed based on HAC,
2815 * fact 4.48
2816 */
2817 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2818 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2819 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2820 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2821 }
2822
Jethro Beekman66689272018-02-14 19:24:10 -08002823 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002824 {
Jethro Beekman66689272018-02-14 19:24:10 -08002825 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2826 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2827 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2828
2829 k = n * biL;
2830 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2831 X->p[0] |= 1;
2832
Janos Follath7c025a92018-08-14 11:08:41 +01002833 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002834 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002835 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002837 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002838 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002839 }
Jethro Beekman66689272018-02-14 19:24:10 -08002840 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002841 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002842 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002843 * An necessary condition for Y and X = 2Y + 1 to be prime
2844 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2845 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002846 */
Jethro Beekman66689272018-02-14 19:24:10 -08002847
2848 X->p[0] |= 2;
2849
2850 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2851 if( r == 0 )
2852 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2853 else if( r == 1 )
2854 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2855
2856 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2857 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2858 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2859
2860 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002861 {
Jethro Beekman66689272018-02-14 19:24:10 -08002862 /*
2863 * First, check small factors for X and Y
2864 * before doing Miller-Rabin on any of them
2865 */
2866 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2867 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002868 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002869 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002870 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002871 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002872 goto cleanup;
2873
2874 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2875 goto cleanup;
2876
2877 /*
2878 * Next candidates. We want to preserve Y = (X-1) / 2 and
2879 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2880 * so up Y by 6 and X by 12.
2881 */
2882 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2883 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002884 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002885 }
2886 }
2887
2888cleanup:
2889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002890 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002891
2892 return( ret );
2893}
2894
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002895#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002896
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002897#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002898
Paul Bakker23986e52011-04-24 08:57:21 +00002899#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002900
2901static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2902{
2903 { 693, 609, 21 },
2904 { 1764, 868, 28 },
2905 { 768454923, 542167814, 1 }
2906};
2907
Paul Bakker5121ce52009-01-03 21:22:43 +00002908/*
2909 * Checkup routine
2910 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002911int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002912{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002913 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002914 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002916 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2917 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002918
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002919 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002920 "EFE021C2645FD1DC586E69184AF4A31E" \
2921 "D5F53E93B5F123FA41680867BA110131" \
2922 "944FE7952E2517337780CB0DB80E61AA" \
2923 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002925 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002926 "B2E7EFD37075B9F03FF989C7C5051C20" \
2927 "34D2A323810251127E7BF8625A4F49A5" \
2928 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2929 "5B5C25763222FEFCCFC38B832366C29E" ) );
2930
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002931 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002932 "0066A198186C18C10B2F5ED9B522752A" \
2933 "9830B69916E535C8F047518A889A43A5" \
2934 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2935
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002936 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002938 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002939 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2940 "9E857EA95A03512E2BAE7391688D264A" \
2941 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2942 "8001B72E848A38CAE1C65F78E56ABDEF" \
2943 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2944 "ECF677152EF804370C1A305CAF3B5BF1" \
2945 "30879B56C61DE584A0F53A2447A51E" ) );
2946
2947 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002948 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002950 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002951 {
2952 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002953 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002954
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002955 ret = 1;
2956 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002957 }
2958
2959 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002960 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002962 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002964 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002965 "256567336059E52CAE22925474705F39A94" ) );
2966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002967 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002968 "6613F26162223DF488E9CD48CC132C7A" \
2969 "0AC93C701B001B092E4E5B9F73BCD27B" \
2970 "9EE50D0657C77F374E903CDFA4C642" ) );
2971
2972 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002973 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002975 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2976 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002977 {
2978 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002979 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002980
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002981 ret = 1;
2982 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002983 }
2984
2985 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002986 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002988 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002990 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002991 "36E139AEA55215609D2816998ED020BB" \
2992 "BD96C37890F65171D948E9BC7CBAA4D9" \
2993 "325D24D6A3C12710F10A09FA08AB87" ) );
2994
2995 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002996 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002997
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002998 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002999 {
3000 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003001 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003002
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003003 ret = 1;
3004 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003005 }
3006
3007 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003008 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003010 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003011
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003012 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003013 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3014 "C3DBA76456363A10869622EAC2DD84EC" \
3015 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3016
3017 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003018 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003020 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003021 {
3022 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003023 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003024
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003025 ret = 1;
3026 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003027 }
3028
3029 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003030 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003031
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003032 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003033 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003034
Paul Bakker66d5d072014-06-17 16:39:18 +02003035 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003036 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003037 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3038 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003040 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003042 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003043 {
3044 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003045 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003046
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003047 ret = 1;
3048 goto cleanup;
3049 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003050 }
3051
3052 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003053 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003054
Paul Bakker5121ce52009-01-03 21:22:43 +00003055cleanup:
3056
3057 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003058 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003060 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3061 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003062
3063 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003064 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003065
3066 return( ret );
3067}
3068
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003069#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003071#endif /* MBEDTLS_BIGNUM_C */