blob: f4de16b918b8408edf5f3d80ba862f56140a5711 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
Simon Butcher15b15d12015-11-26 19:35:03 +000019
Paul Bakker5121ce52009-01-03 21:22:43 +000020/*
Simon Butcher15b15d12015-11-26 19:35:03 +000021 * The following sources were referenced in the design of this Multi-precision
22 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000023 *
Simon Butcher15b15d12015-11-26 19:35:03 +000024 * [1] Handbook of Applied Cryptography - 1997
25 * Menezes, van Oorschot and Vanstone
26 *
27 * [2] Multi-Precision Math
28 * Tom St Denis
29 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30 *
31 * [3] GNU Multi-Precision Arithmetic Library
32 * https://gmplib.org/manual/index.html
33 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000034 */
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Gilles Peskinedb09ef62020-06-03 01:43:33 +020036#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/bignum.h"
41#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050042#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000043#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000044
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <string.h>
46
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000048#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020049#else
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <stdio.h>
51#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020053#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020055#endif
56
Hanno Becker73d7d792018-12-11 10:35:51 +000057#define MPI_VALIDATE_RET( cond ) \
58 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
59#define MPI_VALIDATE( cond ) \
60 MBEDTLS_INTERNAL_VALIDATE( cond )
61
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000063#define biL (ciL << 3) /* bits in limb */
64#define biH (ciL << 2) /* half limb size */
65
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010066#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
67
Paul Bakker5121ce52009-01-03 21:22:43 +000068/*
69 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020070 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000071 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020072#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
73#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000074
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050075/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050076static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
77{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050078 mbedtls_platform_zeroize( v, ciL * n );
79}
80
Paul Bakker5121ce52009-01-03 21:22:43 +000081/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000083 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000085{
Hanno Becker73d7d792018-12-11 10:35:51 +000086 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000087
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 X->s = 1;
89 X->n = 0;
90 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000091}
92
93/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000094 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
Paul Bakker6c591fa2011-05-05 11:49:20 +000098 if( X == NULL )
99 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200103 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000105 }
106
Paul Bakker6c591fa2011-05-05 11:49:20 +0000107 X->s = 1;
108 X->n = 0;
109 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000110}
111
112/*
113 * Enlarge to the specified number of limbs
114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000116{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000118 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200121 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000122
Paul Bakker5121ce52009-01-03 21:22:43 +0000123 if( X->n < nblimbs )
124 {
Simon Butcher29176892016-05-20 00:19:09 +0100125 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->p != NULL )
129 {
130 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200131 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 }
134
135 X->n = nblimbs;
136 X->p = p;
137 }
138
139 return( 0 );
140}
141
142/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143 * Resize down as much as possible,
144 * while keeping at least the specified number of limbs
145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000150 MPI_VALIDATE_RET( X != NULL );
151
152 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
153 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100155 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100156 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine322752b2020-01-21 13:59:51 +0100158 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 for( i = X->n - 1; i > 0; i-- )
161 if( X->p[i] != 0 )
162 break;
163 i++;
164
165 if( i < nblimbs )
166 i = nblimbs;
167
Simon Butcher29176892016-05-20 00:19:09 +0100168 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200169 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100171 if( X->p != NULL )
172 {
173 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200174 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100176 }
177
178 X->n = i;
179 X->p = p;
180
181 return( 0 );
182}
183
184/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000185 * Copy the contents of Y into X
186 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000188{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100189 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000190 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000191 MPI_VALIDATE_RET( X != NULL );
192 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000193
194 if( X == Y )
195 return( 0 );
196
Gilles Peskinedb420622020-01-20 21:12:50 +0100197 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200198 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200200 return( 0 );
201 }
202
Paul Bakker5121ce52009-01-03 21:22:43 +0000203 for( i = Y->n - 1; i > 0; i-- )
204 if( Y->p[i] != 0 )
205 break;
206 i++;
207
208 X->s = Y->s;
209
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100210 if( X->n < i )
211 {
212 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
213 }
214 else
215 {
216 memset( X->p + i, 0, ( X->n - i ) * ciL );
217 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000218
Paul Bakker5121ce52009-01-03 21:22:43 +0000219 memcpy( X->p, Y->p, i * ciL );
220
221cleanup:
222
223 return( ret );
224}
225
226/*
227 * Swap the contents of X and Y
228 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000230{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000232 MPI_VALIDATE( X != NULL );
233 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000234
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 memcpy( &T, X, sizeof( mbedtls_mpi ) );
236 memcpy( X, Y, sizeof( mbedtls_mpi ) );
237 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238}
239
Manuel Pégourié-Gonnard3ae4ae42021-06-07 09:51:00 +0200240/**
241 * Select between two sign values in constant-time.
242 *
243 * This is functionally equivalent to second ? a : b but uses only bit
244 * operations in order to avoid branches.
245 *
246 * \param[in] a The first sign; must be either +1 or -1.
247 * \param[in] b The second sign; must be either +1 or -1.
248 * \param[in] second Must be either 1 (return b) or 0 (return a).
249 *
250 * \return The selected sign value.
251 */
252static int mpi_safe_cond_select_sign( int a, int b, unsigned char second )
253{
254 /* In order to avoid questions about what we can reasonnably assume about
255 * the representations of signed integers, move everything to unsigned
256 * by taking advantage of the fact that a and b are either +1 or -1. */
257 unsigned ua = a + 1;
258 unsigned ub = b + 1;
259
Manuel Pégourié-Gonnard31ec1d72021-06-10 09:36:41 +0200260 /* second was 0 or 1, mask is 0 or 2 as are ua and ub */
261 const unsigned mask = second << 1;
Manuel Pégourié-Gonnard3ae4ae42021-06-07 09:51:00 +0200262
263 /* select ua or ub */
264 unsigned ur = ( ua & ~mask ) | ( ub & mask );
265
266 /* ur is now 0 or 2, convert back to -1 or +1 */
267 return( (int) ur - 1 );
268}
269
Paul Bakker5121ce52009-01-03 21:22:43 +0000270/*
Gilles Peskinef04d11e2020-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é-Gonnard5ada7a82021-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 Peskinef04d11e2020-06-04 19:14:58 +0200297 for( i = 0; i < n; i++ )
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200298 dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
Gilles Peskinef04d11e2020-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é-Gonnard5ada7a82021-05-31 11:48:45 +0200310 mbedtls_mpi_uint limb_mask;
Hanno Becker73d7d792018-12-11 10:35:51 +0000311 MPI_VALIDATE_RET( X != NULL );
312 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100313
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200314 /* MSVC has a warning about unary minus on unsigned integer types,
315 * but this is well-defined and precisely what we want to do here. */
316#if defined(_MSC_VER)
317#pragma warning( push )
318#pragma warning( disable : 4146 )
319#endif
320
Pascal Junodb99183d2015-03-11 16:49:45 +0100321 /* make sure assign is 0 or 1 in a time-constant manner */
322 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200323 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200324 limb_mask = -assign;
325
326#if defined(_MSC_VER)
327#pragma warning( pop )
328#endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200330 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100331
Manuel Pégourié-Gonnard3ae4ae42021-06-07 09:51:00 +0200332 X->s = mpi_safe_cond_select_sign( X->s, Y->s, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100333
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200334 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100335
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200336 for( i = Y->n; i < X->n; i++ )
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200337 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100338
339cleanup:
340 return( ret );
341}
342
343/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100344 * Conditionally swap X and Y, without leaking information
345 * about whether the swap was made or not.
346 * Here it is not ok to simply swap the pointers, which whould lead to
347 * different memory access patterns when X and Y are used afterwards.
348 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100350{
351 int ret, s;
352 size_t i;
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200353 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000355 MPI_VALIDATE_RET( X != NULL );
356 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100357
358 if( X == Y )
359 return( 0 );
360
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200361 /* MSVC has a warning about unary minus on unsigned integer types,
362 * but this is well-defined and precisely what we want to do here. */
363#if defined(_MSC_VER)
364#pragma warning( push )
365#pragma warning( disable : 4146 )
366#endif
367
Pascal Junodb99183d2015-03-11 16:49:45 +0100368 /* make sure swap is 0 or 1 in a time-constant manner */
369 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200370 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200371 limb_mask = -swap;
372
373#if defined(_MSC_VER)
374#pragma warning( pop )
375#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
378 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100379
380 s = X->s;
Manuel Pégourié-Gonnard3ae4ae42021-06-07 09:51:00 +0200381 X->s = mpi_safe_cond_select_sign( X->s, Y->s, swap );
382 Y->s = mpi_safe_cond_select_sign( Y->s, s, swap );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100383
384
385 for( i = 0; i < X->n; i++ )
386 {
387 tmp = X->p[i];
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200388 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
389 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100390 }
391
392cleanup:
393 return( ret );
394}
395
396/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000397 * Set value from integer
398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000400{
Janos Follath24eed8d2019-11-22 13:21:35 +0000401 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000402 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000405 memset( X->p, 0, X->n * ciL );
406
407 X->p[0] = ( z < 0 ) ? -z : z;
408 X->s = ( z < 0 ) ? -1 : 1;
409
410cleanup:
411
412 return( ret );
413}
414
415/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000416 * Get a specific bit
417 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000419{
Hanno Becker73d7d792018-12-11 10:35:51 +0000420 MPI_VALIDATE_RET( X != NULL );
421
Paul Bakker2f5947e2011-05-18 15:47:11 +0000422 if( X->n * biL <= pos )
423 return( 0 );
424
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200425 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000426}
427
Gilles Peskine11cdb052018-11-20 16:47:47 +0100428/* Get a specific byte, without range checks. */
429#define GET_BYTE( X, i ) \
430 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
431
Paul Bakker2f5947e2011-05-18 15:47:11 +0000432/*
433 * Set a bit to a specific value of 0 or 1
434 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000436{
437 int ret = 0;
438 size_t off = pos / biL;
439 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000440 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000441
442 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200444
Paul Bakker2f5947e2011-05-18 15:47:11 +0000445 if( X->n * biL <= pos )
446 {
447 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200448 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000451 }
452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
454 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000455
456cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200457
Paul Bakker2f5947e2011-05-18 15:47:11 +0000458 return( ret );
459}
460
461/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200462 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000465{
Paul Bakker23986e52011-04-24 08:57:21 +0000466 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000467 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000470 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000471 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
472 return( count );
473
474 return( 0 );
475}
476
477/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000478 * Count leading zero bits in a given integer
479 */
480static size_t mbedtls_clz( const mbedtls_mpi_uint x )
481{
482 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100483 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000484
485 for( j = 0; j < biL; j++ )
486 {
487 if( x & mask ) break;
488
489 mask >>= 1;
490 }
491
492 return j;
493}
494
495/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200496 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000497 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200498size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000499{
Paul Bakker23986e52011-04-24 08:57:21 +0000500 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000501
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200502 if( X->n == 0 )
503 return( 0 );
504
Paul Bakker5121ce52009-01-03 21:22:43 +0000505 for( i = X->n - 1; i > 0; i-- )
506 if( X->p[i] != 0 )
507 break;
508
Simon Butcher15b15d12015-11-26 19:35:03 +0000509 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000510
Paul Bakker23986e52011-04-24 08:57:21 +0000511 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000512}
513
514/*
515 * Return the total size in bytes
516 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000518{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200519 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000520}
521
522/*
523 * Convert an ASCII character to digit value
524 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000526{
527 *d = 255;
528
529 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
530 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
531 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 if( *d >= (mbedtls_mpi_uint) radix )
534 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
536 return( 0 );
537}
538
539/*
540 * Import from an ASCII string
541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000543{
Janos Follath24eed8d2019-11-22 13:21:35 +0000544 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000545 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 mbedtls_mpi_uint d;
547 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000548 MPI_VALIDATE_RET( X != NULL );
549 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000550
551 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000552 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Paul Bakkerff60ee62010-03-16 21:09:09 +0000556 slen = strlen( s );
557
Paul Bakker5121ce52009-01-03 21:22:43 +0000558 if( radix == 16 )
559 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100560 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200561 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
562
Paul Bakkerff60ee62010-03-16 21:09:09 +0000563 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
566 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000567
Paul Bakker23986e52011-04-24 08:57:21 +0000568 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000569 {
Paul Bakker23986e52011-04-24 08:57:21 +0000570 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 {
572 X->s = -1;
573 break;
574 }
575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200577 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 }
579 }
580 else
581 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
Paul Bakkerff60ee62010-03-16 21:09:09 +0000584 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000585 {
586 if( i == 0 && s[i] == '-' )
587 {
588 X->s = -1;
589 continue;
590 }
591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
593 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000594
595 if( X->s == 1 )
596 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000598 }
599 else
600 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000602 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 }
604 }
605
606cleanup:
607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 return( ret );
611}
612
613/*
Ron Eldora16fa292018-11-20 14:07:01 +0200614 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 */
Ron Eldora16fa292018-11-20 14:07:01 +0200616static int mpi_write_hlp( mbedtls_mpi *X, int radix,
617 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000618{
Janos Follath24eed8d2019-11-22 13:21:35 +0000619 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200621 size_t length = 0;
622 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
Ron Eldora16fa292018-11-20 14:07:01 +0200624 do
625 {
626 if( length >= buflen )
627 {
628 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
629 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
Ron Eldora16fa292018-11-20 14:07:01 +0200631 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
632 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
633 /*
634 * Write the residue in the current position, as an ASCII character.
635 */
636 if( r < 0xA )
637 *(--p_end) = (char)( '0' + r );
638 else
639 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000640
Ron Eldora16fa292018-11-20 14:07:01 +0200641 length++;
642 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
Ron Eldora16fa292018-11-20 14:07:01 +0200644 memmove( *p, p_end, length );
645 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
647cleanup:
648
649 return( ret );
650}
651
652/*
653 * Export into an ASCII string
654 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100655int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
656 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000657{
Paul Bakker23986e52011-04-24 08:57:21 +0000658 int ret = 0;
659 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000662 MPI_VALIDATE_RET( X != NULL );
663 MPI_VALIDATE_RET( olen != NULL );
664 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000665
666 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000667 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000668
Hanno Becker23cfea02019-02-04 09:45:07 +0000669 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
670 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
671 * `n`. If radix > 4, this might be a strict
672 * overapproximation of the number of
673 * radix-adic digits needed to present `n`. */
674 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
675 * present `n`. */
676
Janos Follath80470622019-03-06 13:43:02 +0000677 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000678 n += 1; /* Compensate for the divisions above, which round down `n`
679 * in case it's not even. */
680 n += 1; /* Potential '-'-sign. */
681 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
682 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100684 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000685 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100686 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000688 }
689
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100690 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
693 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000694 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000695 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000696 buflen--;
697 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
699 if( radix == 16 )
700 {
Paul Bakker23986e52011-04-24 08:57:21 +0000701 int c;
702 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
Paul Bakker23986e52011-04-24 08:57:21 +0000704 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000705 {
Paul Bakker23986e52011-04-24 08:57:21 +0000706 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000707 {
Paul Bakker23986e52011-04-24 08:57:21 +0000708 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000709
Paul Bakker6c343d72014-07-10 14:36:19 +0200710 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000711 continue;
712
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000713 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000714 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000715 k = 1;
716 }
717 }
718 }
719 else
720 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000722
723 if( T.s == -1 )
724 T.s = 1;
725
Ron Eldora16fa292018-11-20 14:07:01 +0200726 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000727 }
728
729 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100730 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000731
732cleanup:
733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
736 return( ret );
737}
738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000740/*
741 * Read X from an opened file
742 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000744{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000746 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000747 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000748 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000749 * Buffer should have space for (short) label and decimal formatted MPI,
750 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000751 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000753
Hanno Becker73d7d792018-12-11 10:35:51 +0000754 MPI_VALIDATE_RET( X != NULL );
755 MPI_VALIDATE_RET( fin != NULL );
756
757 if( radix < 2 || radix > 16 )
758 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
759
Paul Bakker5121ce52009-01-03 21:22:43 +0000760 memset( s, 0, sizeof( s ) );
761 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200762 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000763
764 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000765 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000767
Hanno Beckerb2034b72017-04-26 11:46:46 +0100768 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
769 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000770
771 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100772 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000773 if( mpi_get_digit( &d, radix, *p ) != 0 )
774 break;
775
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000777}
778
779/*
780 * Write X into an opened file (or stdout if fout == NULL)
781 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000783{
Janos Follath24eed8d2019-11-22 13:21:35 +0000784 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000785 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000786 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000787 * Buffer should have space for (short) label and decimal formatted MPI,
788 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000789 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200790 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000791 MPI_VALIDATE_RET( X != NULL );
792
793 if( radix < 2 || radix > 16 )
794 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000795
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100796 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000797
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100798 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000799
800 if( p == NULL ) p = "";
801
802 plen = strlen( p );
803 slen = strlen( s );
804 s[slen++] = '\r';
805 s[slen++] = '\n';
806
807 if( fout != NULL )
808 {
809 if( fwrite( p, 1, plen, fout ) != plen ||
810 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000812 }
813 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
816cleanup:
817
818 return( ret );
819}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000821
Hanno Beckerda1655a2017-10-18 14:21:44 +0100822
823/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
824 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000825
826static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
827{
828 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100829 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000830 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100831
832 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
833 {
834 tmp <<= CHAR_BIT;
835 tmp |= (mbedtls_mpi_uint) *x_ptr;
836 }
837
Hanno Beckerf8720072018-11-08 11:53:49 +0000838 return( tmp );
839}
840
841static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
842{
843#if defined(__BYTE_ORDER__)
844
845/* Nothing to do on bigendian systems. */
846#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
847 return( x );
848#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
849
850#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
851
852/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000853#if defined(__GNUC__) && defined(__GNUC_PREREQ)
854#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000855#define have_bswap
856#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000857#endif
858
859#if defined(__clang__) && defined(__has_builtin)
860#if __has_builtin(__builtin_bswap32) && \
861 __has_builtin(__builtin_bswap64)
862#define have_bswap
863#endif
864#endif
865
Hanno Beckerf8720072018-11-08 11:53:49 +0000866#if defined(have_bswap)
867 /* The compiler is hopefully able to statically evaluate this! */
868 switch( sizeof(mbedtls_mpi_uint) )
869 {
870 case 4:
871 return( __builtin_bswap32(x) );
872 case 8:
873 return( __builtin_bswap64(x) );
874 }
875#endif
876#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
877#endif /* __BYTE_ORDER__ */
878
879 /* Fall back to C-based reordering if we don't know the byte order
880 * or we couldn't use a compiler-specific builtin. */
881 return( mpi_uint_bigendian_to_host_c( x ) );
882}
883
Hanno Becker2be8a552018-10-25 12:40:09 +0100884static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100885{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100886 mbedtls_mpi_uint *cur_limb_left;
887 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100888 if( limbs == 0 )
889 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100890
891 /*
892 * Traverse limbs and
893 * - adapt byte-order in each limb
894 * - swap the limbs themselves.
895 * For that, simultaneously traverse the limbs from left to right
896 * and from right to left, as long as the left index is not bigger
897 * than the right index (it's not a problem if limbs is odd and the
898 * indices coincide in the last iteration).
899 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100900 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
901 cur_limb_left <= cur_limb_right;
902 cur_limb_left++, cur_limb_right-- )
903 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000904 mbedtls_mpi_uint tmp;
905 /* Note that if cur_limb_left == cur_limb_right,
906 * this code effectively swaps the bytes only once. */
907 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
908 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
909 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100910 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100911}
912
Paul Bakker5121ce52009-01-03 21:22:43 +0000913/*
Janos Follatha778a942019-02-13 10:28:28 +0000914 * Import X from unsigned binary data, little endian
915 */
916int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
917 const unsigned char *buf, size_t buflen )
918{
Janos Follath24eed8d2019-11-22 13:21:35 +0000919 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000920 size_t i;
921 size_t const limbs = CHARS_TO_LIMBS( buflen );
922
923 /* Ensure that target MPI has exactly the necessary number of limbs */
924 if( X->n != limbs )
925 {
926 mbedtls_mpi_free( X );
927 mbedtls_mpi_init( X );
928 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
929 }
930
931 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
932
933 for( i = 0; i < buflen; i++ )
934 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
935
936cleanup:
937
Janos Follath171a7ef2019-02-15 16:17:45 +0000938 /*
939 * This function is also used to import keys. However, wiping the buffers
940 * upon failure is not necessary because failure only can happen before any
941 * input is copied.
942 */
Janos Follatha778a942019-02-13 10:28:28 +0000943 return( ret );
944}
945
946/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000947 * Import X from unsigned binary data, big endian
948 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000950{
Janos Follath24eed8d2019-11-22 13:21:35 +0000951 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100952 size_t const limbs = CHARS_TO_LIMBS( buflen );
953 size_t const overhead = ( limbs * ciL ) - buflen;
954 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000955
Hanno Becker8ce11a32018-12-19 16:18:52 +0000956 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000957 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
958
Hanno Becker073c1992017-10-17 15:17:27 +0100959 /* Ensure that target MPI has exactly the necessary number of limbs */
960 if( X->n != limbs )
961 {
962 mbedtls_mpi_free( X );
963 mbedtls_mpi_init( X );
964 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
965 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000967
Hanno Becker0e810b92019-01-03 17:13:11 +0000968 /* Avoid calling `memcpy` with NULL source argument,
969 * even if buflen is 0. */
970 if( buf != NULL )
971 {
972 Xp = (unsigned char*) X->p;
973 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100974
Hanno Becker0e810b92019-01-03 17:13:11 +0000975 mpi_bigendian_to_host( X->p, limbs );
976 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000977
978cleanup:
979
Janos Follath171a7ef2019-02-15 16:17:45 +0000980 /*
981 * This function is also used to import keys. However, wiping the buffers
982 * upon failure is not necessary because failure only can happen before any
983 * input is copied.
984 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000985 return( ret );
986}
987
988/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000989 * Export X into unsigned binary data, little endian
990 */
991int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
992 unsigned char *buf, size_t buflen )
993{
994 size_t stored_bytes = X->n * ciL;
995 size_t bytes_to_copy;
996 size_t i;
997
998 if( stored_bytes < buflen )
999 {
1000 bytes_to_copy = stored_bytes;
1001 }
1002 else
1003 {
1004 bytes_to_copy = buflen;
1005
1006 /* The output buffer is smaller than the allocated size of X.
1007 * However X may fit if its leading bytes are zero. */
1008 for( i = bytes_to_copy; i < stored_bytes; i++ )
1009 {
1010 if( GET_BYTE( X, i ) != 0 )
1011 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1012 }
1013 }
1014
1015 for( i = 0; i < bytes_to_copy; i++ )
1016 buf[i] = GET_BYTE( X, i );
1017
1018 if( stored_bytes < buflen )
1019 {
1020 /* Write trailing 0 bytes */
1021 memset( buf + stored_bytes, 0, buflen - stored_bytes );
1022 }
1023
1024 return( 0 );
1025}
1026
1027/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001028 * Export X into unsigned binary data, big endian
1029 */
Gilles Peskine11cdb052018-11-20 16:47:47 +01001030int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
1031 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001032{
Hanno Becker73d7d792018-12-11 10:35:51 +00001033 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +01001034 size_t bytes_to_copy;
1035 unsigned char *p;
1036 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001037
Hanno Becker73d7d792018-12-11 10:35:51 +00001038 MPI_VALIDATE_RET( X != NULL );
1039 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
1040
1041 stored_bytes = X->n * ciL;
1042
Gilles Peskine11cdb052018-11-20 16:47:47 +01001043 if( stored_bytes < buflen )
1044 {
1045 /* There is enough space in the output buffer. Write initial
1046 * null bytes and record the position at which to start
1047 * writing the significant bytes. In this case, the execution
1048 * trace of this function does not depend on the value of the
1049 * number. */
1050 bytes_to_copy = stored_bytes;
1051 p = buf + buflen - stored_bytes;
1052 memset( buf, 0, buflen - stored_bytes );
1053 }
1054 else
1055 {
1056 /* The output buffer is smaller than the allocated size of X.
1057 * However X may fit if its leading bytes are zero. */
1058 bytes_to_copy = buflen;
1059 p = buf;
1060 for( i = bytes_to_copy; i < stored_bytes; i++ )
1061 {
1062 if( GET_BYTE( X, i ) != 0 )
1063 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1064 }
1065 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001066
Gilles Peskine11cdb052018-11-20 16:47:47 +01001067 for( i = 0; i < bytes_to_copy; i++ )
1068 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069
1070 return( 0 );
1071}
1072
1073/*
1074 * Left-shift: X <<= count
1075 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001076int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001077{
Janos Follath24eed8d2019-11-22 13:21:35 +00001078 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001079 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001081 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001082
1083 v0 = count / (biL );
1084 t1 = count & (biL - 1);
1085
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001086 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001087
Paul Bakkerf9688572011-05-05 10:00:45 +00001088 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001090
1091 ret = 0;
1092
1093 /*
1094 * shift by count / limb_size
1095 */
1096 if( v0 > 0 )
1097 {
Paul Bakker23986e52011-04-24 08:57:21 +00001098 for( i = X->n; i > v0; i-- )
1099 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001100
Paul Bakker23986e52011-04-24 08:57:21 +00001101 for( ; i > 0; i-- )
1102 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001103 }
1104
1105 /*
1106 * shift by count % limb_size
1107 */
1108 if( t1 > 0 )
1109 {
1110 for( i = v0; i < X->n; i++ )
1111 {
1112 r1 = X->p[i] >> (biL - t1);
1113 X->p[i] <<= t1;
1114 X->p[i] |= r0;
1115 r0 = r1;
1116 }
1117 }
1118
1119cleanup:
1120
1121 return( ret );
1122}
1123
1124/*
1125 * Right-shift: X >>= count
1126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001128{
Paul Bakker23986e52011-04-24 08:57:21 +00001129 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001131 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001132
1133 v0 = count / biL;
1134 v1 = count & (biL - 1);
1135
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001136 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001137 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001138
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 /*
1140 * shift by count / limb_size
1141 */
1142 if( v0 > 0 )
1143 {
1144 for( i = 0; i < X->n - v0; i++ )
1145 X->p[i] = X->p[i + v0];
1146
1147 for( ; i < X->n; i++ )
1148 X->p[i] = 0;
1149 }
1150
1151 /*
1152 * shift by count % limb_size
1153 */
1154 if( v1 > 0 )
1155 {
Paul Bakker23986e52011-04-24 08:57:21 +00001156 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001157 {
Paul Bakker23986e52011-04-24 08:57:21 +00001158 r1 = X->p[i - 1] << (biL - v1);
1159 X->p[i - 1] >>= v1;
1160 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 r0 = r1;
1162 }
1163 }
1164
1165 return( 0 );
1166}
1167
1168/*
1169 * Compare unsigned values
1170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001171int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001172{
Paul Bakker23986e52011-04-24 08:57:21 +00001173 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001174 MPI_VALIDATE_RET( X != NULL );
1175 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001176
Paul Bakker23986e52011-04-24 08:57:21 +00001177 for( i = X->n; i > 0; i-- )
1178 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001179 break;
1180
Paul Bakker23986e52011-04-24 08:57:21 +00001181 for( j = Y->n; j > 0; j-- )
1182 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001183 break;
1184
Paul Bakker23986e52011-04-24 08:57:21 +00001185 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186 return( 0 );
1187
1188 if( i > j ) return( 1 );
1189 if( j > i ) return( -1 );
1190
Paul Bakker23986e52011-04-24 08:57:21 +00001191 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 {
Paul Bakker23986e52011-04-24 08:57:21 +00001193 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1194 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001195 }
1196
1197 return( 0 );
1198}
1199
1200/*
1201 * Compare signed values
1202 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001204{
Paul Bakker23986e52011-04-24 08:57:21 +00001205 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001206 MPI_VALIDATE_RET( X != NULL );
1207 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001208
Paul Bakker23986e52011-04-24 08:57:21 +00001209 for( i = X->n; i > 0; i-- )
1210 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001211 break;
1212
Paul Bakker23986e52011-04-24 08:57:21 +00001213 for( j = Y->n; j > 0; j-- )
1214 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001215 break;
1216
Paul Bakker23986e52011-04-24 08:57:21 +00001217 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001218 return( 0 );
1219
1220 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001221 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001222
1223 if( X->s > 0 && Y->s < 0 ) return( 1 );
1224 if( Y->s > 0 && X->s < 0 ) return( -1 );
1225
Paul Bakker23986e52011-04-24 08:57:21 +00001226 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001227 {
Paul Bakker23986e52011-04-24 08:57:21 +00001228 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1229 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 }
1231
1232 return( 0 );
1233}
1234
Janos Follath3f6f0e42019-10-14 09:09:32 +01001235/** Decide if an integer is less than the other, without branches.
1236 *
1237 * \param x First integer.
1238 * \param y Second integer.
1239 *
1240 * \return 1 if \p x is less than \p y, 0 otherwise
1241 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001242static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1243 const mbedtls_mpi_uint y )
Janos Follathee6abce2019-09-05 14:47:19 +01001244{
1245 mbedtls_mpi_uint ret;
1246 mbedtls_mpi_uint cond;
1247
1248 /*
1249 * Check if the most significant bits (MSB) of the operands are different.
1250 */
1251 cond = ( x ^ y );
1252 /*
1253 * If the MSB are the same then the difference x-y will be negative (and
1254 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1255 */
1256 ret = ( x - y ) & ~cond;
1257 /*
1258 * If the MSB are different, then the operand with the MSB of 1 is the
1259 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1260 * the MSB of y is 0.)
1261 */
1262 ret |= y & cond;
1263
1264
Janos Follatha0f732b2019-10-14 08:59:14 +01001265 ret = ret >> ( biL - 1 );
Janos Follathee6abce2019-09-05 14:47:19 +01001266
Janos Follath67ce6472019-10-29 15:08:46 +00001267 return (unsigned) ret;
Janos Follathee6abce2019-09-05 14:47:19 +01001268}
1269
1270/*
1271 * Compare signed values in constant time
1272 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001273int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1274 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001275{
1276 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001277 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001278 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001279
1280 MPI_VALIDATE_RET( X != NULL );
1281 MPI_VALIDATE_RET( Y != NULL );
1282 MPI_VALIDATE_RET( ret != NULL );
1283
1284 if( X->n != Y->n )
1285 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1286
1287 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001288 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1289 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001290 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001291 X_is_negative = ( X->s & 2 ) >> 1;
1292 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001293
1294 /*
1295 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001296 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1297 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001298 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001299 cond = ( X_is_negative ^ Y_is_negative );
1300 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001301
1302 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001303 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001304 * need to go through the loop. Record if we have the result already.
1305 */
Janos Follathee6abce2019-09-05 14:47:19 +01001306 done = cond;
1307
1308 for( i = X->n; i > 0; i-- )
1309 {
1310 /*
Janos Follath30702422019-11-05 12:24:52 +00001311 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1312 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001313 *
1314 * Again even if we can make a decision, we just mark the result and
1315 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001316 */
Janos Follath30702422019-11-05 12:24:52 +00001317 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1318 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001319 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001320
1321 /*
Janos Follath30702422019-11-05 12:24:52 +00001322 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1323 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001324 *
1325 * Again even if we can make a decision, we just mark the result and
1326 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001327 */
Janos Follath30702422019-11-05 12:24:52 +00001328 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1329 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001330 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001331 }
1332
1333 return( 0 );
1334}
1335
Paul Bakker5121ce52009-01-03 21:22:43 +00001336/*
1337 * Compare signed values
1338 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001340{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 mbedtls_mpi Y;
1342 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001343 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344
1345 *p = ( z < 0 ) ? -z : z;
1346 Y.s = ( z < 0 ) ? -1 : 1;
1347 Y.n = 1;
1348 Y.p = p;
1349
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351}
1352
1353/*
1354 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001357{
Janos Follath24eed8d2019-11-22 13:21:35 +00001358 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001359 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001360 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001361 MPI_VALIDATE_RET( X != NULL );
1362 MPI_VALIDATE_RET( A != NULL );
1363 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
1365 if( X == B )
1366 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 }
1369
1370 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001372
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001373 /*
1374 * X should always be positive as a result of unsigned additions.
1375 */
1376 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001377
Paul Bakker23986e52011-04-24 08:57:21 +00001378 for( j = B->n; j > 0; j-- )
1379 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001380 break;
1381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383
1384 o = B->p; p = X->p; c = 0;
1385
Janos Follath6c922682015-10-30 17:43:11 +01001386 /*
1387 * tmp is used because it might happen that p == o
1388 */
Paul Bakker23986e52011-04-24 08:57:21 +00001389 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001390 {
Janos Follath6c922682015-10-30 17:43:11 +01001391 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001392 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001393 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001394 }
1395
1396 while( c != 0 )
1397 {
1398 if( i >= X->n )
1399 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 p = X->p + i;
1402 }
1403
Paul Bakker2d319fd2012-09-16 21:34:26 +00001404 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 }
1406
1407cleanup:
1408
1409 return( ret );
1410}
1411
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001412/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001413 * Helper for mbedtls_mpi subtraction.
1414 *
1415 * Calculate d - s where d and s have the same size.
1416 * This function operates modulo (2^ciL)^n and returns the carry
1417 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1418 *
1419 * \param n Number of limbs of \p d and \p s.
1420 * \param[in,out] d On input, the left operand.
1421 * On output, the result of the subtraction:
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001422 * \param[in] s The right operand.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001423 *
1424 * \return 1 if `d < s`.
1425 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001427static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1428 mbedtls_mpi_uint *d,
1429 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001430{
Paul Bakker23986e52011-04-24 08:57:21 +00001431 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001433
1434 for( i = c = 0; i < n; i++, s++, d++ )
1435 {
1436 z = ( *d < c ); *d -= c;
1437 c = ( *d < *s ) + z; *d -= *s;
1438 }
1439
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001440 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001441}
1442
1443/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001444 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001445 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001447{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448 mbedtls_mpi TB;
Janos Follath24eed8d2019-11-22 13:21:35 +00001449 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001450 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001451 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001452 MPI_VALIDATE_RET( X != NULL );
1453 MPI_VALIDATE_RET( A != NULL );
1454 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001456 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001457
1458 if( X == B )
1459 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001461 B = &TB;
1462 }
1463
1464 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001466
Paul Bakker1ef7a532009-06-20 10:50:55 +00001467 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001468 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001469 */
1470 X->s = 1;
1471
Paul Bakker5121ce52009-01-03 21:22:43 +00001472 ret = 0;
1473
Paul Bakker23986e52011-04-24 08:57:21 +00001474 for( n = B->n; n > 0; n-- )
1475 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001476 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001477 if( n > A->n )
1478 {
1479 /* B >= (2^ciL)^n > A */
1480 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1481 goto cleanup;
1482 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001484 carry = mpi_sub_hlp( n, X->p, B->p );
1485 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001486 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001487 /* Propagate the carry to the first nonzero limb of X. */
1488 for( ; n < X->n && X->p[n] == 0; n++ )
1489 --X->p[n];
1490 /* If we ran out of space for the carry, it means that the result
1491 * is negative. */
1492 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001493 {
1494 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1495 goto cleanup;
1496 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001497 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001498 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001499
1500cleanup:
1501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001503
1504 return( ret );
1505}
1506
1507/*
1508 * Signed addition: X = A + B
1509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001511{
Hanno Becker73d7d792018-12-11 10:35:51 +00001512 int ret, s;
1513 MPI_VALIDATE_RET( X != NULL );
1514 MPI_VALIDATE_RET( A != NULL );
1515 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
Hanno Becker73d7d792018-12-11 10:35:51 +00001517 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 if( A->s * B->s < 0 )
1519 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001523 X->s = s;
1524 }
1525 else
1526 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001527 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001528 X->s = -s;
1529 }
1530 }
1531 else
1532 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001534 X->s = s;
1535 }
1536
1537cleanup:
1538
1539 return( ret );
1540}
1541
1542/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001543 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001544 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001546{
Hanno Becker73d7d792018-12-11 10:35:51 +00001547 int ret, s;
1548 MPI_VALIDATE_RET( X != NULL );
1549 MPI_VALIDATE_RET( A != NULL );
1550 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001551
Hanno Becker73d7d792018-12-11 10:35:51 +00001552 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001553 if( A->s * B->s > 0 )
1554 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001556 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001557 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001558 X->s = s;
1559 }
1560 else
1561 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 X->s = -s;
1564 }
1565 }
1566 else
1567 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001569 X->s = s;
1570 }
1571
1572cleanup:
1573
1574 return( ret );
1575}
1576
1577/*
1578 * Signed addition: X = A + b
1579 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001580int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001581{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 mbedtls_mpi _B;
1583 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001584 MPI_VALIDATE_RET( X != NULL );
1585 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001586
1587 p[0] = ( b < 0 ) ? -b : b;
1588 _B.s = ( b < 0 ) ? -1 : 1;
1589 _B.n = 1;
1590 _B.p = p;
1591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001593}
1594
1595/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001596 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001597 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001599{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001600 mbedtls_mpi _B;
1601 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001602 MPI_VALIDATE_RET( X != NULL );
1603 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604
1605 p[0] = ( b < 0 ) ? -b : b;
1606 _B.s = ( b < 0 ) ? -1 : 1;
1607 _B.n = 1;
1608 _B.p = p;
1609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001611}
1612
1613/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001615 */
1616static
1617#if defined(__APPLE__) && defined(__arm__)
1618/*
1619 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1620 * appears to need this to prevent bad ARM code generation at -O3.
1621 */
1622__attribute__ ((noinline))
1623#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001624void 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 +00001625{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001627
1628#if defined(MULADDC_HUIT)
1629 for( ; i >= 8; i -= 8 )
1630 {
1631 MULADDC_INIT
1632 MULADDC_HUIT
1633 MULADDC_STOP
1634 }
1635
1636 for( ; i > 0; i-- )
1637 {
1638 MULADDC_INIT
1639 MULADDC_CORE
1640 MULADDC_STOP
1641 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001642#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001643 for( ; i >= 16; i -= 16 )
1644 {
1645 MULADDC_INIT
1646 MULADDC_CORE MULADDC_CORE
1647 MULADDC_CORE MULADDC_CORE
1648 MULADDC_CORE MULADDC_CORE
1649 MULADDC_CORE MULADDC_CORE
1650
1651 MULADDC_CORE MULADDC_CORE
1652 MULADDC_CORE MULADDC_CORE
1653 MULADDC_CORE MULADDC_CORE
1654 MULADDC_CORE MULADDC_CORE
1655 MULADDC_STOP
1656 }
1657
1658 for( ; i >= 8; i -= 8 )
1659 {
1660 MULADDC_INIT
1661 MULADDC_CORE MULADDC_CORE
1662 MULADDC_CORE MULADDC_CORE
1663
1664 MULADDC_CORE MULADDC_CORE
1665 MULADDC_CORE MULADDC_CORE
1666 MULADDC_STOP
1667 }
1668
1669 for( ; i > 0; i-- )
1670 {
1671 MULADDC_INIT
1672 MULADDC_CORE
1673 MULADDC_STOP
1674 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001675#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001676
1677 t++;
1678
1679 do {
1680 *d += c; c = ( *d < c ); d++;
1681 }
1682 while( c != 0 );
1683}
1684
1685/*
1686 * Baseline multiplication: X = A * B (HAC 14.12)
1687 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001689{
Janos Follath24eed8d2019-11-22 13:21:35 +00001690 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001691 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001693 MPI_VALIDATE_RET( X != NULL );
1694 MPI_VALIDATE_RET( A != NULL );
1695 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001698
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1700 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001701
Paul Bakker23986e52011-04-24 08:57:21 +00001702 for( i = A->n; i > 0; i-- )
1703 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 break;
1705
Paul Bakker23986e52011-04-24 08:57:21 +00001706 for( j = B->n; j > 0; j-- )
1707 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001708 break;
1709
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001710 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1711 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001712
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001713 for( ; j > 0; j-- )
1714 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001715
1716 X->s = A->s * B->s;
1717
1718cleanup:
1719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001720 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
1722 return( ret );
1723}
1724
1725/*
1726 * Baseline multiplication: X = A * b
1727 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001729{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 mbedtls_mpi _B;
1731 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001732 MPI_VALIDATE_RET( X != NULL );
1733 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001734
1735 _B.s = 1;
1736 _B.n = 1;
1737 _B.p = p;
1738 p[0] = b;
1739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001740 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001741}
1742
1743/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001744 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1745 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001746 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001747static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1748 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001749{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001750#if defined(MBEDTLS_HAVE_UDBL)
1751 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001752#else
Simon Butcher9803d072016-01-03 00:24:34 +00001753 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1754 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001755 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1756 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001757 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001758#endif
1759
Simon Butcher15b15d12015-11-26 19:35:03 +00001760 /*
1761 * Check for overflow
1762 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001763 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001764 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001765 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001766
Simon Butcherf5ba0452015-12-27 23:01:55 +00001767 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001768 }
1769
1770#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001771 dividend = (mbedtls_t_udbl) u1 << biL;
1772 dividend |= (mbedtls_t_udbl) u0;
1773 quotient = dividend / d;
1774 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1775 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1776
1777 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001778 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001779
1780 return (mbedtls_mpi_uint) quotient;
1781#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001782
1783 /*
1784 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1785 * Vol. 2 - Seminumerical Algorithms, Knuth
1786 */
1787
1788 /*
1789 * Normalize the divisor, d, and dividend, u0, u1
1790 */
1791 s = mbedtls_clz( d );
1792 d = d << s;
1793
1794 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001795 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001796 u0 = u0 << s;
1797
1798 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001799 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001800
1801 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001802 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001803
1804 /*
1805 * Find the first quotient and remainder
1806 */
1807 q1 = u1 / d1;
1808 r0 = u1 - d1 * q1;
1809
1810 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1811 {
1812 q1 -= 1;
1813 r0 += d1;
1814
1815 if ( r0 >= radix ) break;
1816 }
1817
Simon Butcherf5ba0452015-12-27 23:01:55 +00001818 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001819 q0 = rAX / d1;
1820 r0 = rAX - q0 * d1;
1821
1822 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1823 {
1824 q0 -= 1;
1825 r0 += d1;
1826
1827 if ( r0 >= radix ) break;
1828 }
1829
1830 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001831 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001832
1833 quotient = q1 * radix + q0;
1834
1835 return quotient;
1836#endif
1837}
1838
1839/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001842int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1843 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001844{
Janos Follath24eed8d2019-11-22 13:21:35 +00001845 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001846 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001848 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001849 MPI_VALIDATE_RET( A != NULL );
1850 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1853 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001856 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001857 /*
1858 * Avoid dynamic memory allocations for constant-size T2.
1859 *
1860 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1861 * so nobody increase the size of the MPI and we're safe to use an on-stack
1862 * buffer.
1863 */
Alexander K35d6d462019-10-31 14:46:45 +03001864 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001865 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1866 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1871 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 return( 0 );
1873 }
1874
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1876 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001877 X.s = Y.s = 1;
1878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1881 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001883 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001884 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 {
1886 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1888 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 }
1890 else k = 0;
1891
1892 n = X.n - 1;
1893 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 {
1898 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
1903 for( i = n; i > t ; i-- )
1904 {
1905 if( X.p[i] >= Y.p[t] )
1906 Z.p[i - t - 1] = ~0;
1907 else
1908 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001909 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1910 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001911 }
1912
Alexander K35d6d462019-10-31 14:46:45 +03001913 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1914 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1915 T2.p[2] = X.p[i];
1916
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 Z.p[i - t - 1]++;
1918 do
1919 {
1920 Z.p[i - t - 1]--;
1921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001923 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001924 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001926 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1931 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001934 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001935 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1936 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1937 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938 Z.p[i - t - 1]--;
1939 }
1940 }
1941
1942 if( Q != NULL )
1943 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945 Q->s = A->s * B->s;
1946 }
1947
1948 if( R != NULL )
1949 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001951 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001955 R->s = 1;
1956 }
1957
1958cleanup:
1959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001961 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001962 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001963
1964 return( ret );
1965}
1966
1967/*
1968 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001969 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001970int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1971 const mbedtls_mpi *A,
1972 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001973{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 mbedtls_mpi _B;
1975 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001976 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
1978 p[0] = ( b < 0 ) ? -b : b;
1979 _B.s = ( b < 0 ) ? -1 : 1;
1980 _B.n = 1;
1981 _B.p = p;
1982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984}
1985
1986/*
1987 * Modulo: R = A mod B
1988 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001990{
Janos Follath24eed8d2019-11-22 13:21:35 +00001991 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001992 MPI_VALIDATE_RET( R != NULL );
1993 MPI_VALIDATE_RET( A != NULL );
1994 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1997 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001999 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
2002 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002003
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002004 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
2005 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
2007cleanup:
2008
2009 return( ret );
2010}
2011
2012/*
2013 * Modulo: r = A mod b
2014 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00002016{
Paul Bakker23986e52011-04-24 08:57:21 +00002017 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00002019 MPI_VALIDATE_RET( r != NULL );
2020 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002021
2022 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00002024
2025 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
2028 /*
2029 * handle trivial cases
2030 */
2031 if( b == 1 )
2032 {
2033 *r = 0;
2034 return( 0 );
2035 }
2036
2037 if( b == 2 )
2038 {
2039 *r = A->p[0] & 1;
2040 return( 0 );
2041 }
2042
2043 /*
2044 * general case
2045 */
Paul Bakker23986e52011-04-24 08:57:21 +00002046 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00002047 {
Paul Bakker23986e52011-04-24 08:57:21 +00002048 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 y = ( y << biH ) | ( x >> biH );
2050 z = y / b;
2051 y -= z * b;
2052
2053 x <<= biH;
2054 y = ( y << biH ) | ( x >> biH );
2055 z = y / b;
2056 y -= z * b;
2057 }
2058
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002059 /*
2060 * If A is negative, then the current y represents a negative value.
2061 * Flipping it to the positive side.
2062 */
2063 if( A->s < 0 && y != 0 )
2064 y = b - y;
2065
Paul Bakker5121ce52009-01-03 21:22:43 +00002066 *r = y;
2067
2068 return( 0 );
2069}
2070
2071/*
2072 * Fast Montgomery initialization (thanks to Tom St Denis)
2073 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002075{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002077 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
2079 x = m0;
2080 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002082 for( i = biL; i >= 8; i /= 2 )
2083 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002084
2085 *mm = ~x + 1;
2086}
2087
Gilles Peskine2a82f722020-06-04 15:00:49 +02002088/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2089 *
2090 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002091 * It must have at least as many limbs as N
2092 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002093 * On successful completion, A contains the result of
2094 * the multiplication A * B * R^-1 mod N where
2095 * R = (2^ciL)^n.
2096 * \param[in] B One of the numbers to multiply.
2097 * It must be nonzero and must not have more limbs than N
2098 * (B->n <= N->n).
2099 * \param[in] N The modulo. N must be odd.
2100 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2101 * This is -N^-1 mod 2^ciL.
2102 * \param[in,out] T A bignum for temporary storage.
2103 * It must be at least twice the limb size of N plus 2
2104 * (T->n >= 2 * (N->n + 1)).
2105 * Its initial content is unused and
2106 * its final content is indeterminate.
2107 * Note that unlike the usual convention in the library
2108 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002110static 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 +02002111 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002112{
Paul Bakker23986e52011-04-24 08:57:21 +00002113 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002115
2116 memset( T->p, 0, T->n * ciL );
2117
2118 d = T->p;
2119 n = N->n;
2120 m = ( B->n < n ) ? B->n : n;
2121
2122 for( i = 0; i < n; i++ )
2123 {
2124 /*
2125 * T = (T + u0*B + u1*N) / 2^biL
2126 */
2127 u0 = A->p[i];
2128 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2129
2130 mpi_mul_hlp( m, B->p, d, u0 );
2131 mpi_mul_hlp( n, N->p, d, u1 );
2132
2133 *d++ = u0; d[n + 1] = 0;
2134 }
2135
Gilles Peskine221626f2020-06-08 22:37:50 +02002136 /* At this point, d is either the desired result or the desired result
2137 * plus N. We now potentially subtract N, avoiding leaking whether the
2138 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002139
Gilles Peskine221626f2020-06-08 22:37:50 +02002140 /* Copy the n least significant limbs of d to A, so that
2141 * A = d if d < N (recall that N has n limbs). */
2142 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002143 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002144 * do the calculation without using conditional tests. */
2145 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002146 d[n] += 1;
Gilles Peskinec097e9e2020-06-08 21:58:22 +02002147 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02002148 /* If d0 < N then d < (2^biL)^n
2149 * so d[n] == 0 and we want to keep A as it is.
2150 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2151 * so d[n] == 1 and we want to set A to the result of the subtraction
2152 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2153 * This exactly corresponds to a conditional assignment. */
2154 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002155}
2156
2157/*
2158 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002159 *
2160 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002161 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002162static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2163 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002164{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 mbedtls_mpi_uint z = 1;
2166 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002167
Paul Bakker8ddb6452013-02-27 14:56:33 +01002168 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002169 U.p = &z;
2170
Gilles Peskine4e91d472020-06-04 20:55:15 +02002171 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002172}
2173
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002174/*
2175 * Constant-flow boolean "equal" comparison:
2176 * return x == y
2177 *
2178 * This function can be used to write constant-time code by replacing branches
2179 * with bit operations - it can be used in conjunction with
2180 * mbedtls_ssl_cf_mask_from_bit().
2181 *
2182 * This function is implemented without using comparison operators, as those
2183 * might be translated to branches by some compilers on some platforms.
2184 */
2185static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2186{
2187 /* diff = 0 if x == y, non-zero otherwise */
2188 const size_t diff = x ^ y;
2189
2190 /* MSVC has a warning about unary minus on unsigned integer types,
2191 * but this is well-defined and precisely what we want to do here. */
2192#if defined(_MSC_VER)
2193#pragma warning( push )
2194#pragma warning( disable : 4146 )
2195#endif
2196
2197 /* diff_msb's most significant bit is equal to x != y */
2198 const size_t diff_msb = ( diff | -diff );
2199
2200#if defined(_MSC_VER)
2201#pragma warning( pop )
2202#endif
2203
2204 /* diff1 = (x != y) ? 1 : 0 */
2205 const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2206
2207 return( 1 ^ diff1 );
2208}
2209
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002210/**
2211 * Select an MPI from a table without leaking the index.
2212 *
2213 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2214 * reads the entire table in order to avoid leaking the value of idx to an
2215 * attacker able to observe memory access patterns.
2216 *
2217 * \param[out] R Where to write the selected MPI.
2218 * \param[in] T The table to read from.
2219 * \param[in] T_size The number of elements in the table.
2220 * \param[in] idx The index of the element to select;
2221 * this must satisfy 0 <= idx < T_size.
2222 *
2223 * \return \c 0 on success, or a negative error code.
2224 */
2225static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2226{
2227 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2228
2229 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002230 {
2231 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
Manuel Pégourié-Gonnarde22176e2021-06-10 09:34:00 +02002232 (unsigned char) mbedtls_mpi_cf_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002233 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002234
2235cleanup:
2236 return( ret );
2237}
2238
Paul Bakker5121ce52009-01-03 21:22:43 +00002239/*
2240 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2241 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002242int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2243 const mbedtls_mpi *E, const mbedtls_mpi *N,
2244 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002245{
Janos Follath24eed8d2019-11-22 13:21:35 +00002246 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002247 size_t wbits, wsize, one = 1;
2248 size_t i, j, nblimbs;
2249 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002251 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002252 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002253
Hanno Becker73d7d792018-12-11 10:35:51 +00002254 MPI_VALIDATE_RET( X != NULL );
2255 MPI_VALIDATE_RET( A != NULL );
2256 MPI_VALIDATE_RET( E != NULL );
2257 MPI_VALIDATE_RET( N != NULL );
2258
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002259 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2263 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002264
Chris Jones9246d042020-11-25 15:12:39 +00002265 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2266 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2267 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2268
Paul Bakkerf6198c12012-05-16 08:02:29 +00002269 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002270 * Init temps and window size
2271 */
2272 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2274 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002275 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 memset( W, 0, sizeof( W ) );
2277
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002278 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
2280 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2281 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2282
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002283#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2285 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002286#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002287
Paul Bakker5121ce52009-01-03 21:22:43 +00002288 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002289 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2290 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2291 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
2293 /*
Paul Bakker50546922012-05-19 08:40:49 +00002294 * Compensate for negative A (and correct at the end)
2295 */
2296 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002297 if( neg )
2298 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002300 Apos.s = 1;
2301 A = &Apos;
2302 }
2303
2304 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 * If 1st call, pre-compute R^2 mod N
2306 */
2307 if( _RR == NULL || _RR->p == NULL )
2308 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2310 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2311 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002312
2313 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 }
2316 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318
2319 /*
2320 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2321 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2323 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002324 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002326
Gilles Peskine4e91d472020-06-04 20:55:15 +02002327 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002328
2329 /*
2330 * X = R^2 * R^-1 mod N = R mod N
2331 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002333 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
2335 if( wsize > 1 )
2336 {
2337 /*
2338 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2339 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002340 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2343 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
2345 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002346 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002347
Paul Bakker5121ce52009-01-03 21:22:43 +00002348 /*
2349 * W[i] = W[i - 1] * W[1]
2350 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002351 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002352 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2354 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
Gilles Peskine4e91d472020-06-04 20:55:15 +02002356 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 }
2358 }
2359
2360 nblimbs = E->n;
2361 bufsize = 0;
2362 nbits = 0;
2363 wbits = 0;
2364 state = 0;
2365
2366 while( 1 )
2367 {
2368 if( bufsize == 0 )
2369 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002370 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 break;
2372
Paul Bakker0d7702c2013-10-29 16:18:35 +01002373 nblimbs--;
2374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002376 }
2377
2378 bufsize--;
2379
2380 ei = (E->p[nblimbs] >> bufsize) & 1;
2381
2382 /*
2383 * skip leading 0s
2384 */
2385 if( ei == 0 && state == 0 )
2386 continue;
2387
2388 if( ei == 0 && state == 1 )
2389 {
2390 /*
2391 * out of window, square X
2392 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002393 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 continue;
2395 }
2396
2397 /*
2398 * add ei to current window
2399 */
2400 state = 2;
2401
2402 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002403 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
2405 if( nbits == wsize )
2406 {
2407 /*
2408 * X = X^wsize R^-1 mod N
2409 */
2410 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002411 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
2413 /*
2414 * X = X * W[wbits] R^-1 mod N
2415 */
Manuel Pégourié-Gonnarde22176e2021-06-10 09:34:00 +02002416 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002417 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002418
2419 state--;
2420 nbits = 0;
2421 wbits = 0;
2422 }
2423 }
2424
2425 /*
2426 * process the remaining bits
2427 */
2428 for( i = 0; i < nbits; i++ )
2429 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002430 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
2432 wbits <<= 1;
2433
Paul Bakker66d5d072014-06-17 16:39:18 +02002434 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002435 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002436 }
2437
2438 /*
2439 * X = A^E * R * R^-1 mod N = A^E mod N
2440 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002441 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002442
Hanno Beckera4af1c42017-04-18 09:07:45 +01002443 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002444 {
2445 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002447 }
2448
Paul Bakker5121ce52009-01-03 21:22:43 +00002449cleanup:
2450
Paul Bakker66d5d072014-06-17 16:39:18 +02002451 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002454 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002455 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002456
Paul Bakker75a28602014-03-31 12:08:17 +02002457 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002459
2460 return( ret );
2461}
2462
Paul Bakker5121ce52009-01-03 21:22:43 +00002463/*
2464 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2465 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002467{
Janos Follath24eed8d2019-11-22 13:21:35 +00002468 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002469 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002470 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002471
Hanno Becker73d7d792018-12-11 10:35:51 +00002472 MPI_VALIDATE_RET( G != NULL );
2473 MPI_VALIDATE_RET( A != NULL );
2474 MPI_VALIDATE_RET( B != NULL );
2475
Alexander Ke8ad49f2019-08-16 16:16:07 +03002476 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2479 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481 lz = mbedtls_mpi_lsb( &TA );
2482 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002483
Paul Bakker66d5d072014-06-17 16:39:18 +02002484 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002485 lz = lzt;
2486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2488 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002489
Paul Bakker5121ce52009-01-03 21:22:43 +00002490 TA.s = TB.s = 1;
2491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002493 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2495 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002498 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2500 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002501 }
2502 else
2503 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2505 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002506 }
2507 }
2508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002509 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2510 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002511
2512cleanup:
2513
Alexander Ke8ad49f2019-08-16 16:16:07 +03002514 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002515
2516 return( ret );
2517}
2518
Paul Bakker33dc46b2014-04-30 16:11:39 +02002519/*
2520 * Fill X with size bytes of random.
2521 *
2522 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002523 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002524 * deterministic, eg for tests).
2525 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002527 int (*f_rng)(void *, unsigned char *, size_t),
2528 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002529{
Janos Follath24eed8d2019-11-22 13:21:35 +00002530 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002531 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002532 size_t const overhead = ( limbs * ciL ) - size;
2533 unsigned char *Xp;
2534
Hanno Becker8ce11a32018-12-19 16:18:52 +00002535 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002536 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002537
Hanno Beckerda1655a2017-10-18 14:21:44 +01002538 /* Ensure that target MPI has exactly the necessary number of limbs */
2539 if( X->n != limbs )
2540 {
2541 mbedtls_mpi_free( X );
2542 mbedtls_mpi_init( X );
2543 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2544 }
2545 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002546
Hanno Beckerda1655a2017-10-18 14:21:44 +01002547 Xp = (unsigned char*) X->p;
Gilles Peskine436400e2020-11-25 16:15:14 +01002548 MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002549
Hanno Becker2be8a552018-10-25 12:40:09 +01002550 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002551
2552cleanup:
2553 return( ret );
2554}
2555
Paul Bakker5121ce52009-01-03 21:22:43 +00002556/*
2557 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2558 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002560{
Janos Follath24eed8d2019-11-22 13:21:35 +00002561 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002563 MPI_VALIDATE_RET( X != NULL );
2564 MPI_VALIDATE_RET( A != NULL );
2565 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002566
Hanno Becker4bcb4912017-04-18 15:49:39 +01002567 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002568 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002570 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2571 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2572 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002577 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002579 goto cleanup;
2580 }
2581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2583 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2584 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2585 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2588 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2589 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2590 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
2592 do
2593 {
2594 while( ( TU.p[0] & 1 ) == 0 )
2595 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002596 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002597
2598 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2599 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2601 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002602 }
2603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2605 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002606 }
2607
2608 while( ( TV.p[0] & 1 ) == 0 )
2609 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002611
2612 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2613 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002614 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2615 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002616 }
2617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2619 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002620 }
2621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002623 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2625 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2626 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002627 }
2628 else
2629 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2631 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2632 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 }
2634 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002636
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002637 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2638 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002640 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2641 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002644
2645cleanup:
2646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2648 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2649 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002650
2651 return( ret );
2652}
2653
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002655
Paul Bakker5121ce52009-01-03 21:22:43 +00002656static const int small_prime[] =
2657{
2658 3, 5, 7, 11, 13, 17, 19, 23,
2659 29, 31, 37, 41, 43, 47, 53, 59,
2660 61, 67, 71, 73, 79, 83, 89, 97,
2661 101, 103, 107, 109, 113, 127, 131, 137,
2662 139, 149, 151, 157, 163, 167, 173, 179,
2663 181, 191, 193, 197, 199, 211, 223, 227,
2664 229, 233, 239, 241, 251, 257, 263, 269,
2665 271, 277, 281, 283, 293, 307, 311, 313,
2666 317, 331, 337, 347, 349, 353, 359, 367,
2667 373, 379, 383, 389, 397, 401, 409, 419,
2668 421, 431, 433, 439, 443, 449, 457, 461,
2669 463, 467, 479, 487, 491, 499, 503, 509,
2670 521, 523, 541, 547, 557, 563, 569, 571,
2671 577, 587, 593, 599, 601, 607, 613, 617,
2672 619, 631, 641, 643, 647, 653, 659, 661,
2673 673, 677, 683, 691, 701, 709, 719, 727,
2674 733, 739, 743, 751, 757, 761, 769, 773,
2675 787, 797, 809, 811, 821, 823, 827, 829,
2676 839, 853, 857, 859, 863, 877, 881, 883,
2677 887, 907, 911, 919, 929, 937, 941, 947,
2678 953, 967, 971, 977, 983, 991, 997, -103
2679};
2680
2681/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002682 * Small divisors test (X must be positive)
2683 *
2684 * Return values:
2685 * 0: no small factor (possible prime, more tests needed)
2686 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002688 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002691{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002692 int ret = 0;
2693 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002695
Paul Bakker5121ce52009-01-03 21:22:43 +00002696 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002698
2699 for( i = 0; small_prime[i] > 0; i++ )
2700 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002702 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002705
2706 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002707 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002708 }
2709
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002710cleanup:
2711 return( ret );
2712}
2713
2714/*
2715 * Miller-Rabin pseudo-primality test (HAC 4.24)
2716 */
Janos Follathda31fa12018-09-03 14:45:23 +01002717static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002718 int (*f_rng)(void *, unsigned char *, size_t),
2719 void *p_rng )
2720{
Pascal Junodb99183d2015-03-11 16:49:45 +01002721 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002722 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002723 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002724
Hanno Becker8ce11a32018-12-19 16:18:52 +00002725 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002726 MPI_VALIDATE_RET( f_rng != NULL );
2727
2728 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2729 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002731
Paul Bakker5121ce52009-01-03 21:22:43 +00002732 /*
2733 * W = |X| - 1
2734 * R = W >> lsb( W )
2735 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002736 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2737 s = mbedtls_mpi_lsb( &W );
2738 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2739 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002740
Janos Follathda31fa12018-09-03 14:45:23 +01002741 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002742 {
2743 /*
2744 * pick a random A, 1 < A < |X| - 1
2745 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002746 count = 0;
2747 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002748 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002749
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002750 j = mbedtls_mpi_bitlen( &A );
2751 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002752 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002753 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002754 }
2755
2756 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002757 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2758 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002759 }
2760
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002761 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2762 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002763
2764 /*
2765 * A = A^R mod |X|
2766 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002767 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002769 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2770 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002771 continue;
2772
2773 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002775 {
2776 /*
2777 * A = A * A mod |X|
2778 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002779 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2780 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002781
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002782 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002783 break;
2784
2785 j++;
2786 }
2787
2788 /*
2789 * not prime if A != |X| - 1 or A == 1
2790 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002791 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2792 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002793 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002794 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002795 break;
2796 }
2797 }
2798
2799cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002800 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2801 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002802 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002803
2804 return( ret );
2805}
2806
2807/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002808 * Pseudo-primality test: small factors, then Miller-Rabin
2809 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002810int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2811 int (*f_rng)(void *, unsigned char *, size_t),
2812 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002813{
Janos Follath24eed8d2019-11-22 13:21:35 +00002814 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002815 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002816 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002817 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002818
2819 XX.s = 1;
2820 XX.n = X->n;
2821 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002823 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2824 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2825 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002827 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002828 return( 0 );
2829
2830 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2831 {
2832 if( ret == 1 )
2833 return( 0 );
2834
2835 return( ret );
2836 }
2837
Janos Follathda31fa12018-09-03 14:45:23 +01002838 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002839}
2840
Janos Follatha0b67c22018-09-18 14:48:23 +01002841#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002842/*
2843 * Pseudo-primality test, error probability 2^-80
2844 */
2845int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2846 int (*f_rng)(void *, unsigned char *, size_t),
2847 void *p_rng )
2848{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002849 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002850 MPI_VALIDATE_RET( f_rng != NULL );
2851
Janos Follatha0b67c22018-09-18 14:48:23 +01002852 /*
2853 * In the past our key generation aimed for an error rate of at most
2854 * 2^-80. Since this function is deprecated, aim for the same certainty
2855 * here as well.
2856 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002857 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002858}
Janos Follatha0b67c22018-09-18 14:48:23 +01002859#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002860
2861/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002862 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002863 *
Janos Follathf301d232018-08-14 13:34:01 +01002864 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2865 * be either 1024 bits or 1536 bits long, and flags must contain
2866 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002867 */
Janos Follath7c025a92018-08-14 11:08:41 +01002868int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002869 int (*f_rng)(void *, unsigned char *, size_t),
2870 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002871{
Jethro Beekman66689272018-02-14 19:24:10 -08002872#ifdef MBEDTLS_HAVE_INT64
2873// ceil(2^63.5)
2874#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2875#else
2876// ceil(2^31.5)
2877#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2878#endif
2879 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002880 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002881 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002882 mbedtls_mpi_uint r;
2883 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002884
Hanno Becker8ce11a32018-12-19 16:18:52 +00002885 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002886 MPI_VALIDATE_RET( f_rng != NULL );
2887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002888 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2889 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002891 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002892
2893 n = BITS_TO_LIMBS( nbits );
2894
Janos Follathda31fa12018-09-03 14:45:23 +01002895 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2896 {
2897 /*
2898 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2899 */
2900 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2901 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2902 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2903 }
2904 else
2905 {
2906 /*
2907 * 2^-100 error probability, number of rounds computed based on HAC,
2908 * fact 4.48
2909 */
2910 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2911 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2912 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2913 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2914 }
2915
Jethro Beekman66689272018-02-14 19:24:10 -08002916 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002917 {
Jethro Beekman66689272018-02-14 19:24:10 -08002918 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2919 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2920 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2921
2922 k = n * biL;
2923 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2924 X->p[0] |= 1;
2925
Janos Follath7c025a92018-08-14 11:08:41 +01002926 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002927 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002928 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002929
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002930 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002931 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002932 }
Jethro Beekman66689272018-02-14 19:24:10 -08002933 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002934 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002935 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002936 * An necessary condition for Y and X = 2Y + 1 to be prime
2937 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2938 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002939 */
Jethro Beekman66689272018-02-14 19:24:10 -08002940
2941 X->p[0] |= 2;
2942
2943 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2944 if( r == 0 )
2945 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2946 else if( r == 1 )
2947 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2948
2949 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2950 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2951 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2952
2953 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002954 {
Jethro Beekman66689272018-02-14 19:24:10 -08002955 /*
2956 * First, check small factors for X and Y
2957 * before doing Miller-Rabin on any of them
2958 */
2959 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2960 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002961 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002962 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002963 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002964 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002965 goto cleanup;
2966
2967 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2968 goto cleanup;
2969
2970 /*
2971 * Next candidates. We want to preserve Y = (X-1) / 2 and
2972 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2973 * so up Y by 6 and X by 12.
2974 */
2975 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2976 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002977 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002978 }
2979 }
2980
2981cleanup:
2982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002983 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002984
2985 return( ret );
2986}
2987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002988#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002990#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002991
Paul Bakker23986e52011-04-24 08:57:21 +00002992#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002993
2994static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2995{
2996 { 693, 609, 21 },
2997 { 1764, 868, 28 },
2998 { 768454923, 542167814, 1 }
2999};
3000
Paul Bakker5121ce52009-01-03 21:22:43 +00003001/*
3002 * Checkup routine
3003 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003004int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00003005{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003006 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003007 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003008
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003009 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
3010 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
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( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003013 "EFE021C2645FD1DC586E69184AF4A31E" \
3014 "D5F53E93B5F123FA41680867BA110131" \
3015 "944FE7952E2517337780CB0DB80E61AA" \
3016 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003018 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003019 "B2E7EFD37075B9F03FF989C7C5051C20" \
3020 "34D2A323810251127E7BF8625A4F49A5" \
3021 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3022 "5B5C25763222FEFCCFC38B832366C29E" ) );
3023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003024 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003025 "0066A198186C18C10B2F5ED9B522752A" \
3026 "9830B69916E535C8F047518A889A43A5" \
3027 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003029 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003030
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003031 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003032 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3033 "9E857EA95A03512E2BAE7391688D264A" \
3034 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3035 "8001B72E848A38CAE1C65F78E56ABDEF" \
3036 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3037 "ECF677152EF804370C1A305CAF3B5BF1" \
3038 "30879B56C61DE584A0F53A2447A51E" ) );
3039
3040 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003041 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003042
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003043 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003044 {
3045 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003046 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003047
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003048 ret = 1;
3049 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003050 }
3051
3052 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003053 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003055 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003057 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003058 "256567336059E52CAE22925474705F39A94" ) );
3059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003060 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003061 "6613F26162223DF488E9CD48CC132C7A" \
3062 "0AC93C701B001B092E4E5B9F73BCD27B" \
3063 "9EE50D0657C77F374E903CDFA4C642" ) );
3064
3065 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003066 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003068 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3069 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003070 {
3071 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003072 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003073
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003074 ret = 1;
3075 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003076 }
3077
3078 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003079 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003081 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003083 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003084 "36E139AEA55215609D2816998ED020BB" \
3085 "BD96C37890F65171D948E9BC7CBAA4D9" \
3086 "325D24D6A3C12710F10A09FA08AB87" ) );
3087
3088 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003089 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003091 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003092 {
3093 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003094 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003095
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003096 ret = 1;
3097 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003098 }
3099
3100 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003101 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003102
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003103 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003105 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003106 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3107 "C3DBA76456363A10869622EAC2DD84EC" \
3108 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3109
3110 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003111 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003113 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003114 {
3115 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003116 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003117
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003118 ret = 1;
3119 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003120 }
3121
3122 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003123 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003124
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003125 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003126 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003127
Paul Bakker66d5d072014-06-17 16:39:18 +02003128 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003129 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003130 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3131 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003133 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003135 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003136 {
3137 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003138 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003139
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003140 ret = 1;
3141 goto cleanup;
3142 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003143 }
3144
3145 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003146 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003147
Paul Bakker5121ce52009-01-03 21:22:43 +00003148cleanup:
3149
3150 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003151 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003153 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3154 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003155
3156 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003157 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003158
3159 return( ret );
3160}
3161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003162#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003164#endif /* MBEDTLS_BIGNUM_C */