blob: d934cb2c9e46a739d8b9f68b1c17e128ac5a31b0 [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
240/*
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200241 * Conditionally assign dest = src, without leaking information
242 * about whether the assignment was made or not.
243 * dest and src must be arrays of limbs of size n.
244 * assign must be 0 or 1.
245 */
246static void mpi_safe_cond_assign( size_t n,
247 mbedtls_mpi_uint *dest,
248 const mbedtls_mpi_uint *src,
249 unsigned char assign )
250{
251 size_t i;
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200252
253 /* MSVC has a warning about unary minus on unsigned integer types,
254 * but this is well-defined and precisely what we want to do here. */
255#if defined(_MSC_VER)
256#pragma warning( push )
257#pragma warning( disable : 4146 )
258#endif
259
260 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
261 const mbedtls_mpi_uint mask = -assign;
262
263#if defined(_MSC_VER)
264#pragma warning( pop )
265#endif
266
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200267 for( i = 0; i < n; i++ )
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200268 dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200269}
270
271/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100272 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100273 * about whether the assignment was made or not.
274 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100275 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100277{
278 int ret = 0;
279 size_t i;
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200280 unsigned int mask;
281 mbedtls_mpi_uint limb_mask;
Hanno Becker73d7d792018-12-11 10:35:51 +0000282 MPI_VALIDATE_RET( X != NULL );
283 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100284
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200285 /* MSVC has a warning about unary minus on unsigned integer types,
286 * but this is well-defined and precisely what we want to do here. */
287#if defined(_MSC_VER)
288#pragma warning( push )
289#pragma warning( disable : 4146 )
290#endif
291
Pascal Junodb99183d2015-03-11 16:49:45 +0100292 /* make sure assign is 0 or 1 in a time-constant manner */
293 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200294 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
295 mask = -assign;
296 limb_mask = -assign;
297
298#if defined(_MSC_VER)
299#pragma warning( pop )
300#endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100303
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200304 X->s = ( X->s & ~mask ) | ( Y->s & mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100305
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200306 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100307
Gilles Peskinef04d11e2020-06-04 19:14:58 +0200308 for( i = Y->n; i < X->n; i++ )
Manuel Pégourié-Gonnard5ada7a82021-05-31 11:48:45 +0200309 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100310
311cleanup:
312 return( ret );
313}
314
315/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100316 * Conditionally swap X and Y, without leaking information
317 * about whether the swap was made or not.
318 * Here it is not ok to simply swap the pointers, which whould lead to
319 * different memory access patterns when X and Y are used afterwards.
320 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100322{
323 int ret, s;
324 size_t i;
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200325 unsigned int sign_mask;
326 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000328 MPI_VALIDATE_RET( X != NULL );
329 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100330
331 if( X == Y )
332 return( 0 );
333
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200334 /* MSVC has a warning about unary minus on unsigned integer types,
335 * but this is well-defined and precisely what we want to do here. */
336#if defined(_MSC_VER)
337#pragma warning( push )
338#pragma warning( disable : 4146 )
339#endif
340
Pascal Junodb99183d2015-03-11 16:49:45 +0100341 /* make sure swap is 0 or 1 in a time-constant manner */
342 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200343 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
344 sign_mask = -swap;
345 limb_mask = -swap;
346
347#if defined(_MSC_VER)
348#pragma warning( pop )
349#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
352 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100353
354 s = X->s;
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200355 X->s = ( X->s & ~sign_mask ) | ( Y->s & sign_mask );
356 Y->s = ( Y->s & ~sign_mask ) | ( s & sign_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100357
358
359 for( i = 0; i < X->n; i++ )
360 {
361 tmp = X->p[i];
Manuel Pégourié-Gonnard448f1352021-06-03 10:54:01 +0200362 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
363 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100364 }
365
366cleanup:
367 return( ret );
368}
369
370/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000371 * Set value from integer
372 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000374{
Janos Follath24eed8d2019-11-22 13:21:35 +0000375 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000376 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 memset( X->p, 0, X->n * ciL );
380
381 X->p[0] = ( z < 0 ) ? -z : z;
382 X->s = ( z < 0 ) ? -1 : 1;
383
384cleanup:
385
386 return( ret );
387}
388
389/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000390 * Get a specific bit
391 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000393{
Hanno Becker73d7d792018-12-11 10:35:51 +0000394 MPI_VALIDATE_RET( X != NULL );
395
Paul Bakker2f5947e2011-05-18 15:47:11 +0000396 if( X->n * biL <= pos )
397 return( 0 );
398
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200399 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000400}
401
Gilles Peskine11cdb052018-11-20 16:47:47 +0100402/* Get a specific byte, without range checks. */
403#define GET_BYTE( X, i ) \
404 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
405
Paul Bakker2f5947e2011-05-18 15:47:11 +0000406/*
407 * Set a bit to a specific value of 0 or 1
408 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000410{
411 int ret = 0;
412 size_t off = pos / biL;
413 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000414 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000415
416 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200418
Paul Bakker2f5947e2011-05-18 15:47:11 +0000419 if( X->n * biL <= pos )
420 {
421 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200422 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000425 }
426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
428 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000429
430cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200431
Paul Bakker2f5947e2011-05-18 15:47:11 +0000432 return( ret );
433}
434
435/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200436 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000437 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000439{
Paul Bakker23986e52011-04-24 08:57:21 +0000440 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000441 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
443 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000444 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
446 return( count );
447
448 return( 0 );
449}
450
451/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000452 * Count leading zero bits in a given integer
453 */
454static size_t mbedtls_clz( const mbedtls_mpi_uint x )
455{
456 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100457 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000458
459 for( j = 0; j < biL; j++ )
460 {
461 if( x & mask ) break;
462
463 mask >>= 1;
464 }
465
466 return j;
467}
468
469/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200470 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000471 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200472size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000473{
Paul Bakker23986e52011-04-24 08:57:21 +0000474 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200476 if( X->n == 0 )
477 return( 0 );
478
Paul Bakker5121ce52009-01-03 21:22:43 +0000479 for( i = X->n - 1; i > 0; i-- )
480 if( X->p[i] != 0 )
481 break;
482
Simon Butcher15b15d12015-11-26 19:35:03 +0000483 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
Paul Bakker23986e52011-04-24 08:57:21 +0000485 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000486}
487
488/*
489 * Return the total size in bytes
490 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000492{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200493 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494}
495
496/*
497 * Convert an ASCII character to digit value
498 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000500{
501 *d = 255;
502
503 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
504 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
505 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 if( *d >= (mbedtls_mpi_uint) radix )
508 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509
510 return( 0 );
511}
512
513/*
514 * Import from an ASCII string
515 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000517{
Janos Follath24eed8d2019-11-22 13:21:35 +0000518 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000519 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 mbedtls_mpi_uint d;
521 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000522 MPI_VALIDATE_RET( X != NULL );
523 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000524
525 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000526 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
Paul Bakkerff60ee62010-03-16 21:09:09 +0000530 slen = strlen( s );
531
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 if( radix == 16 )
533 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100534 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200535 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
536
Paul Bakkerff60ee62010-03-16 21:09:09 +0000537 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
540 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000541
Paul Bakker23986e52011-04-24 08:57:21 +0000542 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000543 {
Paul Bakker23986e52011-04-24 08:57:21 +0000544 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000545 {
546 X->s = -1;
547 break;
548 }
549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200551 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000552 }
553 }
554 else
555 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
Paul Bakkerff60ee62010-03-16 21:09:09 +0000558 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000559 {
560 if( i == 0 && s[i] == '-' )
561 {
562 X->s = -1;
563 continue;
564 }
565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
567 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000568
569 if( X->s == 1 )
570 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000572 }
573 else
574 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000576 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000577 }
578 }
579
580cleanup:
581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584 return( ret );
585}
586
587/*
Ron Eldora16fa292018-11-20 14:07:01 +0200588 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 */
Ron Eldora16fa292018-11-20 14:07:01 +0200590static int mpi_write_hlp( mbedtls_mpi *X, int radix,
591 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000592{
Janos Follath24eed8d2019-11-22 13:21:35 +0000593 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200595 size_t length = 0;
596 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000597
Ron Eldora16fa292018-11-20 14:07:01 +0200598 do
599 {
600 if( length >= buflen )
601 {
602 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
603 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000604
Ron Eldora16fa292018-11-20 14:07:01 +0200605 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
606 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
607 /*
608 * Write the residue in the current position, as an ASCII character.
609 */
610 if( r < 0xA )
611 *(--p_end) = (char)( '0' + r );
612 else
613 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
Ron Eldora16fa292018-11-20 14:07:01 +0200615 length++;
616 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
Ron Eldora16fa292018-11-20 14:07:01 +0200618 memmove( *p, p_end, length );
619 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000620
621cleanup:
622
623 return( ret );
624}
625
626/*
627 * Export into an ASCII string
628 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100629int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
630 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000631{
Paul Bakker23986e52011-04-24 08:57:21 +0000632 int ret = 0;
633 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000634 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000636 MPI_VALIDATE_RET( X != NULL );
637 MPI_VALIDATE_RET( olen != NULL );
638 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000641 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
Hanno Becker23cfea02019-02-04 09:45:07 +0000643 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
644 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
645 * `n`. If radix > 4, this might be a strict
646 * overapproximation of the number of
647 * radix-adic digits needed to present `n`. */
648 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
649 * present `n`. */
650
Janos Follath80470622019-03-06 13:43:02 +0000651 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000652 n += 1; /* Compensate for the divisions above, which round down `n`
653 * in case it's not even. */
654 n += 1; /* Potential '-'-sign. */
655 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
656 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100658 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000659 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100660 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000662 }
663
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100664 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
667 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000668 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000670 buflen--;
671 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000672
673 if( radix == 16 )
674 {
Paul Bakker23986e52011-04-24 08:57:21 +0000675 int c;
676 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000677
Paul Bakker23986e52011-04-24 08:57:21 +0000678 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000679 {
Paul Bakker23986e52011-04-24 08:57:21 +0000680 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 {
Paul Bakker23986e52011-04-24 08:57:21 +0000682 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000683
Paul Bakker6c343d72014-07-10 14:36:19 +0200684 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000685 continue;
686
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000687 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000688 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 k = 1;
690 }
691 }
692 }
693 else
694 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000696
697 if( T.s == -1 )
698 T.s = 1;
699
Ron Eldora16fa292018-11-20 14:07:01 +0200700 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000701 }
702
703 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100704 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
706cleanup:
707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000709
710 return( ret );
711}
712
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000714/*
715 * Read X from an opened file
716 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000718{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000720 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000721 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000722 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000723 * Buffer should have space for (short) label and decimal formatted MPI,
724 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000725 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000727
Hanno Becker73d7d792018-12-11 10:35:51 +0000728 MPI_VALIDATE_RET( X != NULL );
729 MPI_VALIDATE_RET( fin != NULL );
730
731 if( radix < 2 || radix > 16 )
732 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
733
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 memset( s, 0, sizeof( s ) );
735 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
738 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000739 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000741
Hanno Beckerb2034b72017-04-26 11:46:46 +0100742 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
743 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000744
745 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100746 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000747 if( mpi_get_digit( &d, radix, *p ) != 0 )
748 break;
749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000751}
752
753/*
754 * Write X into an opened file (or stdout if fout == NULL)
755 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000757{
Janos Follath24eed8d2019-11-22 13:21:35 +0000758 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000759 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000760 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000761 * Buffer should have space for (short) label and decimal formatted MPI,
762 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000763 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000765 MPI_VALIDATE_RET( X != NULL );
766
767 if( radix < 2 || radix > 16 )
768 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000769
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100770 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000771
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100772 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000773
774 if( p == NULL ) p = "";
775
776 plen = strlen( p );
777 slen = strlen( s );
778 s[slen++] = '\r';
779 s[slen++] = '\n';
780
781 if( fout != NULL )
782 {
783 if( fwrite( p, 1, plen, fout ) != plen ||
784 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000786 }
787 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000789
790cleanup:
791
792 return( ret );
793}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200794#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000795
Hanno Beckerda1655a2017-10-18 14:21:44 +0100796
797/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
798 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000799
800static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
801{
802 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100803 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000804 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100805
806 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
807 {
808 tmp <<= CHAR_BIT;
809 tmp |= (mbedtls_mpi_uint) *x_ptr;
810 }
811
Hanno Beckerf8720072018-11-08 11:53:49 +0000812 return( tmp );
813}
814
815static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
816{
817#if defined(__BYTE_ORDER__)
818
819/* Nothing to do on bigendian systems. */
820#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
821 return( x );
822#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
823
824#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
825
826/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000827#if defined(__GNUC__) && defined(__GNUC_PREREQ)
828#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000829#define have_bswap
830#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000831#endif
832
833#if defined(__clang__) && defined(__has_builtin)
834#if __has_builtin(__builtin_bswap32) && \
835 __has_builtin(__builtin_bswap64)
836#define have_bswap
837#endif
838#endif
839
Hanno Beckerf8720072018-11-08 11:53:49 +0000840#if defined(have_bswap)
841 /* The compiler is hopefully able to statically evaluate this! */
842 switch( sizeof(mbedtls_mpi_uint) )
843 {
844 case 4:
845 return( __builtin_bswap32(x) );
846 case 8:
847 return( __builtin_bswap64(x) );
848 }
849#endif
850#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
851#endif /* __BYTE_ORDER__ */
852
853 /* Fall back to C-based reordering if we don't know the byte order
854 * or we couldn't use a compiler-specific builtin. */
855 return( mpi_uint_bigendian_to_host_c( x ) );
856}
857
Hanno Becker2be8a552018-10-25 12:40:09 +0100858static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100859{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100860 mbedtls_mpi_uint *cur_limb_left;
861 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100862 if( limbs == 0 )
863 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100864
865 /*
866 * Traverse limbs and
867 * - adapt byte-order in each limb
868 * - swap the limbs themselves.
869 * For that, simultaneously traverse the limbs from left to right
870 * and from right to left, as long as the left index is not bigger
871 * than the right index (it's not a problem if limbs is odd and the
872 * indices coincide in the last iteration).
873 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100874 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
875 cur_limb_left <= cur_limb_right;
876 cur_limb_left++, cur_limb_right-- )
877 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000878 mbedtls_mpi_uint tmp;
879 /* Note that if cur_limb_left == cur_limb_right,
880 * this code effectively swaps the bytes only once. */
881 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
882 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
883 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100884 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100885}
886
Paul Bakker5121ce52009-01-03 21:22:43 +0000887/*
Janos Follatha778a942019-02-13 10:28:28 +0000888 * Import X from unsigned binary data, little endian
889 */
890int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
891 const unsigned char *buf, size_t buflen )
892{
Janos Follath24eed8d2019-11-22 13:21:35 +0000893 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000894 size_t i;
895 size_t const limbs = CHARS_TO_LIMBS( buflen );
896
897 /* Ensure that target MPI has exactly the necessary number of limbs */
898 if( X->n != limbs )
899 {
900 mbedtls_mpi_free( X );
901 mbedtls_mpi_init( X );
902 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
903 }
904
905 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
906
907 for( i = 0; i < buflen; i++ )
908 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
909
910cleanup:
911
Janos Follath171a7ef2019-02-15 16:17:45 +0000912 /*
913 * This function is also used to import keys. However, wiping the buffers
914 * upon failure is not necessary because failure only can happen before any
915 * input is copied.
916 */
Janos Follatha778a942019-02-13 10:28:28 +0000917 return( ret );
918}
919
920/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000921 * Import X from unsigned binary data, big endian
922 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000924{
Janos Follath24eed8d2019-11-22 13:21:35 +0000925 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100926 size_t const limbs = CHARS_TO_LIMBS( buflen );
927 size_t const overhead = ( limbs * ciL ) - buflen;
928 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
Hanno Becker8ce11a32018-12-19 16:18:52 +0000930 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000931 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
932
Hanno Becker073c1992017-10-17 15:17:27 +0100933 /* Ensure that target MPI has exactly the necessary number of limbs */
934 if( X->n != limbs )
935 {
936 mbedtls_mpi_free( X );
937 mbedtls_mpi_init( X );
938 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
939 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000941
Hanno Becker0e810b92019-01-03 17:13:11 +0000942 /* Avoid calling `memcpy` with NULL source argument,
943 * even if buflen is 0. */
944 if( buf != NULL )
945 {
946 Xp = (unsigned char*) X->p;
947 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100948
Hanno Becker0e810b92019-01-03 17:13:11 +0000949 mpi_bigendian_to_host( X->p, limbs );
950 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000951
952cleanup:
953
Janos Follath171a7ef2019-02-15 16:17:45 +0000954 /*
955 * This function is also used to import keys. However, wiping the buffers
956 * upon failure is not necessary because failure only can happen before any
957 * input is copied.
958 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000959 return( ret );
960}
961
962/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000963 * Export X into unsigned binary data, little endian
964 */
965int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
966 unsigned char *buf, size_t buflen )
967{
968 size_t stored_bytes = X->n * ciL;
969 size_t bytes_to_copy;
970 size_t i;
971
972 if( stored_bytes < buflen )
973 {
974 bytes_to_copy = stored_bytes;
975 }
976 else
977 {
978 bytes_to_copy = buflen;
979
980 /* The output buffer is smaller than the allocated size of X.
981 * However X may fit if its leading bytes are zero. */
982 for( i = bytes_to_copy; i < stored_bytes; i++ )
983 {
984 if( GET_BYTE( X, i ) != 0 )
985 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
986 }
987 }
988
989 for( i = 0; i < bytes_to_copy; i++ )
990 buf[i] = GET_BYTE( X, i );
991
992 if( stored_bytes < buflen )
993 {
994 /* Write trailing 0 bytes */
995 memset( buf + stored_bytes, 0, buflen - stored_bytes );
996 }
997
998 return( 0 );
999}
1000
1001/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001002 * Export X into unsigned binary data, big endian
1003 */
Gilles Peskine11cdb052018-11-20 16:47:47 +01001004int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
1005 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +00001006{
Hanno Becker73d7d792018-12-11 10:35:51 +00001007 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +01001008 size_t bytes_to_copy;
1009 unsigned char *p;
1010 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001011
Hanno Becker73d7d792018-12-11 10:35:51 +00001012 MPI_VALIDATE_RET( X != NULL );
1013 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
1014
1015 stored_bytes = X->n * ciL;
1016
Gilles Peskine11cdb052018-11-20 16:47:47 +01001017 if( stored_bytes < buflen )
1018 {
1019 /* There is enough space in the output buffer. Write initial
1020 * null bytes and record the position at which to start
1021 * writing the significant bytes. In this case, the execution
1022 * trace of this function does not depend on the value of the
1023 * number. */
1024 bytes_to_copy = stored_bytes;
1025 p = buf + buflen - stored_bytes;
1026 memset( buf, 0, buflen - stored_bytes );
1027 }
1028 else
1029 {
1030 /* The output buffer is smaller than the allocated size of X.
1031 * However X may fit if its leading bytes are zero. */
1032 bytes_to_copy = buflen;
1033 p = buf;
1034 for( i = bytes_to_copy; i < stored_bytes; i++ )
1035 {
1036 if( GET_BYTE( X, i ) != 0 )
1037 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1038 }
1039 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001040
Gilles Peskine11cdb052018-11-20 16:47:47 +01001041 for( i = 0; i < bytes_to_copy; i++ )
1042 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001043
1044 return( 0 );
1045}
1046
1047/*
1048 * Left-shift: X <<= count
1049 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051{
Janos Follath24eed8d2019-11-22 13:21:35 +00001052 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001053 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001055 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001056
1057 v0 = count / (biL );
1058 t1 = count & (biL - 1);
1059
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001060 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001061
Paul Bakkerf9688572011-05-05 10:00:45 +00001062 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001064
1065 ret = 0;
1066
1067 /*
1068 * shift by count / limb_size
1069 */
1070 if( v0 > 0 )
1071 {
Paul Bakker23986e52011-04-24 08:57:21 +00001072 for( i = X->n; i > v0; i-- )
1073 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001074
Paul Bakker23986e52011-04-24 08:57:21 +00001075 for( ; i > 0; i-- )
1076 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001077 }
1078
1079 /*
1080 * shift by count % limb_size
1081 */
1082 if( t1 > 0 )
1083 {
1084 for( i = v0; i < X->n; i++ )
1085 {
1086 r1 = X->p[i] >> (biL - t1);
1087 X->p[i] <<= t1;
1088 X->p[i] |= r0;
1089 r0 = r1;
1090 }
1091 }
1092
1093cleanup:
1094
1095 return( ret );
1096}
1097
1098/*
1099 * Right-shift: X >>= count
1100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001101int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001102{
Paul Bakker23986e52011-04-24 08:57:21 +00001103 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001104 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001105 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001106
1107 v0 = count / biL;
1108 v1 = count & (biL - 1);
1109
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001110 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001112
Paul Bakker5121ce52009-01-03 21:22:43 +00001113 /*
1114 * shift by count / limb_size
1115 */
1116 if( v0 > 0 )
1117 {
1118 for( i = 0; i < X->n - v0; i++ )
1119 X->p[i] = X->p[i + v0];
1120
1121 for( ; i < X->n; i++ )
1122 X->p[i] = 0;
1123 }
1124
1125 /*
1126 * shift by count % limb_size
1127 */
1128 if( v1 > 0 )
1129 {
Paul Bakker23986e52011-04-24 08:57:21 +00001130 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001131 {
Paul Bakker23986e52011-04-24 08:57:21 +00001132 r1 = X->p[i - 1] << (biL - v1);
1133 X->p[i - 1] >>= v1;
1134 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001135 r0 = r1;
1136 }
1137 }
1138
1139 return( 0 );
1140}
1141
1142/*
1143 * Compare unsigned values
1144 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001145int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001146{
Paul Bakker23986e52011-04-24 08:57:21 +00001147 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001148 MPI_VALIDATE_RET( X != NULL );
1149 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
Paul Bakker23986e52011-04-24 08:57:21 +00001151 for( i = X->n; i > 0; i-- )
1152 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001153 break;
1154
Paul Bakker23986e52011-04-24 08:57:21 +00001155 for( j = Y->n; j > 0; j-- )
1156 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001157 break;
1158
Paul Bakker23986e52011-04-24 08:57:21 +00001159 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001160 return( 0 );
1161
1162 if( i > j ) return( 1 );
1163 if( j > i ) return( -1 );
1164
Paul Bakker23986e52011-04-24 08:57:21 +00001165 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001166 {
Paul Bakker23986e52011-04-24 08:57:21 +00001167 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1168 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001169 }
1170
1171 return( 0 );
1172}
1173
1174/*
1175 * Compare signed values
1176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001178{
Paul Bakker23986e52011-04-24 08:57:21 +00001179 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001180 MPI_VALIDATE_RET( X != NULL );
1181 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
Paul Bakker23986e52011-04-24 08:57:21 +00001183 for( i = X->n; i > 0; i-- )
1184 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 break;
1186
Paul Bakker23986e52011-04-24 08:57:21 +00001187 for( j = Y->n; j > 0; j-- )
1188 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 break;
1190
Paul Bakker23986e52011-04-24 08:57:21 +00001191 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 return( 0 );
1193
1194 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001195 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
1197 if( X->s > 0 && Y->s < 0 ) return( 1 );
1198 if( Y->s > 0 && X->s < 0 ) return( -1 );
1199
Paul Bakker23986e52011-04-24 08:57:21 +00001200 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 {
Paul Bakker23986e52011-04-24 08:57:21 +00001202 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1203 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204 }
1205
1206 return( 0 );
1207}
1208
Janos Follath3f6f0e42019-10-14 09:09:32 +01001209/** Decide if an integer is less than the other, without branches.
1210 *
1211 * \param x First integer.
1212 * \param y Second integer.
1213 *
1214 * \return 1 if \p x is less than \p y, 0 otherwise
1215 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001216static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1217 const mbedtls_mpi_uint y )
Janos Follathee6abce2019-09-05 14:47:19 +01001218{
1219 mbedtls_mpi_uint ret;
1220 mbedtls_mpi_uint cond;
1221
1222 /*
1223 * Check if the most significant bits (MSB) of the operands are different.
1224 */
1225 cond = ( x ^ y );
1226 /*
1227 * If the MSB are the same then the difference x-y will be negative (and
1228 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1229 */
1230 ret = ( x - y ) & ~cond;
1231 /*
1232 * If the MSB are different, then the operand with the MSB of 1 is the
1233 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1234 * the MSB of y is 0.)
1235 */
1236 ret |= y & cond;
1237
1238
Janos Follatha0f732b2019-10-14 08:59:14 +01001239 ret = ret >> ( biL - 1 );
Janos Follathee6abce2019-09-05 14:47:19 +01001240
Janos Follath67ce6472019-10-29 15:08:46 +00001241 return (unsigned) ret;
Janos Follathee6abce2019-09-05 14:47:19 +01001242}
1243
1244/*
1245 * Compare signed values in constant time
1246 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001247int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1248 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001249{
1250 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001251 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001252 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001253
1254 MPI_VALIDATE_RET( X != NULL );
1255 MPI_VALIDATE_RET( Y != NULL );
1256 MPI_VALIDATE_RET( ret != NULL );
1257
1258 if( X->n != Y->n )
1259 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1260
1261 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001262 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1263 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001264 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001265 X_is_negative = ( X->s & 2 ) >> 1;
1266 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001267
1268 /*
1269 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001270 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1271 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001272 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001273 cond = ( X_is_negative ^ Y_is_negative );
1274 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001275
1276 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001277 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001278 * need to go through the loop. Record if we have the result already.
1279 */
Janos Follathee6abce2019-09-05 14:47:19 +01001280 done = cond;
1281
1282 for( i = X->n; i > 0; i-- )
1283 {
1284 /*
Janos Follath30702422019-11-05 12:24:52 +00001285 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1286 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001287 *
1288 * Again even if we can make a decision, we just mark the result and
1289 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001290 */
Janos Follath30702422019-11-05 12:24:52 +00001291 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1292 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001293 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001294
1295 /*
Janos Follath30702422019-11-05 12:24:52 +00001296 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1297 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001298 *
1299 * Again even if we can make a decision, we just mark the result and
1300 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001301 */
Janos Follath30702422019-11-05 12:24:52 +00001302 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1303 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001304 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001305 }
1306
1307 return( 0 );
1308}
1309
Paul Bakker5121ce52009-01-03 21:22:43 +00001310/*
1311 * Compare signed values
1312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001314{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 mbedtls_mpi Y;
1316 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001317 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001318
1319 *p = ( z < 0 ) ? -z : z;
1320 Y.s = ( z < 0 ) ? -1 : 1;
1321 Y.n = 1;
1322 Y.p = p;
1323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001325}
1326
1327/*
1328 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1329 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001331{
Janos Follath24eed8d2019-11-22 13:21:35 +00001332 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001333 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001334 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001335 MPI_VALIDATE_RET( X != NULL );
1336 MPI_VALIDATE_RET( A != NULL );
1337 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338
1339 if( X == B )
1340 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 }
1343
1344 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001346
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001347 /*
1348 * X should always be positive as a result of unsigned additions.
1349 */
1350 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001351
Paul Bakker23986e52011-04-24 08:57:21 +00001352 for( j = B->n; j > 0; j-- )
1353 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001354 break;
1355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001357
1358 o = B->p; p = X->p; c = 0;
1359
Janos Follath6c922682015-10-30 17:43:11 +01001360 /*
1361 * tmp is used because it might happen that p == o
1362 */
Paul Bakker23986e52011-04-24 08:57:21 +00001363 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001364 {
Janos Follath6c922682015-10-30 17:43:11 +01001365 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001366 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001367 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001368 }
1369
1370 while( c != 0 )
1371 {
1372 if( i >= X->n )
1373 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001375 p = X->p + i;
1376 }
1377
Paul Bakker2d319fd2012-09-16 21:34:26 +00001378 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 }
1380
1381cleanup:
1382
1383 return( ret );
1384}
1385
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001386/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001387 * Helper for mbedtls_mpi subtraction.
1388 *
1389 * Calculate d - s where d and s have the same size.
1390 * This function operates modulo (2^ciL)^n and returns the carry
1391 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1392 *
1393 * \param n Number of limbs of \p d and \p s.
1394 * \param[in,out] d On input, the left operand.
1395 * On output, the result of the subtraction:
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001396 * \param[in] s The right operand.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001397 *
1398 * \return 1 if `d < s`.
1399 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001400 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001401static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1402 mbedtls_mpi_uint *d,
1403 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001404{
Paul Bakker23986e52011-04-24 08:57:21 +00001405 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001407
1408 for( i = c = 0; i < n; i++, s++, d++ )
1409 {
1410 z = ( *d < c ); *d -= c;
1411 c = ( *d < *s ) + z; *d -= *s;
1412 }
1413
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001414 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415}
1416
1417/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001418 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001419 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001421{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 mbedtls_mpi TB;
Janos Follath24eed8d2019-11-22 13:21:35 +00001423 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001424 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001425 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001426 MPI_VALIDATE_RET( X != NULL );
1427 MPI_VALIDATE_RET( A != NULL );
1428 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001431
1432 if( X == B )
1433 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001435 B = &TB;
1436 }
1437
1438 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001440
Paul Bakker1ef7a532009-06-20 10:50:55 +00001441 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001442 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001443 */
1444 X->s = 1;
1445
Paul Bakker5121ce52009-01-03 21:22:43 +00001446 ret = 0;
1447
Paul Bakker23986e52011-04-24 08:57:21 +00001448 for( n = B->n; n > 0; n-- )
1449 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001450 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001451 if( n > A->n )
1452 {
1453 /* B >= (2^ciL)^n > A */
1454 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1455 goto cleanup;
1456 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001457
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001458 carry = mpi_sub_hlp( n, X->p, B->p );
1459 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001460 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001461 /* Propagate the carry to the first nonzero limb of X. */
1462 for( ; n < X->n && X->p[n] == 0; n++ )
1463 --X->p[n];
1464 /* If we ran out of space for the carry, it means that the result
1465 * is negative. */
1466 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001467 {
1468 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1469 goto cleanup;
1470 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001471 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001472 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001473
1474cleanup:
1475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
1478 return( ret );
1479}
1480
1481/*
1482 * Signed addition: X = A + B
1483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001485{
Hanno Becker73d7d792018-12-11 10:35:51 +00001486 int ret, s;
1487 MPI_VALIDATE_RET( X != NULL );
1488 MPI_VALIDATE_RET( A != NULL );
1489 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
Hanno Becker73d7d792018-12-11 10:35:51 +00001491 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001492 if( A->s * B->s < 0 )
1493 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001495 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 X->s = s;
1498 }
1499 else
1500 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 X->s = -s;
1503 }
1504 }
1505 else
1506 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 X->s = s;
1509 }
1510
1511cleanup:
1512
1513 return( ret );
1514}
1515
1516/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001517 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001520{
Hanno Becker73d7d792018-12-11 10:35:51 +00001521 int ret, s;
1522 MPI_VALIDATE_RET( X != NULL );
1523 MPI_VALIDATE_RET( A != NULL );
1524 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001525
Hanno Becker73d7d792018-12-11 10:35:51 +00001526 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001527 if( A->s * B->s > 0 )
1528 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001529 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001530 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532 X->s = s;
1533 }
1534 else
1535 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001537 X->s = -s;
1538 }
1539 }
1540 else
1541 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001543 X->s = s;
1544 }
1545
1546cleanup:
1547
1548 return( ret );
1549}
1550
1551/*
1552 * Signed addition: X = A + b
1553 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001555{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 mbedtls_mpi _B;
1557 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001558 MPI_VALIDATE_RET( X != NULL );
1559 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001560
1561 p[0] = ( b < 0 ) ? -b : b;
1562 _B.s = ( b < 0 ) ? -1 : 1;
1563 _B.n = 1;
1564 _B.p = p;
1565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001567}
1568
1569/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001570 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001571 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001573{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 mbedtls_mpi _B;
1575 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001576 MPI_VALIDATE_RET( X != NULL );
1577 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001578
1579 p[0] = ( b < 0 ) ? -b : b;
1580 _B.s = ( b < 0 ) ? -1 : 1;
1581 _B.n = 1;
1582 _B.p = p;
1583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585}
1586
1587/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001589 */
1590static
1591#if defined(__APPLE__) && defined(__arm__)
1592/*
1593 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1594 * appears to need this to prevent bad ARM code generation at -O3.
1595 */
1596__attribute__ ((noinline))
1597#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598void 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 +00001599{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001600 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001601
1602#if defined(MULADDC_HUIT)
1603 for( ; i >= 8; i -= 8 )
1604 {
1605 MULADDC_INIT
1606 MULADDC_HUIT
1607 MULADDC_STOP
1608 }
1609
1610 for( ; i > 0; i-- )
1611 {
1612 MULADDC_INIT
1613 MULADDC_CORE
1614 MULADDC_STOP
1615 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001616#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001617 for( ; i >= 16; i -= 16 )
1618 {
1619 MULADDC_INIT
1620 MULADDC_CORE MULADDC_CORE
1621 MULADDC_CORE MULADDC_CORE
1622 MULADDC_CORE MULADDC_CORE
1623 MULADDC_CORE MULADDC_CORE
1624
1625 MULADDC_CORE MULADDC_CORE
1626 MULADDC_CORE MULADDC_CORE
1627 MULADDC_CORE MULADDC_CORE
1628 MULADDC_CORE MULADDC_CORE
1629 MULADDC_STOP
1630 }
1631
1632 for( ; i >= 8; i -= 8 )
1633 {
1634 MULADDC_INIT
1635 MULADDC_CORE MULADDC_CORE
1636 MULADDC_CORE MULADDC_CORE
1637
1638 MULADDC_CORE MULADDC_CORE
1639 MULADDC_CORE MULADDC_CORE
1640 MULADDC_STOP
1641 }
1642
1643 for( ; i > 0; i-- )
1644 {
1645 MULADDC_INIT
1646 MULADDC_CORE
1647 MULADDC_STOP
1648 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001649#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
1651 t++;
1652
1653 do {
1654 *d += c; c = ( *d < c ); d++;
1655 }
1656 while( c != 0 );
1657}
1658
1659/*
1660 * Baseline multiplication: X = A * B (HAC 14.12)
1661 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001663{
Janos Follath24eed8d2019-11-22 13:21:35 +00001664 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001665 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001667 MPI_VALIDATE_RET( X != NULL );
1668 MPI_VALIDATE_RET( A != NULL );
1669 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1674 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
Paul Bakker23986e52011-04-24 08:57:21 +00001676 for( i = A->n; i > 0; i-- )
1677 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001678 break;
1679
Paul Bakker23986e52011-04-24 08:57:21 +00001680 for( j = B->n; j > 0; j-- )
1681 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001682 break;
1683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1685 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001687 for( ; j > 0; j-- )
1688 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
1690 X->s = A->s * B->s;
1691
1692cleanup:
1693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001695
1696 return( ret );
1697}
1698
1699/*
1700 * Baseline multiplication: X = A * b
1701 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001703{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 mbedtls_mpi _B;
1705 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001706 MPI_VALIDATE_RET( X != NULL );
1707 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001708
1709 _B.s = 1;
1710 _B.n = 1;
1711 _B.p = p;
1712 p[0] = b;
1713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001715}
1716
1717/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001718 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1719 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001720 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001721static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1722 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001723{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001724#if defined(MBEDTLS_HAVE_UDBL)
1725 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001726#else
Simon Butcher9803d072016-01-03 00:24:34 +00001727 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1728 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001729 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1730 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001731 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001732#endif
1733
Simon Butcher15b15d12015-11-26 19:35:03 +00001734 /*
1735 * Check for overflow
1736 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001737 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001738 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001739 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001740
Simon Butcherf5ba0452015-12-27 23:01:55 +00001741 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001742 }
1743
1744#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001745 dividend = (mbedtls_t_udbl) u1 << biL;
1746 dividend |= (mbedtls_t_udbl) u0;
1747 quotient = dividend / d;
1748 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1749 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1750
1751 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001752 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001753
1754 return (mbedtls_mpi_uint) quotient;
1755#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001756
1757 /*
1758 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1759 * Vol. 2 - Seminumerical Algorithms, Knuth
1760 */
1761
1762 /*
1763 * Normalize the divisor, d, and dividend, u0, u1
1764 */
1765 s = mbedtls_clz( d );
1766 d = d << s;
1767
1768 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001769 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001770 u0 = u0 << s;
1771
1772 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001773 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001774
1775 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001776 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001777
1778 /*
1779 * Find the first quotient and remainder
1780 */
1781 q1 = u1 / d1;
1782 r0 = u1 - d1 * q1;
1783
1784 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1785 {
1786 q1 -= 1;
1787 r0 += d1;
1788
1789 if ( r0 >= radix ) break;
1790 }
1791
Simon Butcherf5ba0452015-12-27 23:01:55 +00001792 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001793 q0 = rAX / d1;
1794 r0 = rAX - q0 * d1;
1795
1796 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1797 {
1798 q0 -= 1;
1799 r0 += d1;
1800
1801 if ( r0 >= radix ) break;
1802 }
1803
1804 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001805 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001806
1807 quotient = q1 * radix + q0;
1808
1809 return quotient;
1810#endif
1811}
1812
1813/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001815 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001816int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1817 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001818{
Janos Follath24eed8d2019-11-22 13:21:35 +00001819 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001820 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001822 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001823 MPI_VALIDATE_RET( A != NULL );
1824 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1827 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001830 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001831 /*
1832 * Avoid dynamic memory allocations for constant-size T2.
1833 *
1834 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1835 * so nobody increase the size of the MPI and we're safe to use an on-stack
1836 * buffer.
1837 */
Alexander K35d6d462019-10-31 14:46:45 +03001838 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001839 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1840 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1845 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 return( 0 );
1847 }
1848
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1850 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 X.s = Y.s = 1;
1852
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1854 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001857 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001858 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001859 {
1860 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1862 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 }
1864 else k = 0;
1865
1866 n = X.n - 1;
1867 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001871 {
1872 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001874 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001876
1877 for( i = n; i > t ; i-- )
1878 {
1879 if( X.p[i] >= Y.p[t] )
1880 Z.p[i - t - 1] = ~0;
1881 else
1882 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001883 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1884 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 }
1886
Alexander K35d6d462019-10-31 14:46:45 +03001887 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1888 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1889 T2.p[2] = X.p[i];
1890
Paul Bakker5121ce52009-01-03 21:22:43 +00001891 Z.p[i - t - 1]++;
1892 do
1893 {
1894 Z.p[i - t - 1]--;
1895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001897 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001898 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1904 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1905 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001908 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1910 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1911 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001912 Z.p[i - t - 1]--;
1913 }
1914 }
1915
1916 if( Q != NULL )
1917 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001918 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919 Q->s = A->s * B->s;
1920 }
1921
1922 if( R != NULL )
1923 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001925 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001926 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001929 R->s = 1;
1930 }
1931
1932cleanup:
1933
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001935 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001936 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001937
1938 return( ret );
1939}
1940
1941/*
1942 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001943 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001944int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1945 const mbedtls_mpi *A,
1946 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001947{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 mbedtls_mpi _B;
1949 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001950 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951
1952 p[0] = ( b < 0 ) ? -b : b;
1953 _B.s = ( b < 0 ) ? -1 : 1;
1954 _B.n = 1;
1955 _B.p = p;
1956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958}
1959
1960/*
1961 * Modulo: R = A mod B
1962 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001964{
Janos Follath24eed8d2019-11-22 13:21:35 +00001965 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001966 MPI_VALIDATE_RET( R != NULL );
1967 MPI_VALIDATE_RET( A != NULL );
1968 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1971 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1976 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1979 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980
1981cleanup:
1982
1983 return( ret );
1984}
1985
1986/*
1987 * Modulo: r = A mod b
1988 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001990{
Paul Bakker23986e52011-04-24 08:57:21 +00001991 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001993 MPI_VALIDATE_RET( r != NULL );
1994 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
1996 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001997 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
1999 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002001
2002 /*
2003 * handle trivial cases
2004 */
2005 if( b == 1 )
2006 {
2007 *r = 0;
2008 return( 0 );
2009 }
2010
2011 if( b == 2 )
2012 {
2013 *r = A->p[0] & 1;
2014 return( 0 );
2015 }
2016
2017 /*
2018 * general case
2019 */
Paul Bakker23986e52011-04-24 08:57:21 +00002020 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00002021 {
Paul Bakker23986e52011-04-24 08:57:21 +00002022 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 y = ( y << biH ) | ( x >> biH );
2024 z = y / b;
2025 y -= z * b;
2026
2027 x <<= biH;
2028 y = ( y << biH ) | ( x >> biH );
2029 z = y / b;
2030 y -= z * b;
2031 }
2032
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002033 /*
2034 * If A is negative, then the current y represents a negative value.
2035 * Flipping it to the positive side.
2036 */
2037 if( A->s < 0 && y != 0 )
2038 y = b - y;
2039
Paul Bakker5121ce52009-01-03 21:22:43 +00002040 *r = y;
2041
2042 return( 0 );
2043}
2044
2045/*
2046 * Fast Montgomery initialization (thanks to Tom St Denis)
2047 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002049{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002051 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
2053 x = m0;
2054 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002055
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002056 for( i = biL; i >= 8; i /= 2 )
2057 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
2059 *mm = ~x + 1;
2060}
2061
Gilles Peskine2a82f722020-06-04 15:00:49 +02002062/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2063 *
2064 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002065 * It must have at least as many limbs as N
2066 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002067 * On successful completion, A contains the result of
2068 * the multiplication A * B * R^-1 mod N where
2069 * R = (2^ciL)^n.
2070 * \param[in] B One of the numbers to multiply.
2071 * It must be nonzero and must not have more limbs than N
2072 * (B->n <= N->n).
2073 * \param[in] N The modulo. N must be odd.
2074 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2075 * This is -N^-1 mod 2^ciL.
2076 * \param[in,out] T A bignum for temporary storage.
2077 * It must be at least twice the limb size of N plus 2
2078 * (T->n >= 2 * (N->n + 1)).
2079 * Its initial content is unused and
2080 * its final content is indeterminate.
2081 * Note that unlike the usual convention in the library
2082 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002083 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002084static 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 +02002085 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002086{
Paul Bakker23986e52011-04-24 08:57:21 +00002087 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002089
2090 memset( T->p, 0, T->n * ciL );
2091
2092 d = T->p;
2093 n = N->n;
2094 m = ( B->n < n ) ? B->n : n;
2095
2096 for( i = 0; i < n; i++ )
2097 {
2098 /*
2099 * T = (T + u0*B + u1*N) / 2^biL
2100 */
2101 u0 = A->p[i];
2102 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2103
2104 mpi_mul_hlp( m, B->p, d, u0 );
2105 mpi_mul_hlp( n, N->p, d, u1 );
2106
2107 *d++ = u0; d[n + 1] = 0;
2108 }
2109
Gilles Peskine221626f2020-06-08 22:37:50 +02002110 /* At this point, d is either the desired result or the desired result
2111 * plus N. We now potentially subtract N, avoiding leaking whether the
2112 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002113
Gilles Peskine221626f2020-06-08 22:37:50 +02002114 /* Copy the n least significant limbs of d to A, so that
2115 * A = d if d < N (recall that N has n limbs). */
2116 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002117 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002118 * do the calculation without using conditional tests. */
2119 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002120 d[n] += 1;
Gilles Peskinec097e9e2020-06-08 21:58:22 +02002121 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02002122 /* If d0 < N then d < (2^biL)^n
2123 * so d[n] == 0 and we want to keep A as it is.
2124 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2125 * so d[n] == 1 and we want to set A to the result of the subtraction
2126 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2127 * This exactly corresponds to a conditional assignment. */
2128 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002129}
2130
2131/*
2132 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002133 *
2134 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002135 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002136static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2137 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002138{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 mbedtls_mpi_uint z = 1;
2140 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Paul Bakker8ddb6452013-02-27 14:56:33 +01002142 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002143 U.p = &z;
2144
Gilles Peskine4e91d472020-06-04 20:55:15 +02002145 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002146}
2147
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002148/*
2149 * Constant-flow boolean "equal" comparison:
2150 * return x == y
2151 *
2152 * This function can be used to write constant-time code by replacing branches
2153 * with bit operations - it can be used in conjunction with
2154 * mbedtls_ssl_cf_mask_from_bit().
2155 *
2156 * This function is implemented without using comparison operators, as those
2157 * might be translated to branches by some compilers on some platforms.
2158 */
2159static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2160{
2161 /* diff = 0 if x == y, non-zero otherwise */
2162 const size_t diff = x ^ y;
2163
2164 /* MSVC has a warning about unary minus on unsigned integer types,
2165 * but this is well-defined and precisely what we want to do here. */
2166#if defined(_MSC_VER)
2167#pragma warning( push )
2168#pragma warning( disable : 4146 )
2169#endif
2170
2171 /* diff_msb's most significant bit is equal to x != y */
2172 const size_t diff_msb = ( diff | -diff );
2173
2174#if defined(_MSC_VER)
2175#pragma warning( pop )
2176#endif
2177
2178 /* diff1 = (x != y) ? 1 : 0 */
2179 const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2180
2181 return( 1 ^ diff1 );
2182}
2183
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002184/**
2185 * Select an MPI from a table without leaking the index.
2186 *
2187 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2188 * reads the entire table in order to avoid leaking the value of idx to an
2189 * attacker able to observe memory access patterns.
2190 *
2191 * \param[out] R Where to write the selected MPI.
2192 * \param[in] T The table to read from.
2193 * \param[in] T_size The number of elements in the table.
2194 * \param[in] idx The index of the element to select;
2195 * this must satisfy 0 <= idx < T_size.
2196 *
2197 * \return \c 0 on success, or a negative error code.
2198 */
2199static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2200{
2201 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2202
2203 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002204 {
2205 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
2206 mbedtls_mpi_cf_bool_eq( i, idx ) ) );
2207 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002208
2209cleanup:
2210 return( ret );
2211}
2212
Paul Bakker5121ce52009-01-03 21:22:43 +00002213/*
2214 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2215 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002216int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2217 const mbedtls_mpi *E, const mbedtls_mpi *N,
2218 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002219{
Janos Follath24eed8d2019-11-22 13:21:35 +00002220 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002221 size_t wbits, wsize, one = 1;
2222 size_t i, j, nblimbs;
2223 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002225 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002226 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002227
Hanno Becker73d7d792018-12-11 10:35:51 +00002228 MPI_VALIDATE_RET( X != NULL );
2229 MPI_VALIDATE_RET( A != NULL );
2230 MPI_VALIDATE_RET( E != NULL );
2231 MPI_VALIDATE_RET( N != NULL );
2232
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002233 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2237 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002238
Chris Jones9246d042020-11-25 15:12:39 +00002239 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2240 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2241 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2242
Paul Bakkerf6198c12012-05-16 08:02:29 +00002243 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002244 * Init temps and window size
2245 */
2246 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2248 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002249 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250 memset( W, 0, sizeof( W ) );
2251
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002252 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002253
2254 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2255 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2256
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002257#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2259 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002260#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002261
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2264 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2265 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
2267 /*
Paul Bakker50546922012-05-19 08:40:49 +00002268 * Compensate for negative A (and correct at the end)
2269 */
2270 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002271 if( neg )
2272 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002274 Apos.s = 1;
2275 A = &Apos;
2276 }
2277
2278 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 * If 1st call, pre-compute R^2 mod N
2280 */
2281 if( _RR == NULL || _RR->p == NULL )
2282 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2284 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2285 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
2287 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 }
2290 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
2293 /*
2294 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2295 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2297 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002298 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002300
Gilles Peskine4e91d472020-06-04 20:55:15 +02002301 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
2303 /*
2304 * X = R^2 * R^-1 mod N = R mod N
2305 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002307 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
2309 if( wsize > 1 )
2310 {
2311 /*
2312 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2313 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002314 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2317 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002318
2319 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002320 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002321
Paul Bakker5121ce52009-01-03 21:22:43 +00002322 /*
2323 * W[i] = W[i - 1] * W[1]
2324 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002325 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002326 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2328 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
Gilles Peskine4e91d472020-06-04 20:55:15 +02002330 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 }
2332 }
2333
2334 nblimbs = E->n;
2335 bufsize = 0;
2336 nbits = 0;
2337 wbits = 0;
2338 state = 0;
2339
2340 while( 1 )
2341 {
2342 if( bufsize == 0 )
2343 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002344 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002345 break;
2346
Paul Bakker0d7702c2013-10-29 16:18:35 +01002347 nblimbs--;
2348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002350 }
2351
2352 bufsize--;
2353
2354 ei = (E->p[nblimbs] >> bufsize) & 1;
2355
2356 /*
2357 * skip leading 0s
2358 */
2359 if( ei == 0 && state == 0 )
2360 continue;
2361
2362 if( ei == 0 && state == 1 )
2363 {
2364 /*
2365 * out of window, square X
2366 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002367 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 continue;
2369 }
2370
2371 /*
2372 * add ei to current window
2373 */
2374 state = 2;
2375
2376 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002377 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002378
2379 if( nbits == wsize )
2380 {
2381 /*
2382 * X = X^wsize R^-1 mod N
2383 */
2384 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002385 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002386
2387 /*
2388 * X = X * W[wbits] R^-1 mod N
2389 */
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002390 MBEDTLS_MPI_CHK( mpi_select( &WW, W, 1 << wsize, wbits ) );
2391 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
2393 state--;
2394 nbits = 0;
2395 wbits = 0;
2396 }
2397 }
2398
2399 /*
2400 * process the remaining bits
2401 */
2402 for( i = 0; i < nbits; i++ )
2403 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002404 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002405
2406 wbits <<= 1;
2407
Paul Bakker66d5d072014-06-17 16:39:18 +02002408 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002409 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002410 }
2411
2412 /*
2413 * X = A^E * R * R^-1 mod N = A^E mod N
2414 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002415 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002416
Hanno Beckera4af1c42017-04-18 09:07:45 +01002417 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002418 {
2419 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002421 }
2422
Paul Bakker5121ce52009-01-03 21:22:43 +00002423cleanup:
2424
Paul Bakker66d5d072014-06-17 16:39:18 +02002425 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002428 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002429 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002430
Paul Bakker75a28602014-03-31 12:08:17 +02002431 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
2434 return( ret );
2435}
2436
Paul Bakker5121ce52009-01-03 21:22:43 +00002437/*
2438 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2439 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002441{
Janos Follath24eed8d2019-11-22 13:21:35 +00002442 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002443 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002444 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002445
Hanno Becker73d7d792018-12-11 10:35:51 +00002446 MPI_VALIDATE_RET( G != NULL );
2447 MPI_VALIDATE_RET( A != NULL );
2448 MPI_VALIDATE_RET( B != NULL );
2449
Alexander Ke8ad49f2019-08-16 16:16:07 +03002450 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2453 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 lz = mbedtls_mpi_lsb( &TA );
2456 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002457
Paul Bakker66d5d072014-06-17 16:39:18 +02002458 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002459 lz = lzt;
2460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2462 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002463
Paul Bakker5121ce52009-01-03 21:22:43 +00002464 TA.s = TB.s = 1;
2465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002467 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2469 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002472 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2474 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002475 }
2476 else
2477 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2479 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002480 }
2481 }
2482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2484 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002485
2486cleanup:
2487
Alexander Ke8ad49f2019-08-16 16:16:07 +03002488 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002489
2490 return( ret );
2491}
2492
Paul Bakker33dc46b2014-04-30 16:11:39 +02002493/*
2494 * Fill X with size bytes of random.
2495 *
2496 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002497 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002498 * deterministic, eg for tests).
2499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002501 int (*f_rng)(void *, unsigned char *, size_t),
2502 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002503{
Janos Follath24eed8d2019-11-22 13:21:35 +00002504 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002505 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002506 size_t const overhead = ( limbs * ciL ) - size;
2507 unsigned char *Xp;
2508
Hanno Becker8ce11a32018-12-19 16:18:52 +00002509 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002510 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002511
Hanno Beckerda1655a2017-10-18 14:21:44 +01002512 /* Ensure that target MPI has exactly the necessary number of limbs */
2513 if( X->n != limbs )
2514 {
2515 mbedtls_mpi_free( X );
2516 mbedtls_mpi_init( X );
2517 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2518 }
2519 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002520
Hanno Beckerda1655a2017-10-18 14:21:44 +01002521 Xp = (unsigned char*) X->p;
Gilles Peskine436400e2020-11-25 16:15:14 +01002522 MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002523
Hanno Becker2be8a552018-10-25 12:40:09 +01002524 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002525
2526cleanup:
2527 return( ret );
2528}
2529
Paul Bakker5121ce52009-01-03 21:22:43 +00002530/*
2531 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2532 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002534{
Janos Follath24eed8d2019-11-22 13:21:35 +00002535 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002536 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002537 MPI_VALIDATE_RET( X != NULL );
2538 MPI_VALIDATE_RET( A != NULL );
2539 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002540
Hanno Becker4bcb4912017-04-18 15:49:39 +01002541 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2545 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2546 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002551 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002553 goto cleanup;
2554 }
2555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2557 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2558 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2559 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002561 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2562 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2563 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2564 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002565
2566 do
2567 {
2568 while( ( TU.p[0] & 1 ) == 0 )
2569 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002570 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002571
2572 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2573 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2575 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002576 }
2577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2579 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002580 }
2581
2582 while( ( TV.p[0] & 1 ) == 0 )
2583 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
2586 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2587 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2589 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002590 }
2591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2593 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594 }
2595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002596 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2599 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2600 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002601 }
2602 else
2603 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2605 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2606 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002607 }
2608 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002609 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002611 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2612 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002614 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2615 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002618
2619cleanup:
2620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002621 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2622 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2623 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002624
2625 return( ret );
2626}
2627
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002628#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002629
Paul Bakker5121ce52009-01-03 21:22:43 +00002630static const int small_prime[] =
2631{
2632 3, 5, 7, 11, 13, 17, 19, 23,
2633 29, 31, 37, 41, 43, 47, 53, 59,
2634 61, 67, 71, 73, 79, 83, 89, 97,
2635 101, 103, 107, 109, 113, 127, 131, 137,
2636 139, 149, 151, 157, 163, 167, 173, 179,
2637 181, 191, 193, 197, 199, 211, 223, 227,
2638 229, 233, 239, 241, 251, 257, 263, 269,
2639 271, 277, 281, 283, 293, 307, 311, 313,
2640 317, 331, 337, 347, 349, 353, 359, 367,
2641 373, 379, 383, 389, 397, 401, 409, 419,
2642 421, 431, 433, 439, 443, 449, 457, 461,
2643 463, 467, 479, 487, 491, 499, 503, 509,
2644 521, 523, 541, 547, 557, 563, 569, 571,
2645 577, 587, 593, 599, 601, 607, 613, 617,
2646 619, 631, 641, 643, 647, 653, 659, 661,
2647 673, 677, 683, 691, 701, 709, 719, 727,
2648 733, 739, 743, 751, 757, 761, 769, 773,
2649 787, 797, 809, 811, 821, 823, 827, 829,
2650 839, 853, 857, 859, 863, 877, 881, 883,
2651 887, 907, 911, 919, 929, 937, 941, 947,
2652 953, 967, 971, 977, 983, 991, 997, -103
2653};
2654
2655/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002656 * Small divisors test (X must be positive)
2657 *
2658 * Return values:
2659 * 0: no small factor (possible prime, more tests needed)
2660 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002662 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002663 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002664static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002665{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002666 int ret = 0;
2667 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002668 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002669
Paul Bakker5121ce52009-01-03 21:22:43 +00002670 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002672
2673 for( i = 0; small_prime[i] > 0; i++ )
2674 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002675 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002676 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002678 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002679
2680 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002681 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002682 }
2683
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002684cleanup:
2685 return( ret );
2686}
2687
2688/*
2689 * Miller-Rabin pseudo-primality test (HAC 4.24)
2690 */
Janos Follathda31fa12018-09-03 14:45:23 +01002691static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002692 int (*f_rng)(void *, unsigned char *, size_t),
2693 void *p_rng )
2694{
Pascal Junodb99183d2015-03-11 16:49:45 +01002695 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002696 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002698
Hanno Becker8ce11a32018-12-19 16:18:52 +00002699 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002700 MPI_VALIDATE_RET( f_rng != NULL );
2701
2702 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2703 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002705
Paul Bakker5121ce52009-01-03 21:22:43 +00002706 /*
2707 * W = |X| - 1
2708 * R = W >> lsb( W )
2709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002710 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2711 s = mbedtls_mpi_lsb( &W );
2712 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2713 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002714
Janos Follathda31fa12018-09-03 14:45:23 +01002715 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002716 {
2717 /*
2718 * pick a random A, 1 < A < |X| - 1
2719 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002720 count = 0;
2721 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002722 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002723
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002724 j = mbedtls_mpi_bitlen( &A );
2725 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002726 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002727 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002728 }
2729
2730 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002731 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2732 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002733 }
2734
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002735 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2736 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002737
2738 /*
2739 * A = A^R mod |X|
2740 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002741 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002743 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2744 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002745 continue;
2746
2747 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002748 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002749 {
2750 /*
2751 * A = A * A mod |X|
2752 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002753 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2754 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002757 break;
2758
2759 j++;
2760 }
2761
2762 /*
2763 * not prime if A != |X| - 1 or A == 1
2764 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002765 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2766 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002767 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002769 break;
2770 }
2771 }
2772
2773cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002774 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2775 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002776 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002777
2778 return( ret );
2779}
2780
2781/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002782 * Pseudo-primality test: small factors, then Miller-Rabin
2783 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002784int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2785 int (*f_rng)(void *, unsigned char *, size_t),
2786 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002787{
Janos Follath24eed8d2019-11-22 13:21:35 +00002788 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002790 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002791 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002792
2793 XX.s = 1;
2794 XX.n = X->n;
2795 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002797 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2798 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2799 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002800
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002801 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002802 return( 0 );
2803
2804 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2805 {
2806 if( ret == 1 )
2807 return( 0 );
2808
2809 return( ret );
2810 }
2811
Janos Follathda31fa12018-09-03 14:45:23 +01002812 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002813}
2814
Janos Follatha0b67c22018-09-18 14:48:23 +01002815#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002816/*
2817 * Pseudo-primality test, error probability 2^-80
2818 */
2819int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2820 int (*f_rng)(void *, unsigned char *, size_t),
2821 void *p_rng )
2822{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002823 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002824 MPI_VALIDATE_RET( f_rng != NULL );
2825
Janos Follatha0b67c22018-09-18 14:48:23 +01002826 /*
2827 * In the past our key generation aimed for an error rate of at most
2828 * 2^-80. Since this function is deprecated, aim for the same certainty
2829 * here as well.
2830 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002831 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002832}
Janos Follatha0b67c22018-09-18 14:48:23 +01002833#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002834
2835/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002836 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002837 *
Janos Follathf301d232018-08-14 13:34:01 +01002838 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2839 * be either 1024 bits or 1536 bits long, and flags must contain
2840 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002841 */
Janos Follath7c025a92018-08-14 11:08:41 +01002842int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002843 int (*f_rng)(void *, unsigned char *, size_t),
2844 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002845{
Jethro Beekman66689272018-02-14 19:24:10 -08002846#ifdef MBEDTLS_HAVE_INT64
2847// ceil(2^63.5)
2848#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2849#else
2850// ceil(2^31.5)
2851#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2852#endif
2853 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002854 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002855 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002856 mbedtls_mpi_uint r;
2857 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002858
Hanno Becker8ce11a32018-12-19 16:18:52 +00002859 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002860 MPI_VALIDATE_RET( f_rng != NULL );
2861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002862 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2863 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002864
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002865 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002866
2867 n = BITS_TO_LIMBS( nbits );
2868
Janos Follathda31fa12018-09-03 14:45:23 +01002869 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2870 {
2871 /*
2872 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2873 */
2874 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2875 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2876 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2877 }
2878 else
2879 {
2880 /*
2881 * 2^-100 error probability, number of rounds computed based on HAC,
2882 * fact 4.48
2883 */
2884 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2885 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2886 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2887 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2888 }
2889
Jethro Beekman66689272018-02-14 19:24:10 -08002890 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002891 {
Jethro Beekman66689272018-02-14 19:24:10 -08002892 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2893 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2894 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2895
2896 k = n * biL;
2897 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2898 X->p[0] |= 1;
2899
Janos Follath7c025a92018-08-14 11:08:41 +01002900 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002901 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002902 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002903
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002904 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002905 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002906 }
Jethro Beekman66689272018-02-14 19:24:10 -08002907 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002908 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002909 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002910 * An necessary condition for Y and X = 2Y + 1 to be prime
2911 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2912 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002913 */
Jethro Beekman66689272018-02-14 19:24:10 -08002914
2915 X->p[0] |= 2;
2916
2917 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2918 if( r == 0 )
2919 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2920 else if( r == 1 )
2921 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2922
2923 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2924 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2925 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2926
2927 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002928 {
Jethro Beekman66689272018-02-14 19:24:10 -08002929 /*
2930 * First, check small factors for X and Y
2931 * before doing Miller-Rabin on any of them
2932 */
2933 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2934 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002935 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002936 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002937 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002938 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002939 goto cleanup;
2940
2941 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2942 goto cleanup;
2943
2944 /*
2945 * Next candidates. We want to preserve Y = (X-1) / 2 and
2946 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2947 * so up Y by 6 and X by 12.
2948 */
2949 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2950 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002951 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002952 }
2953 }
2954
2955cleanup:
2956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002957 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002958
2959 return( ret );
2960}
2961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002962#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002964#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002965
Paul Bakker23986e52011-04-24 08:57:21 +00002966#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002967
2968static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2969{
2970 { 693, 609, 21 },
2971 { 1764, 868, 28 },
2972 { 768454923, 542167814, 1 }
2973};
2974
Paul Bakker5121ce52009-01-03 21:22:43 +00002975/*
2976 * Checkup routine
2977 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002978int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002979{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002980 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002981 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002983 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2984 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002985
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002986 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002987 "EFE021C2645FD1DC586E69184AF4A31E" \
2988 "D5F53E93B5F123FA41680867BA110131" \
2989 "944FE7952E2517337780CB0DB80E61AA" \
2990 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2991
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002992 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002993 "B2E7EFD37075B9F03FF989C7C5051C20" \
2994 "34D2A323810251127E7BF8625A4F49A5" \
2995 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2996 "5B5C25763222FEFCCFC38B832366C29E" ) );
2997
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002998 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002999 "0066A198186C18C10B2F5ED9B522752A" \
3000 "9830B69916E535C8F047518A889A43A5" \
3001 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003003 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003004
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003005 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003006 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3007 "9E857EA95A03512E2BAE7391688D264A" \
3008 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3009 "8001B72E848A38CAE1C65F78E56ABDEF" \
3010 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3011 "ECF677152EF804370C1A305CAF3B5BF1" \
3012 "30879B56C61DE584A0F53A2447A51E" ) );
3013
3014 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003015 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003016
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003017 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003018 {
3019 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003020 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003021
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003022 ret = 1;
3023 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003024 }
3025
3026 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003027 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003029 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &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 "256567336059E52CAE22925474705F39A94" ) );
3033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003034 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003035 "6613F26162223DF488E9CD48CC132C7A" \
3036 "0AC93C701B001B092E4E5B9F73BCD27B" \
3037 "9EE50D0657C77F374E903CDFA4C642" ) );
3038
3039 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003040 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003042 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3043 mbedtls_mpi_cmp_mpi( &Y, &V ) != 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_exp_mod( &X, &A, &E, &N, NULL ) );
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 "36E139AEA55215609D2816998ED020BB" \
3059 "BD96C37890F65171D948E9BC7CBAA4D9" \
3060 "325D24D6A3C12710F10A09FA08AB87" ) );
3061
3062 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003063 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003065 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003066 {
3067 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003068 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003069
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003070 ret = 1;
3071 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003072 }
3073
3074 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003075 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003077 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003079 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003080 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3081 "C3DBA76456363A10869622EAC2DD84EC" \
3082 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3083
3084 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003085 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003087 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003088 {
3089 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003090 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003091
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003092 ret = 1;
3093 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003094 }
3095
3096 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003097 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003098
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003099 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003100 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003101
Paul Bakker66d5d072014-06-17 16:39:18 +02003102 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003103 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003104 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3105 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003107 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003109 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003110 {
3111 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003112 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003113
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003114 ret = 1;
3115 goto cleanup;
3116 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003117 }
3118
3119 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003120 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003121
Paul Bakker5121ce52009-01-03 21:22:43 +00003122cleanup:
3123
3124 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003125 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003127 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3128 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003129
3130 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003131 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003132
3133 return( ret );
3134}
3135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003136#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003138#endif /* MBEDTLS_BIGNUM_C */