blob: 343ce48dfdf0408e3e3aebd77333345ed3fcf0dc [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é-Gonnard2cf5a7c2015-04-08 12:49:31 +0200325 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000326 MPI_VALIDATE_RET( X != NULL );
327 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100328
329 if( X == Y )
330 return( 0 );
331
Pascal Junodb99183d2015-03-11 16:49:45 +0100332 /* make sure swap is 0 or 1 in a time-constant manner */
333 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
336 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100337
338 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200339 X->s = X->s * ( 1 - swap ) + Y->s * swap;
340 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100341
342
343 for( i = 0; i < X->n; i++ )
344 {
345 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200346 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
347 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100348 }
349
350cleanup:
351 return( ret );
352}
353
354/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000355 * Set value from integer
356 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000358{
Janos Follath24eed8d2019-11-22 13:21:35 +0000359 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +0000360 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000363 memset( X->p, 0, X->n * ciL );
364
365 X->p[0] = ( z < 0 ) ? -z : z;
366 X->s = ( z < 0 ) ? -1 : 1;
367
368cleanup:
369
370 return( ret );
371}
372
373/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 * Get a specific bit
375 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000377{
Hanno Becker73d7d792018-12-11 10:35:51 +0000378 MPI_VALIDATE_RET( X != NULL );
379
Paul Bakker2f5947e2011-05-18 15:47:11 +0000380 if( X->n * biL <= pos )
381 return( 0 );
382
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200383 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000384}
385
Gilles Peskine11cdb052018-11-20 16:47:47 +0100386/* Get a specific byte, without range checks. */
387#define GET_BYTE( X, i ) \
388 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
389
Paul Bakker2f5947e2011-05-18 15:47:11 +0000390/*
391 * Set a bit to a specific value of 0 or 1
392 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000394{
395 int ret = 0;
396 size_t off = pos / biL;
397 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000398 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000399
400 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200402
Paul Bakker2f5947e2011-05-18 15:47:11 +0000403 if( X->n * biL <= pos )
404 {
405 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200406 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000409 }
410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
412 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000413
414cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200415
Paul Bakker2f5947e2011-05-18 15:47:11 +0000416 return( ret );
417}
418
419/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200420 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000423{
Paul Bakker23986e52011-04-24 08:57:21 +0000424 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000425 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
427 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000428 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000429 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
430 return( count );
431
432 return( 0 );
433}
434
435/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000436 * Count leading zero bits in a given integer
437 */
438static size_t mbedtls_clz( const mbedtls_mpi_uint x )
439{
440 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100441 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000442
443 for( j = 0; j < biL; j++ )
444 {
445 if( x & mask ) break;
446
447 mask >>= 1;
448 }
449
450 return j;
451}
452
453/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200454 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000455 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200456size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000457{
Paul Bakker23986e52011-04-24 08:57:21 +0000458 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000459
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200460 if( X->n == 0 )
461 return( 0 );
462
Paul Bakker5121ce52009-01-03 21:22:43 +0000463 for( i = X->n - 1; i > 0; i-- )
464 if( X->p[i] != 0 )
465 break;
466
Simon Butcher15b15d12015-11-26 19:35:03 +0000467 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
Paul Bakker23986e52011-04-24 08:57:21 +0000469 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470}
471
472/*
473 * Return the total size in bytes
474 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000476{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200477 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000478}
479
480/*
481 * Convert an ASCII character to digit value
482 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000484{
485 *d = 255;
486
487 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
488 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
489 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
490
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 if( *d >= (mbedtls_mpi_uint) radix )
492 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000493
494 return( 0 );
495}
496
497/*
498 * Import from an ASCII string
499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501{
Janos Follath24eed8d2019-11-22 13:21:35 +0000502 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000503 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 mbedtls_mpi_uint d;
505 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000506 MPI_VALIDATE_RET( X != NULL );
507 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000508
509 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000510 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513
Paul Bakkerff60ee62010-03-16 21:09:09 +0000514 slen = strlen( s );
515
Paul Bakker5121ce52009-01-03 21:22:43 +0000516 if( radix == 16 )
517 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100518 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200519 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
520
Paul Bakkerff60ee62010-03-16 21:09:09 +0000521 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
524 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
Paul Bakker23986e52011-04-24 08:57:21 +0000526 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000527 {
Paul Bakker23986e52011-04-24 08:57:21 +0000528 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000529 {
530 X->s = -1;
531 break;
532 }
533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200535 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000536 }
537 }
538 else
539 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000541
Paul Bakkerff60ee62010-03-16 21:09:09 +0000542 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000543 {
544 if( i == 0 && s[i] == '-' )
545 {
546 X->s = -1;
547 continue;
548 }
549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
551 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000552
553 if( X->s == 1 )
554 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000556 }
557 else
558 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200559 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000560 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000561 }
562 }
563
564cleanup:
565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000567
568 return( ret );
569}
570
571/*
Ron Eldora16fa292018-11-20 14:07:01 +0200572 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000573 */
Ron Eldora16fa292018-11-20 14:07:01 +0200574static int mpi_write_hlp( mbedtls_mpi *X, int radix,
575 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000576{
Janos Follath24eed8d2019-11-22 13:21:35 +0000577 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200579 size_t length = 0;
580 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
Ron Eldora16fa292018-11-20 14:07:01 +0200582 do
583 {
584 if( length >= buflen )
585 {
586 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
587 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000588
Ron Eldora16fa292018-11-20 14:07:01 +0200589 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
590 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
591 /*
592 * Write the residue in the current position, as an ASCII character.
593 */
594 if( r < 0xA )
595 *(--p_end) = (char)( '0' + r );
596 else
597 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000598
Ron Eldora16fa292018-11-20 14:07:01 +0200599 length++;
600 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000601
Ron Eldora16fa292018-11-20 14:07:01 +0200602 memmove( *p, p_end, length );
603 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000604
605cleanup:
606
607 return( ret );
608}
609
610/*
611 * Export into an ASCII string
612 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100613int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
614 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000615{
Paul Bakker23986e52011-04-24 08:57:21 +0000616 int ret = 0;
617 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000618 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000620 MPI_VALIDATE_RET( X != NULL );
621 MPI_VALIDATE_RET( olen != NULL );
622 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
624 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000625 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000626
Hanno Becker23cfea02019-02-04 09:45:07 +0000627 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
628 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
629 * `n`. If radix > 4, this might be a strict
630 * overapproximation of the number of
631 * radix-adic digits needed to present `n`. */
632 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
633 * present `n`. */
634
Janos Follath80470622019-03-06 13:43:02 +0000635 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000636 n += 1; /* Compensate for the divisions above, which round down `n`
637 * in case it's not even. */
638 n += 1; /* Potential '-'-sign. */
639 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
640 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100642 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100644 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000646 }
647
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100648 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
651 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000652 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000653 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000654 buflen--;
655 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
657 if( radix == 16 )
658 {
Paul Bakker23986e52011-04-24 08:57:21 +0000659 int c;
660 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Paul Bakker23986e52011-04-24 08:57:21 +0000662 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 {
Paul Bakker23986e52011-04-24 08:57:21 +0000664 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000665 {
Paul Bakker23986e52011-04-24 08:57:21 +0000666 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
Paul Bakker6c343d72014-07-10 14:36:19 +0200668 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 continue;
670
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000671 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000672 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000673 k = 1;
674 }
675 }
676 }
677 else
678 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000680
681 if( T.s == -1 )
682 T.s = 1;
683
Ron Eldora16fa292018-11-20 14:07:01 +0200684 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000685 }
686
687 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100688 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
690cleanup:
691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
694 return( ret );
695}
696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000698/*
699 * Read X from an opened file
700 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000702{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000704 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000705 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000706 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000707 * Buffer should have space for (short) label and decimal formatted MPI,
708 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Hanno Becker73d7d792018-12-11 10:35:51 +0000712 MPI_VALIDATE_RET( X != NULL );
713 MPI_VALIDATE_RET( fin != NULL );
714
715 if( radix < 2 || radix > 16 )
716 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
717
Paul Bakker5121ce52009-01-03 21:22:43 +0000718 memset( s, 0, sizeof( s ) );
719 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000721
722 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000723 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000725
Hanno Beckerb2034b72017-04-26 11:46:46 +0100726 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
727 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000728
729 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100730 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000731 if( mpi_get_digit( &d, radix, *p ) != 0 )
732 break;
733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000735}
736
737/*
738 * Write X into an opened file (or stdout if fout == NULL)
739 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000741{
Janos Follath24eed8d2019-11-22 13:21:35 +0000742 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000743 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000744 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000745 * Buffer should have space for (short) label and decimal formatted MPI,
746 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000747 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000749 MPI_VALIDATE_RET( X != NULL );
750
751 if( radix < 2 || radix > 16 )
752 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000753
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100754 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000755
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100756 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
758 if( p == NULL ) p = "";
759
760 plen = strlen( p );
761 slen = strlen( s );
762 s[slen++] = '\r';
763 s[slen++] = '\n';
764
765 if( fout != NULL )
766 {
767 if( fwrite( p, 1, plen, fout ) != plen ||
768 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000770 }
771 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200772 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000773
774cleanup:
775
776 return( ret );
777}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000779
Hanno Beckerda1655a2017-10-18 14:21:44 +0100780
781/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
782 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000783
784static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
785{
786 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100787 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000788 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100789
790 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
791 {
792 tmp <<= CHAR_BIT;
793 tmp |= (mbedtls_mpi_uint) *x_ptr;
794 }
795
Hanno Beckerf8720072018-11-08 11:53:49 +0000796 return( tmp );
797}
798
799static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
800{
801#if defined(__BYTE_ORDER__)
802
803/* Nothing to do on bigendian systems. */
804#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
805 return( x );
806#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
807
808#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
809
810/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000811#if defined(__GNUC__) && defined(__GNUC_PREREQ)
812#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000813#define have_bswap
814#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000815#endif
816
817#if defined(__clang__) && defined(__has_builtin)
818#if __has_builtin(__builtin_bswap32) && \
819 __has_builtin(__builtin_bswap64)
820#define have_bswap
821#endif
822#endif
823
Hanno Beckerf8720072018-11-08 11:53:49 +0000824#if defined(have_bswap)
825 /* The compiler is hopefully able to statically evaluate this! */
826 switch( sizeof(mbedtls_mpi_uint) )
827 {
828 case 4:
829 return( __builtin_bswap32(x) );
830 case 8:
831 return( __builtin_bswap64(x) );
832 }
833#endif
834#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
835#endif /* __BYTE_ORDER__ */
836
837 /* Fall back to C-based reordering if we don't know the byte order
838 * or we couldn't use a compiler-specific builtin. */
839 return( mpi_uint_bigendian_to_host_c( x ) );
840}
841
Hanno Becker2be8a552018-10-25 12:40:09 +0100842static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100843{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100844 mbedtls_mpi_uint *cur_limb_left;
845 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100846 if( limbs == 0 )
847 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100848
849 /*
850 * Traverse limbs and
851 * - adapt byte-order in each limb
852 * - swap the limbs themselves.
853 * For that, simultaneously traverse the limbs from left to right
854 * and from right to left, as long as the left index is not bigger
855 * than the right index (it's not a problem if limbs is odd and the
856 * indices coincide in the last iteration).
857 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100858 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
859 cur_limb_left <= cur_limb_right;
860 cur_limb_left++, cur_limb_right-- )
861 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000862 mbedtls_mpi_uint tmp;
863 /* Note that if cur_limb_left == cur_limb_right,
864 * this code effectively swaps the bytes only once. */
865 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
866 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
867 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100868 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100869}
870
Paul Bakker5121ce52009-01-03 21:22:43 +0000871/*
Janos Follatha778a942019-02-13 10:28:28 +0000872 * Import X from unsigned binary data, little endian
873 */
874int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
875 const unsigned char *buf, size_t buflen )
876{
Janos Follath24eed8d2019-11-22 13:21:35 +0000877 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000878 size_t i;
879 size_t const limbs = CHARS_TO_LIMBS( buflen );
880
881 /* Ensure that target MPI has exactly the necessary number of limbs */
882 if( X->n != limbs )
883 {
884 mbedtls_mpi_free( X );
885 mbedtls_mpi_init( X );
886 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
887 }
888
889 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
890
891 for( i = 0; i < buflen; i++ )
892 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
893
894cleanup:
895
Janos Follath171a7ef2019-02-15 16:17:45 +0000896 /*
897 * This function is also used to import keys. However, wiping the buffers
898 * upon failure is not necessary because failure only can happen before any
899 * input is copied.
900 */
Janos Follatha778a942019-02-13 10:28:28 +0000901 return( ret );
902}
903
904/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000905 * Import X from unsigned binary data, big endian
906 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000908{
Janos Follath24eed8d2019-11-22 13:21:35 +0000909 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100910 size_t const limbs = CHARS_TO_LIMBS( buflen );
911 size_t const overhead = ( limbs * ciL ) - buflen;
912 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000913
Hanno Becker8ce11a32018-12-19 16:18:52 +0000914 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000915 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
916
Hanno Becker073c1992017-10-17 15:17:27 +0100917 /* Ensure that target MPI has exactly the necessary number of limbs */
918 if( X->n != limbs )
919 {
920 mbedtls_mpi_free( X );
921 mbedtls_mpi_init( X );
922 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
923 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000925
Hanno Becker0e810b92019-01-03 17:13:11 +0000926 /* Avoid calling `memcpy` with NULL source argument,
927 * even if buflen is 0. */
928 if( buf != NULL )
929 {
930 Xp = (unsigned char*) X->p;
931 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100932
Hanno Becker0e810b92019-01-03 17:13:11 +0000933 mpi_bigendian_to_host( X->p, limbs );
934 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000935
936cleanup:
937
Janos Follath171a7ef2019-02-15 16:17:45 +0000938 /*
939 * This function is also used to import keys. However, wiping the buffers
940 * upon failure is not necessary because failure only can happen before any
941 * input is copied.
942 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 return( ret );
944}
945
946/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000947 * Export X into unsigned binary data, little endian
948 */
949int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
950 unsigned char *buf, size_t buflen )
951{
952 size_t stored_bytes = X->n * ciL;
953 size_t bytes_to_copy;
954 size_t i;
955
956 if( stored_bytes < buflen )
957 {
958 bytes_to_copy = stored_bytes;
959 }
960 else
961 {
962 bytes_to_copy = buflen;
963
964 /* The output buffer is smaller than the allocated size of X.
965 * However X may fit if its leading bytes are zero. */
966 for( i = bytes_to_copy; i < stored_bytes; i++ )
967 {
968 if( GET_BYTE( X, i ) != 0 )
969 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
970 }
971 }
972
973 for( i = 0; i < bytes_to_copy; i++ )
974 buf[i] = GET_BYTE( X, i );
975
976 if( stored_bytes < buflen )
977 {
978 /* Write trailing 0 bytes */
979 memset( buf + stored_bytes, 0, buflen - stored_bytes );
980 }
981
982 return( 0 );
983}
984
985/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000986 * Export X into unsigned binary data, big endian
987 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100988int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
989 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000990{
Hanno Becker73d7d792018-12-11 10:35:51 +0000991 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100992 size_t bytes_to_copy;
993 unsigned char *p;
994 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000995
Hanno Becker73d7d792018-12-11 10:35:51 +0000996 MPI_VALIDATE_RET( X != NULL );
997 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
998
999 stored_bytes = X->n * ciL;
1000
Gilles Peskine11cdb052018-11-20 16:47:47 +01001001 if( stored_bytes < buflen )
1002 {
1003 /* There is enough space in the output buffer. Write initial
1004 * null bytes and record the position at which to start
1005 * writing the significant bytes. In this case, the execution
1006 * trace of this function does not depend on the value of the
1007 * number. */
1008 bytes_to_copy = stored_bytes;
1009 p = buf + buflen - stored_bytes;
1010 memset( buf, 0, buflen - stored_bytes );
1011 }
1012 else
1013 {
1014 /* The output buffer is smaller than the allocated size of X.
1015 * However X may fit if its leading bytes are zero. */
1016 bytes_to_copy = buflen;
1017 p = buf;
1018 for( i = bytes_to_copy; i < stored_bytes; i++ )
1019 {
1020 if( GET_BYTE( X, i ) != 0 )
1021 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1022 }
1023 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001024
Gilles Peskine11cdb052018-11-20 16:47:47 +01001025 for( i = 0; i < bytes_to_copy; i++ )
1026 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001027
1028 return( 0 );
1029}
1030
1031/*
1032 * Left-shift: X <<= count
1033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001035{
Janos Follath24eed8d2019-11-22 13:21:35 +00001036 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001037 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001039 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001040
1041 v0 = count / (biL );
1042 t1 = count & (biL - 1);
1043
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001044 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001045
Paul Bakkerf9688572011-05-05 10:00:45 +00001046 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001048
1049 ret = 0;
1050
1051 /*
1052 * shift by count / limb_size
1053 */
1054 if( v0 > 0 )
1055 {
Paul Bakker23986e52011-04-24 08:57:21 +00001056 for( i = X->n; i > v0; i-- )
1057 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001058
Paul Bakker23986e52011-04-24 08:57:21 +00001059 for( ; i > 0; i-- )
1060 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001061 }
1062
1063 /*
1064 * shift by count % limb_size
1065 */
1066 if( t1 > 0 )
1067 {
1068 for( i = v0; i < X->n; i++ )
1069 {
1070 r1 = X->p[i] >> (biL - t1);
1071 X->p[i] <<= t1;
1072 X->p[i] |= r0;
1073 r0 = r1;
1074 }
1075 }
1076
1077cleanup:
1078
1079 return( ret );
1080}
1081
1082/*
1083 * Right-shift: X >>= count
1084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001086{
Paul Bakker23986e52011-04-24 08:57:21 +00001087 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001089 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001090
1091 v0 = count / biL;
1092 v1 = count & (biL - 1);
1093
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001094 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001096
Paul Bakker5121ce52009-01-03 21:22:43 +00001097 /*
1098 * shift by count / limb_size
1099 */
1100 if( v0 > 0 )
1101 {
1102 for( i = 0; i < X->n - v0; i++ )
1103 X->p[i] = X->p[i + v0];
1104
1105 for( ; i < X->n; i++ )
1106 X->p[i] = 0;
1107 }
1108
1109 /*
1110 * shift by count % limb_size
1111 */
1112 if( v1 > 0 )
1113 {
Paul Bakker23986e52011-04-24 08:57:21 +00001114 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001115 {
Paul Bakker23986e52011-04-24 08:57:21 +00001116 r1 = X->p[i - 1] << (biL - v1);
1117 X->p[i - 1] >>= v1;
1118 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001119 r0 = r1;
1120 }
1121 }
1122
1123 return( 0 );
1124}
1125
1126/*
1127 * Compare unsigned values
1128 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001130{
Paul Bakker23986e52011-04-24 08:57:21 +00001131 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001132 MPI_VALIDATE_RET( X != NULL );
1133 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001134
Paul Bakker23986e52011-04-24 08:57:21 +00001135 for( i = X->n; i > 0; i-- )
1136 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001137 break;
1138
Paul Bakker23986e52011-04-24 08:57:21 +00001139 for( j = Y->n; j > 0; j-- )
1140 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001141 break;
1142
Paul Bakker23986e52011-04-24 08:57:21 +00001143 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001144 return( 0 );
1145
1146 if( i > j ) return( 1 );
1147 if( j > i ) return( -1 );
1148
Paul Bakker23986e52011-04-24 08:57:21 +00001149 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001150 {
Paul Bakker23986e52011-04-24 08:57:21 +00001151 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1152 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001153 }
1154
1155 return( 0 );
1156}
1157
1158/*
1159 * Compare signed values
1160 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001161int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001162{
Paul Bakker23986e52011-04-24 08:57:21 +00001163 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001164 MPI_VALIDATE_RET( X != NULL );
1165 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
Paul Bakker23986e52011-04-24 08:57:21 +00001167 for( i = X->n; i > 0; i-- )
1168 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001169 break;
1170
Paul Bakker23986e52011-04-24 08:57:21 +00001171 for( j = Y->n; j > 0; j-- )
1172 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001173 break;
1174
Paul Bakker23986e52011-04-24 08:57:21 +00001175 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001176 return( 0 );
1177
1178 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001179 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001180
1181 if( X->s > 0 && Y->s < 0 ) return( 1 );
1182 if( Y->s > 0 && X->s < 0 ) return( -1 );
1183
Paul Bakker23986e52011-04-24 08:57:21 +00001184 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 {
Paul Bakker23986e52011-04-24 08:57:21 +00001186 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1187 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001188 }
1189
1190 return( 0 );
1191}
1192
Janos Follath3f6f0e42019-10-14 09:09:32 +01001193/** Decide if an integer is less than the other, without branches.
1194 *
1195 * \param x First integer.
1196 * \param y Second integer.
1197 *
1198 * \return 1 if \p x is less than \p y, 0 otherwise
1199 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001200static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1201 const mbedtls_mpi_uint y )
Janos Follathee6abce2019-09-05 14:47:19 +01001202{
1203 mbedtls_mpi_uint ret;
1204 mbedtls_mpi_uint cond;
1205
1206 /*
1207 * Check if the most significant bits (MSB) of the operands are different.
1208 */
1209 cond = ( x ^ y );
1210 /*
1211 * If the MSB are the same then the difference x-y will be negative (and
1212 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1213 */
1214 ret = ( x - y ) & ~cond;
1215 /*
1216 * If the MSB are different, then the operand with the MSB of 1 is the
1217 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1218 * the MSB of y is 0.)
1219 */
1220 ret |= y & cond;
1221
1222
Janos Follatha0f732b2019-10-14 08:59:14 +01001223 ret = ret >> ( biL - 1 );
Janos Follathee6abce2019-09-05 14:47:19 +01001224
Janos Follath67ce6472019-10-29 15:08:46 +00001225 return (unsigned) ret;
Janos Follathee6abce2019-09-05 14:47:19 +01001226}
1227
1228/*
1229 * Compare signed values in constant time
1230 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001231int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1232 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001233{
1234 size_t i;
Janos Follathbb5147f2019-10-28 12:23:18 +00001235 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath5e614ce2019-10-28 12:31:34 +00001236 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathee6abce2019-09-05 14:47:19 +01001237
1238 MPI_VALIDATE_RET( X != NULL );
1239 MPI_VALIDATE_RET( Y != NULL );
1240 MPI_VALIDATE_RET( ret != NULL );
1241
1242 if( X->n != Y->n )
1243 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1244
1245 /*
Janos Follath73ba9ec2019-10-28 12:12:15 +00001246 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1247 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathee6abce2019-09-05 14:47:19 +01001248 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001249 X_is_negative = ( X->s & 2 ) >> 1;
1250 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath0e5532d2019-10-11 14:21:53 +01001251
1252 /*
1253 * If the signs are different, then the positive operand is the bigger.
Janos Follath5e614ce2019-10-28 12:31:34 +00001254 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1255 * is false if X is positive (X_is_negative == 0).
Janos Follath0e5532d2019-10-11 14:21:53 +01001256 */
Janos Follath5e614ce2019-10-28 12:31:34 +00001257 cond = ( X_is_negative ^ Y_is_negative );
1258 *ret = cond & X_is_negative;
Janos Follath0e5532d2019-10-11 14:21:53 +01001259
1260 /*
Janos Follathbb5147f2019-10-28 12:23:18 +00001261 * This is a constant-time function. We might have the result, but we still
Janos Follath0e5532d2019-10-11 14:21:53 +01001262 * need to go through the loop. Record if we have the result already.
1263 */
Janos Follathee6abce2019-09-05 14:47:19 +01001264 done = cond;
1265
1266 for( i = X->n; i > 0; i-- )
1267 {
1268 /*
Janos Follath30702422019-11-05 12:24:52 +00001269 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1270 * X and Y are negative.
Janos Follath0e5532d2019-10-11 14:21:53 +01001271 *
1272 * Again even if we can make a decision, we just mark the result and
1273 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001274 */
Janos Follath30702422019-11-05 12:24:52 +00001275 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1276 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc50e6d52019-10-28 12:37:21 +00001277 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001278
1279 /*
Janos Follath30702422019-11-05 12:24:52 +00001280 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1281 * X and Y are positive.
Janos Follath0e5532d2019-10-11 14:21:53 +01001282 *
1283 * Again even if we can make a decision, we just mark the result and
1284 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001285 */
Janos Follath30702422019-11-05 12:24:52 +00001286 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1287 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc50e6d52019-10-28 12:37:21 +00001288 done |= cond;
Janos Follathee6abce2019-09-05 14:47:19 +01001289 }
1290
1291 return( 0 );
1292}
1293
Paul Bakker5121ce52009-01-03 21:22:43 +00001294/*
1295 * Compare signed values
1296 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001297int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001298{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299 mbedtls_mpi Y;
1300 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001301 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001302
1303 *p = ( z < 0 ) ? -z : z;
1304 Y.s = ( z < 0 ) ? -1 : 1;
1305 Y.n = 1;
1306 Y.p = p;
1307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001308 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001309}
1310
1311/*
1312 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1313 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001315{
Janos Follath24eed8d2019-11-22 13:21:35 +00001316 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001317 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001318 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001319 MPI_VALIDATE_RET( X != NULL );
1320 MPI_VALIDATE_RET( A != NULL );
1321 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001322
1323 if( X == B )
1324 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001325 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001326 }
1327
1328 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001330
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001331 /*
1332 * X should always be positive as a result of unsigned additions.
1333 */
1334 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001335
Paul Bakker23986e52011-04-24 08:57:21 +00001336 for( j = B->n; j > 0; j-- )
1337 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 break;
1339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001341
1342 o = B->p; p = X->p; c = 0;
1343
Janos Follath6c922682015-10-30 17:43:11 +01001344 /*
1345 * tmp is used because it might happen that p == o
1346 */
Paul Bakker23986e52011-04-24 08:57:21 +00001347 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 {
Janos Follath6c922682015-10-30 17:43:11 +01001349 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001350 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001351 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001352 }
1353
1354 while( c != 0 )
1355 {
1356 if( i >= X->n )
1357 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001359 p = X->p + i;
1360 }
1361
Paul Bakker2d319fd2012-09-16 21:34:26 +00001362 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001363 }
1364
1365cleanup:
1366
1367 return( ret );
1368}
1369
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001370/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001371 * Helper for mbedtls_mpi subtraction.
1372 *
1373 * Calculate d - s where d and s have the same size.
1374 * This function operates modulo (2^ciL)^n and returns the carry
1375 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1376 *
1377 * \param n Number of limbs of \p d and \p s.
1378 * \param[in,out] d On input, the left operand.
1379 * On output, the result of the subtraction:
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001380 * \param[in] s The right operand.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001381 *
1382 * \return 1 if `d < s`.
1383 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 */
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001385static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1386 mbedtls_mpi_uint *d,
1387 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388{
Paul Bakker23986e52011-04-24 08:57:21 +00001389 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001391
1392 for( i = c = 0; i < n; i++, s++, d++ )
1393 {
1394 z = ( *d < c ); *d -= c;
1395 c = ( *d < *s ) + z; *d -= *s;
1396 }
1397
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001398 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001399}
1400
1401/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001402 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001403 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001404int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001405{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 mbedtls_mpi TB;
Janos Follath24eed8d2019-11-22 13:21:35 +00001407 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001408 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001409 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001410 MPI_VALIDATE_RET( X != NULL );
1411 MPI_VALIDATE_RET( A != NULL );
1412 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415
1416 if( X == B )
1417 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001419 B = &TB;
1420 }
1421
1422 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001424
Paul Bakker1ef7a532009-06-20 10:50:55 +00001425 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001426 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001427 */
1428 X->s = 1;
1429
Paul Bakker5121ce52009-01-03 21:22:43 +00001430 ret = 0;
1431
Paul Bakker23986e52011-04-24 08:57:21 +00001432 for( n = B->n; n > 0; n-- )
1433 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 break;
Gilles Peskinec8a91772021-01-27 22:30:43 +01001435 if( n > A->n )
1436 {
1437 /* B >= (2^ciL)^n > A */
1438 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1439 goto cleanup;
1440 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001441
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001442 carry = mpi_sub_hlp( n, X->p, B->p );
1443 if( carry != 0 )
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001444 {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001445 /* Propagate the carry to the first nonzero limb of X. */
1446 for( ; n < X->n && X->p[n] == 0; n++ )
1447 --X->p[n];
1448 /* If we ran out of space for the carry, it means that the result
1449 * is negative. */
1450 if( n == X->n )
Gilles Peskine89b41302020-07-23 01:16:46 +02001451 {
1452 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1453 goto cleanup;
1454 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001455 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001456 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001457
1458cleanup:
1459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001461
1462 return( ret );
1463}
1464
1465/*
1466 * Signed addition: X = A + B
1467 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001469{
Hanno Becker73d7d792018-12-11 10:35:51 +00001470 int ret, s;
1471 MPI_VALIDATE_RET( X != NULL );
1472 MPI_VALIDATE_RET( A != NULL );
1473 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001474
Hanno Becker73d7d792018-12-11 10:35:51 +00001475 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001476 if( A->s * B->s < 0 )
1477 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001479 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001481 X->s = s;
1482 }
1483 else
1484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001486 X->s = -s;
1487 }
1488 }
1489 else
1490 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001492 X->s = s;
1493 }
1494
1495cleanup:
1496
1497 return( ret );
1498}
1499
1500/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001501 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001504{
Hanno Becker73d7d792018-12-11 10:35:51 +00001505 int ret, s;
1506 MPI_VALIDATE_RET( X != NULL );
1507 MPI_VALIDATE_RET( A != NULL );
1508 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001509
Hanno Becker73d7d792018-12-11 10:35:51 +00001510 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001511 if( A->s * B->s > 0 )
1512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001516 X->s = s;
1517 }
1518 else
1519 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 X->s = -s;
1522 }
1523 }
1524 else
1525 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001526 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001527 X->s = s;
1528 }
1529
1530cleanup:
1531
1532 return( ret );
1533}
1534
1535/*
1536 * Signed addition: X = A + b
1537 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001539{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 mbedtls_mpi _B;
1541 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001542 MPI_VALIDATE_RET( X != NULL );
1543 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001544
1545 p[0] = ( b < 0 ) ? -b : b;
1546 _B.s = ( b < 0 ) ? -1 : 1;
1547 _B.n = 1;
1548 _B.p = p;
1549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001551}
1552
1553/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001554 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001555 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001557{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 mbedtls_mpi _B;
1559 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001560 MPI_VALIDATE_RET( X != NULL );
1561 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001562
1563 p[0] = ( b < 0 ) ? -b : b;
1564 _B.s = ( b < 0 ) ? -1 : 1;
1565 _B.n = 1;
1566 _B.p = p;
1567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001569}
1570
1571/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001573 */
1574static
1575#if defined(__APPLE__) && defined(__arm__)
1576/*
1577 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1578 * appears to need this to prevent bad ARM code generation at -O3.
1579 */
1580__attribute__ ((noinline))
1581#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582void 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 +00001583{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001585
1586#if defined(MULADDC_HUIT)
1587 for( ; i >= 8; i -= 8 )
1588 {
1589 MULADDC_INIT
1590 MULADDC_HUIT
1591 MULADDC_STOP
1592 }
1593
1594 for( ; i > 0; i-- )
1595 {
1596 MULADDC_INIT
1597 MULADDC_CORE
1598 MULADDC_STOP
1599 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001600#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001601 for( ; i >= 16; i -= 16 )
1602 {
1603 MULADDC_INIT
1604 MULADDC_CORE MULADDC_CORE
1605 MULADDC_CORE MULADDC_CORE
1606 MULADDC_CORE MULADDC_CORE
1607 MULADDC_CORE MULADDC_CORE
1608
1609 MULADDC_CORE MULADDC_CORE
1610 MULADDC_CORE MULADDC_CORE
1611 MULADDC_CORE MULADDC_CORE
1612 MULADDC_CORE MULADDC_CORE
1613 MULADDC_STOP
1614 }
1615
1616 for( ; i >= 8; i -= 8 )
1617 {
1618 MULADDC_INIT
1619 MULADDC_CORE MULADDC_CORE
1620 MULADDC_CORE MULADDC_CORE
1621
1622 MULADDC_CORE MULADDC_CORE
1623 MULADDC_CORE MULADDC_CORE
1624 MULADDC_STOP
1625 }
1626
1627 for( ; i > 0; i-- )
1628 {
1629 MULADDC_INIT
1630 MULADDC_CORE
1631 MULADDC_STOP
1632 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001633#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
1635 t++;
1636
1637 do {
1638 *d += c; c = ( *d < c ); d++;
1639 }
1640 while( c != 0 );
1641}
1642
1643/*
1644 * Baseline multiplication: X = A * B (HAC 14.12)
1645 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001646int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001647{
Janos Follath24eed8d2019-11-22 13:21:35 +00001648 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001649 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001650 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001651 MPI_VALIDATE_RET( X != NULL );
1652 MPI_VALIDATE_RET( A != NULL );
1653 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1658 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
Paul Bakker23986e52011-04-24 08:57:21 +00001660 for( i = A->n; i > 0; i-- )
1661 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001662 break;
1663
Paul Bakker23986e52011-04-24 08:57:21 +00001664 for( j = B->n; j > 0; j-- )
1665 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001666 break;
1667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001671 for( ; j > 0; j-- )
1672 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
1674 X->s = A->s * B->s;
1675
1676cleanup:
1677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001679
1680 return( ret );
1681}
1682
1683/*
1684 * Baseline multiplication: X = A * b
1685 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001687{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 mbedtls_mpi _B;
1689 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001690 MPI_VALIDATE_RET( X != NULL );
1691 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
1693 _B.s = 1;
1694 _B.n = 1;
1695 _B.p = p;
1696 p[0] = b;
1697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001699}
1700
1701/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001702 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1703 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001704 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001705static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1706 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001707{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001708#if defined(MBEDTLS_HAVE_UDBL)
1709 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001710#else
Simon Butcher9803d072016-01-03 00:24:34 +00001711 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1712 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001713 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1714 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001715 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001716#endif
1717
Simon Butcher15b15d12015-11-26 19:35:03 +00001718 /*
1719 * Check for overflow
1720 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001721 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001722 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001723 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001724
Simon Butcherf5ba0452015-12-27 23:01:55 +00001725 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001726 }
1727
1728#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001729 dividend = (mbedtls_t_udbl) u1 << biL;
1730 dividend |= (mbedtls_t_udbl) u0;
1731 quotient = dividend / d;
1732 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1733 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1734
1735 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001736 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001737
1738 return (mbedtls_mpi_uint) quotient;
1739#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001740
1741 /*
1742 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1743 * Vol. 2 - Seminumerical Algorithms, Knuth
1744 */
1745
1746 /*
1747 * Normalize the divisor, d, and dividend, u0, u1
1748 */
1749 s = mbedtls_clz( d );
1750 d = d << s;
1751
1752 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001753 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001754 u0 = u0 << s;
1755
1756 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001757 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001758
1759 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001760 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001761
1762 /*
1763 * Find the first quotient and remainder
1764 */
1765 q1 = u1 / d1;
1766 r0 = u1 - d1 * q1;
1767
1768 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1769 {
1770 q1 -= 1;
1771 r0 += d1;
1772
1773 if ( r0 >= radix ) break;
1774 }
1775
Simon Butcherf5ba0452015-12-27 23:01:55 +00001776 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001777 q0 = rAX / d1;
1778 r0 = rAX - q0 * d1;
1779
1780 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1781 {
1782 q0 -= 1;
1783 r0 += d1;
1784
1785 if ( r0 >= radix ) break;
1786 }
1787
1788 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001789 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001790
1791 quotient = q1 * radix + q0;
1792
1793 return quotient;
1794#endif
1795}
1796
1797/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001798 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001799 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001800int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1801 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001802{
Janos Follath24eed8d2019-11-22 13:21:35 +00001803 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001804 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001806 mbedtls_mpi_uint TP2[3];
Hanno Becker73d7d792018-12-11 10:35:51 +00001807 MPI_VALIDATE_RET( A != NULL );
1808 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1811 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001814 mbedtls_mpi_init( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001815 /*
1816 * Avoid dynamic memory allocations for constant-size T2.
1817 *
1818 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1819 * so nobody increase the size of the MPI and we're safe to use an on-stack
1820 * buffer.
1821 */
Alexander K35d6d462019-10-31 14:46:45 +03001822 T2.s = 1;
Alexander Kd19a1932019-11-01 18:20:42 +03001823 T2.n = sizeof( TP2 ) / sizeof( *TP2 );
1824 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001827 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1829 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 return( 0 );
1831 }
1832
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1834 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001835 X.s = Y.s = 1;
1836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1838 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1839 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001841 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001842 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 {
1844 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1846 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 }
1848 else k = 0;
1849
1850 n = X.n - 1;
1851 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 {
1856 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
1861 for( i = n; i > t ; i-- )
1862 {
1863 if( X.p[i] >= Y.p[t] )
1864 Z.p[i - t - 1] = ~0;
1865 else
1866 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001867 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1868 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001869 }
1870
Alexander K35d6d462019-10-31 14:46:45 +03001871 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1872 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1873 T2.p[2] = X.p[i];
1874
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 Z.p[i - t - 1]++;
1876 do
1877 {
1878 Z.p[i - t - 1]--;
1879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001881 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001882 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001884 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1888 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1889 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001892 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1894 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1895 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896 Z.p[i - t - 1]--;
1897 }
1898 }
1899
1900 if( Q != NULL )
1901 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001903 Q->s = A->s * B->s;
1904 }
1905
1906 if( R != NULL )
1907 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001908 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001909 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 R->s = 1;
1914 }
1915
1916cleanup:
1917
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001918 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Alexander K35d6d462019-10-31 14:46:45 +03001919 mbedtls_mpi_free( &T1 );
Alexander Kd19a1932019-11-01 18:20:42 +03001920 mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001921
1922 return( ret );
1923}
1924
1925/*
1926 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001927 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001928int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1929 const mbedtls_mpi *A,
1930 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001931{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 mbedtls_mpi _B;
1933 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001934 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935
1936 p[0] = ( b < 0 ) ? -b : b;
1937 _B.s = ( b < 0 ) ? -1 : 1;
1938 _B.n = 1;
1939 _B.p = p;
1940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942}
1943
1944/*
1945 * Modulo: R = A mod B
1946 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001948{
Janos Follath24eed8d2019-11-22 13:21:35 +00001949 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker73d7d792018-12-11 10:35:51 +00001950 MPI_VALIDATE_RET( R != NULL );
1951 MPI_VALIDATE_RET( A != NULL );
1952 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1955 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1960 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1963 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
1965cleanup:
1966
1967 return( ret );
1968}
1969
1970/*
1971 * Modulo: r = A mod b
1972 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001974{
Paul Bakker23986e52011-04-24 08:57:21 +00001975 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001977 MPI_VALIDATE_RET( r != NULL );
1978 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
1980 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
1983 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
1986 /*
1987 * handle trivial cases
1988 */
1989 if( b == 1 )
1990 {
1991 *r = 0;
1992 return( 0 );
1993 }
1994
1995 if( b == 2 )
1996 {
1997 *r = A->p[0] & 1;
1998 return( 0 );
1999 }
2000
2001 /*
2002 * general case
2003 */
Paul Bakker23986e52011-04-24 08:57:21 +00002004 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 {
Paul Bakker23986e52011-04-24 08:57:21 +00002006 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00002007 y = ( y << biH ) | ( x >> biH );
2008 z = y / b;
2009 y -= z * b;
2010
2011 x <<= biH;
2012 y = ( y << biH ) | ( x >> biH );
2013 z = y / b;
2014 y -= z * b;
2015 }
2016
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002017 /*
2018 * If A is negative, then the current y represents a negative value.
2019 * Flipping it to the positive side.
2020 */
2021 if( A->s < 0 && y != 0 )
2022 y = b - y;
2023
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 *r = y;
2025
2026 return( 0 );
2027}
2028
2029/*
2030 * Fast Montgomery initialization (thanks to Tom St Denis)
2031 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002033{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002035 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
2037 x = m0;
2038 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002040 for( i = biL; i >= 8; i /= 2 )
2041 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002042
2043 *mm = ~x + 1;
2044}
2045
Gilles Peskine2a82f722020-06-04 15:00:49 +02002046/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2047 *
2048 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02002049 * It must have at least as many limbs as N
2050 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02002051 * On successful completion, A contains the result of
2052 * the multiplication A * B * R^-1 mod N where
2053 * R = (2^ciL)^n.
2054 * \param[in] B One of the numbers to multiply.
2055 * It must be nonzero and must not have more limbs than N
2056 * (B->n <= N->n).
2057 * \param[in] N The modulo. N must be odd.
2058 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2059 * This is -N^-1 mod 2^ciL.
2060 * \param[in,out] T A bignum for temporary storage.
2061 * It must be at least twice the limb size of N plus 2
2062 * (T->n >= 2 * (N->n + 1)).
2063 * Its initial content is unused and
2064 * its final content is indeterminate.
2065 * Note that unlike the usual convention in the library
2066 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002067 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002068static 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 +02002069 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002070{
Paul Bakker23986e52011-04-24 08:57:21 +00002071 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002073
2074 memset( T->p, 0, T->n * ciL );
2075
2076 d = T->p;
2077 n = N->n;
2078 m = ( B->n < n ) ? B->n : n;
2079
2080 for( i = 0; i < n; i++ )
2081 {
2082 /*
2083 * T = (T + u0*B + u1*N) / 2^biL
2084 */
2085 u0 = A->p[i];
2086 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2087
2088 mpi_mul_hlp( m, B->p, d, u0 );
2089 mpi_mul_hlp( n, N->p, d, u1 );
2090
2091 *d++ = u0; d[n + 1] = 0;
2092 }
2093
Gilles Peskine221626f2020-06-08 22:37:50 +02002094 /* At this point, d is either the desired result or the desired result
2095 * plus N. We now potentially subtract N, avoiding leaking whether the
2096 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002097
Gilles Peskine221626f2020-06-08 22:37:50 +02002098 /* Copy the n least significant limbs of d to A, so that
2099 * A = d if d < N (recall that N has n limbs). */
2100 memcpy( A->p, d, n * ciL );
Gilles Peskine09ec10a2020-06-09 10:39:38 +02002101 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02002102 * do the calculation without using conditional tests. */
2103 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02002104 d[n] += 1;
Gilles Peskinec097e9e2020-06-08 21:58:22 +02002105 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskine221626f2020-06-08 22:37:50 +02002106 /* If d0 < N then d < (2^biL)^n
2107 * so d[n] == 0 and we want to keep A as it is.
2108 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2109 * so d[n] == 1 and we want to set A to the result of the subtraction
2110 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2111 * This exactly corresponds to a conditional assignment. */
2112 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002113}
2114
2115/*
2116 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002117 *
2118 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002119 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002120static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2121 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002122{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 mbedtls_mpi_uint z = 1;
2124 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
Paul Bakker8ddb6452013-02-27 14:56:33 +01002126 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002127 U.p = &z;
2128
Gilles Peskine4e91d472020-06-04 20:55:15 +02002129 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002130}
2131
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002132/*
2133 * Constant-flow boolean "equal" comparison:
2134 * return x == y
2135 *
2136 * This function can be used to write constant-time code by replacing branches
2137 * with bit operations - it can be used in conjunction with
2138 * mbedtls_ssl_cf_mask_from_bit().
2139 *
2140 * This function is implemented without using comparison operators, as those
2141 * might be translated to branches by some compilers on some platforms.
2142 */
2143static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2144{
2145 /* diff = 0 if x == y, non-zero otherwise */
2146 const size_t diff = x ^ y;
2147
2148 /* MSVC has a warning about unary minus on unsigned integer types,
2149 * but this is well-defined and precisely what we want to do here. */
2150#if defined(_MSC_VER)
2151#pragma warning( push )
2152#pragma warning( disable : 4146 )
2153#endif
2154
2155 /* diff_msb's most significant bit is equal to x != y */
2156 const size_t diff_msb = ( diff | -diff );
2157
2158#if defined(_MSC_VER)
2159#pragma warning( pop )
2160#endif
2161
2162 /* diff1 = (x != y) ? 1 : 0 */
2163 const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2164
2165 return( 1 ^ diff1 );
2166}
2167
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002168/**
2169 * Select an MPI from a table without leaking the index.
2170 *
2171 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2172 * reads the entire table in order to avoid leaking the value of idx to an
2173 * attacker able to observe memory access patterns.
2174 *
2175 * \param[out] R Where to write the selected MPI.
2176 * \param[in] T The table to read from.
2177 * \param[in] T_size The number of elements in the table.
2178 * \param[in] idx The index of the element to select;
2179 * this must satisfy 0 <= idx < T_size.
2180 *
2181 * \return \c 0 on success, or a negative error code.
2182 */
2183static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2184{
2185 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2186
2187 for( size_t i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02002188 {
2189 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
2190 mbedtls_mpi_cf_bool_eq( i, idx ) ) );
2191 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002192
2193cleanup:
2194 return( ret );
2195}
2196
Paul Bakker5121ce52009-01-03 21:22:43 +00002197/*
2198 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2199 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002200int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2201 const mbedtls_mpi *E, const mbedtls_mpi *N,
2202 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002203{
Janos Follath24eed8d2019-11-22 13:21:35 +00002204 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002205 size_t wbits, wsize, one = 1;
2206 size_t i, j, nblimbs;
2207 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002209 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002210 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002211
Hanno Becker73d7d792018-12-11 10:35:51 +00002212 MPI_VALIDATE_RET( X != NULL );
2213 MPI_VALIDATE_RET( A != NULL );
2214 MPI_VALIDATE_RET( E != NULL );
2215 MPI_VALIDATE_RET( N != NULL );
2216
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002217 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2221 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002222
Chris Jones9246d042020-11-25 15:12:39 +00002223 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2224 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2225 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2226
Paul Bakkerf6198c12012-05-16 08:02:29 +00002227 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002228 * Init temps and window size
2229 */
2230 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2232 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002233 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002234 memset( W, 0, sizeof( W ) );
2235
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002236 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
2238 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2239 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2240
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002241#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2243 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002244#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002245
Paul Bakker5121ce52009-01-03 21:22:43 +00002246 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2248 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2249 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
2251 /*
Paul Bakker50546922012-05-19 08:40:49 +00002252 * Compensate for negative A (and correct at the end)
2253 */
2254 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002255 if( neg )
2256 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002258 Apos.s = 1;
2259 A = &Apos;
2260 }
2261
2262 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002263 * If 1st call, pre-compute R^2 mod N
2264 */
2265 if( _RR == NULL || _RR->p == NULL )
2266 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2268 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2269 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002270
2271 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273 }
2274 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
2277 /*
2278 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2281 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002282 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
Gilles Peskine4e91d472020-06-04 20:55:15 +02002285 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
2287 /*
2288 * X = R^2 * R^-1 mod N = R mod N
2289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskine4e91d472020-06-04 20:55:15 +02002291 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
2293 if( wsize > 1 )
2294 {
2295 /*
2296 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2297 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002298 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2301 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002302
2303 for( i = 0; i < wsize - 1; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002304 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002305
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 /*
2307 * W[i] = W[i - 1] * W[1]
2308 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002309 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002310 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2312 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
Gilles Peskine4e91d472020-06-04 20:55:15 +02002314 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 }
2316 }
2317
2318 nblimbs = E->n;
2319 bufsize = 0;
2320 nbits = 0;
2321 wbits = 0;
2322 state = 0;
2323
2324 while( 1 )
2325 {
2326 if( bufsize == 0 )
2327 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002328 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 break;
2330
Paul Bakker0d7702c2013-10-29 16:18:35 +01002331 nblimbs--;
2332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002334 }
2335
2336 bufsize--;
2337
2338 ei = (E->p[nblimbs] >> bufsize) & 1;
2339
2340 /*
2341 * skip leading 0s
2342 */
2343 if( ei == 0 && state == 0 )
2344 continue;
2345
2346 if( ei == 0 && state == 1 )
2347 {
2348 /*
2349 * out of window, square X
2350 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002351 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002352 continue;
2353 }
2354
2355 /*
2356 * add ei to current window
2357 */
2358 state = 2;
2359
2360 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002361 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002362
2363 if( nbits == wsize )
2364 {
2365 /*
2366 * X = X^wsize R^-1 mod N
2367 */
2368 for( i = 0; i < wsize; i++ )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002369 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
2371 /*
2372 * X = X * W[wbits] R^-1 mod N
2373 */
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002374 MBEDTLS_MPI_CHK( mpi_select( &WW, W, 1 << wsize, wbits ) );
2375 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002376
2377 state--;
2378 nbits = 0;
2379 wbits = 0;
2380 }
2381 }
2382
2383 /*
2384 * process the remaining bits
2385 */
2386 for( i = 0; i < nbits; i++ )
2387 {
Gilles Peskine4e91d472020-06-04 20:55:15 +02002388 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002389
2390 wbits <<= 1;
2391
Paul Bakker66d5d072014-06-17 16:39:18 +02002392 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskine4e91d472020-06-04 20:55:15 +02002393 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 }
2395
2396 /*
2397 * X = A^E * R * R^-1 mod N = A^E mod N
2398 */
Gilles Peskine4e91d472020-06-04 20:55:15 +02002399 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002400
Hanno Beckera4af1c42017-04-18 09:07:45 +01002401 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002402 {
2403 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002404 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002405 }
2406
Paul Bakker5121ce52009-01-03 21:22:43 +00002407cleanup:
2408
Paul Bakker66d5d072014-06-17 16:39:18 +02002409 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01002413 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002414
Paul Bakker75a28602014-03-31 12:08:17 +02002415 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002417
2418 return( ret );
2419}
2420
Paul Bakker5121ce52009-01-03 21:22:43 +00002421/*
2422 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002425{
Janos Follath24eed8d2019-11-22 13:21:35 +00002426 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002427 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002428 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002429
Hanno Becker73d7d792018-12-11 10:35:51 +00002430 MPI_VALIDATE_RET( G != NULL );
2431 MPI_VALIDATE_RET( A != NULL );
2432 MPI_VALIDATE_RET( B != NULL );
2433
Alexander Ke8ad49f2019-08-16 16:16:07 +03002434 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2437 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002438
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002439 lz = mbedtls_mpi_lsb( &TA );
2440 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002441
Paul Bakker66d5d072014-06-17 16:39:18 +02002442 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002443 lz = lzt;
2444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2446 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002447
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 TA.s = TB.s = 1;
2449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002451 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2453 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002456 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2458 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002459 }
2460 else
2461 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002462 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2463 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002464 }
2465 }
2466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002467 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2468 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002469
2470cleanup:
2471
Alexander Ke8ad49f2019-08-16 16:16:07 +03002472 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002473
2474 return( ret );
2475}
2476
Paul Bakker33dc46b2014-04-30 16:11:39 +02002477/*
2478 * Fill X with size bytes of random.
2479 *
2480 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002481 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002482 * deterministic, eg for tests).
2483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002485 int (*f_rng)(void *, unsigned char *, size_t),
2486 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002487{
Janos Follath24eed8d2019-11-22 13:21:35 +00002488 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker6dab6202019-01-02 16:42:29 +00002489 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002490 size_t const overhead = ( limbs * ciL ) - size;
2491 unsigned char *Xp;
2492
Hanno Becker8ce11a32018-12-19 16:18:52 +00002493 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002494 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002495
Hanno Beckerda1655a2017-10-18 14:21:44 +01002496 /* Ensure that target MPI has exactly the necessary number of limbs */
2497 if( X->n != limbs )
2498 {
2499 mbedtls_mpi_free( X );
2500 mbedtls_mpi_init( X );
2501 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2502 }
2503 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002504
Hanno Beckerda1655a2017-10-18 14:21:44 +01002505 Xp = (unsigned char*) X->p;
Gilles Peskine436400e2020-11-25 16:15:14 +01002506 MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002507
Hanno Becker2be8a552018-10-25 12:40:09 +01002508 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002509
2510cleanup:
2511 return( ret );
2512}
2513
Paul Bakker5121ce52009-01-03 21:22:43 +00002514/*
2515 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2516 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002518{
Janos Follath24eed8d2019-11-22 13:21:35 +00002519 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002520 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002521 MPI_VALIDATE_RET( X != NULL );
2522 MPI_VALIDATE_RET( A != NULL );
2523 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002524
Hanno Becker4bcb4912017-04-18 15:49:39 +01002525 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002528 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2529 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2530 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002534 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002535 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002536 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002537 goto cleanup;
2538 }
2539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2541 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2542 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2543 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2546 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2547 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2548 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
2550 do
2551 {
2552 while( ( TU.p[0] & 1 ) == 0 )
2553 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002555
2556 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2557 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002558 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2559 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002560 }
2561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2563 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002564 }
2565
2566 while( ( TV.p[0] & 1 ) == 0 )
2567 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002568 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002569
2570 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2571 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2573 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002574 }
2575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2577 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002578 }
2579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002580 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002581 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2583 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2584 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002585 }
2586 else
2587 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2589 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2590 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591 }
2592 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2596 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2599 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002602
2603cleanup:
2604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2606 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2607 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002608
2609 return( ret );
2610}
2611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002612#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002613
Paul Bakker5121ce52009-01-03 21:22:43 +00002614static const int small_prime[] =
2615{
2616 3, 5, 7, 11, 13, 17, 19, 23,
2617 29, 31, 37, 41, 43, 47, 53, 59,
2618 61, 67, 71, 73, 79, 83, 89, 97,
2619 101, 103, 107, 109, 113, 127, 131, 137,
2620 139, 149, 151, 157, 163, 167, 173, 179,
2621 181, 191, 193, 197, 199, 211, 223, 227,
2622 229, 233, 239, 241, 251, 257, 263, 269,
2623 271, 277, 281, 283, 293, 307, 311, 313,
2624 317, 331, 337, 347, 349, 353, 359, 367,
2625 373, 379, 383, 389, 397, 401, 409, 419,
2626 421, 431, 433, 439, 443, 449, 457, 461,
2627 463, 467, 479, 487, 491, 499, 503, 509,
2628 521, 523, 541, 547, 557, 563, 569, 571,
2629 577, 587, 593, 599, 601, 607, 613, 617,
2630 619, 631, 641, 643, 647, 653, 659, 661,
2631 673, 677, 683, 691, 701, 709, 719, 727,
2632 733, 739, 743, 751, 757, 761, 769, 773,
2633 787, 797, 809, 811, 821, 823, 827, 829,
2634 839, 853, 857, 859, 863, 877, 881, 883,
2635 887, 907, 911, 919, 929, 937, 941, 947,
2636 953, 967, 971, 977, 983, 991, 997, -103
2637};
2638
2639/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002640 * Small divisors test (X must be positive)
2641 *
2642 * Return values:
2643 * 0: no small factor (possible prime, more tests needed)
2644 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002645 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002646 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002647 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002648static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002649{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002650 int ret = 0;
2651 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002652 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002653
Paul Bakker5121ce52009-01-03 21:22:43 +00002654 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002655 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002656
2657 for( i = 0; small_prime[i] > 0; i++ )
2658 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002659 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002660 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002662 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002663
2664 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002666 }
2667
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002668cleanup:
2669 return( ret );
2670}
2671
2672/*
2673 * Miller-Rabin pseudo-primality test (HAC 4.24)
2674 */
Janos Follathda31fa12018-09-03 14:45:23 +01002675static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002676 int (*f_rng)(void *, unsigned char *, size_t),
2677 void *p_rng )
2678{
Pascal Junodb99183d2015-03-11 16:49:45 +01002679 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002680 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002681 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002682
Hanno Becker8ce11a32018-12-19 16:18:52 +00002683 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002684 MPI_VALIDATE_RET( f_rng != NULL );
2685
2686 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2687 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002688 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002689
Paul Bakker5121ce52009-01-03 21:22:43 +00002690 /*
2691 * W = |X| - 1
2692 * R = W >> lsb( W )
2693 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2695 s = mbedtls_mpi_lsb( &W );
2696 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2697 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002698
Janos Follathda31fa12018-09-03 14:45:23 +01002699 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002700 {
2701 /*
2702 * pick a random A, 1 < A < |X| - 1
2703 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002704 count = 0;
2705 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002706 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002707
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002708 j = mbedtls_mpi_bitlen( &A );
2709 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002710 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002711 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002712 }
2713
2714 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002715 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2716 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002717 }
2718
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002719 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2720 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002721
2722 /*
2723 * A = A^R mod |X|
2724 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002727 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2728 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002729 continue;
2730
2731 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002732 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002733 {
2734 /*
2735 * A = A * A mod |X|
2736 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002737 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2738 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002740 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002741 break;
2742
2743 j++;
2744 }
2745
2746 /*
2747 * not prime if A != |X| - 1 or A == 1
2748 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002749 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2750 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002751 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002753 break;
2754 }
2755 }
2756
2757cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002758 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2759 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002760 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002761
2762 return( ret );
2763}
2764
2765/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002766 * Pseudo-primality test: small factors, then Miller-Rabin
2767 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002768int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2769 int (*f_rng)(void *, unsigned char *, size_t),
2770 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002771{
Janos Follath24eed8d2019-11-22 13:21:35 +00002772 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002773 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002774 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002775 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002776
2777 XX.s = 1;
2778 XX.n = X->n;
2779 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002780
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002781 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2782 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2783 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002786 return( 0 );
2787
2788 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2789 {
2790 if( ret == 1 )
2791 return( 0 );
2792
2793 return( ret );
2794 }
2795
Janos Follathda31fa12018-09-03 14:45:23 +01002796 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002797}
2798
Janos Follatha0b67c22018-09-18 14:48:23 +01002799#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002800/*
2801 * Pseudo-primality test, error probability 2^-80
2802 */
2803int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2804 int (*f_rng)(void *, unsigned char *, size_t),
2805 void *p_rng )
2806{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002807 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002808 MPI_VALIDATE_RET( f_rng != NULL );
2809
Janos Follatha0b67c22018-09-18 14:48:23 +01002810 /*
2811 * In the past our key generation aimed for an error rate of at most
2812 * 2^-80. Since this function is deprecated, aim for the same certainty
2813 * here as well.
2814 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002815 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002816}
Janos Follatha0b67c22018-09-18 14:48:23 +01002817#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002818
2819/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002820 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002821 *
Janos Follathf301d232018-08-14 13:34:01 +01002822 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2823 * be either 1024 bits or 1536 bits long, and flags must contain
2824 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002825 */
Janos Follath7c025a92018-08-14 11:08:41 +01002826int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002827 int (*f_rng)(void *, unsigned char *, size_t),
2828 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002829{
Jethro Beekman66689272018-02-14 19:24:10 -08002830#ifdef MBEDTLS_HAVE_INT64
2831// ceil(2^63.5)
2832#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2833#else
2834// ceil(2^31.5)
2835#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2836#endif
2837 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002838 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002839 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002840 mbedtls_mpi_uint r;
2841 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002842
Hanno Becker8ce11a32018-12-19 16:18:52 +00002843 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002844 MPI_VALIDATE_RET( f_rng != NULL );
2845
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002846 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2847 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002848
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002849 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002850
2851 n = BITS_TO_LIMBS( nbits );
2852
Janos Follathda31fa12018-09-03 14:45:23 +01002853 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2854 {
2855 /*
2856 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2857 */
2858 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2859 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2860 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2861 }
2862 else
2863 {
2864 /*
2865 * 2^-100 error probability, number of rounds computed based on HAC,
2866 * fact 4.48
2867 */
2868 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2869 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2870 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2871 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2872 }
2873
Jethro Beekman66689272018-02-14 19:24:10 -08002874 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002875 {
Jethro Beekman66689272018-02-14 19:24:10 -08002876 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2877 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2878 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2879
2880 k = n * biL;
2881 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2882 X->p[0] |= 1;
2883
Janos Follath7c025a92018-08-14 11:08:41 +01002884 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002885 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002886 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002888 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002889 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002890 }
Jethro Beekman66689272018-02-14 19:24:10 -08002891 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002892 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002893 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002894 * An necessary condition for Y and X = 2Y + 1 to be prime
2895 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2896 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002897 */
Jethro Beekman66689272018-02-14 19:24:10 -08002898
2899 X->p[0] |= 2;
2900
2901 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2902 if( r == 0 )
2903 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2904 else if( r == 1 )
2905 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2906
2907 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2908 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2909 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2910
2911 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002912 {
Jethro Beekman66689272018-02-14 19:24:10 -08002913 /*
2914 * First, check small factors for X and Y
2915 * before doing Miller-Rabin on any of them
2916 */
2917 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2918 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002919 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002920 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002921 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002922 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002923 goto cleanup;
2924
2925 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2926 goto cleanup;
2927
2928 /*
2929 * Next candidates. We want to preserve Y = (X-1) / 2 and
2930 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2931 * so up Y by 6 and X by 12.
2932 */
2933 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2934 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002935 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002936 }
2937 }
2938
2939cleanup:
2940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002941 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002942
2943 return( ret );
2944}
2945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002946#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002947
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002948#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002949
Paul Bakker23986e52011-04-24 08:57:21 +00002950#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002951
2952static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2953{
2954 { 693, 609, 21 },
2955 { 1764, 868, 28 },
2956 { 768454923, 542167814, 1 }
2957};
2958
Paul Bakker5121ce52009-01-03 21:22:43 +00002959/*
2960 * Checkup routine
2961 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002962int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002963{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002964 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002965 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002967 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2968 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002970 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002971 "EFE021C2645FD1DC586E69184AF4A31E" \
2972 "D5F53E93B5F123FA41680867BA110131" \
2973 "944FE7952E2517337780CB0DB80E61AA" \
2974 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002976 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002977 "B2E7EFD37075B9F03FF989C7C5051C20" \
2978 "34D2A323810251127E7BF8625A4F49A5" \
2979 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2980 "5B5C25763222FEFCCFC38B832366C29E" ) );
2981
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002982 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002983 "0066A198186C18C10B2F5ED9B522752A" \
2984 "9830B69916E535C8F047518A889A43A5" \
2985 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2986
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002987 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002989 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002990 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2991 "9E857EA95A03512E2BAE7391688D264A" \
2992 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2993 "8001B72E848A38CAE1C65F78E56ABDEF" \
2994 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2995 "ECF677152EF804370C1A305CAF3B5BF1" \
2996 "30879B56C61DE584A0F53A2447A51E" ) );
2997
2998 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002999 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003001 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003002 {
3003 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003004 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003005
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003006 ret = 1;
3007 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003008 }
3009
3010 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003011 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003013 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003015 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003016 "256567336059E52CAE22925474705F39A94" ) );
3017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003018 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003019 "6613F26162223DF488E9CD48CC132C7A" \
3020 "0AC93C701B001B092E4E5B9F73BCD27B" \
3021 "9EE50D0657C77F374E903CDFA4C642" ) );
3022
3023 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003024 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003025
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003026 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3027 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003028 {
3029 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003030 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003031
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003032 ret = 1;
3033 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003034 }
3035
3036 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003037 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003038
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003039 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003040
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003041 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003042 "36E139AEA55215609D2816998ED020BB" \
3043 "BD96C37890F65171D948E9BC7CBAA4D9" \
3044 "325D24D6A3C12710F10A09FA08AB87" ) );
3045
3046 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003047 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003049 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003050 {
3051 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003052 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003053
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003054 ret = 1;
3055 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003056 }
3057
3058 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003059 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003060
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003061 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003063 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003064 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3065 "C3DBA76456363A10869622EAC2DD84EC" \
3066 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3067
3068 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003069 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003071 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003072 {
3073 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003074 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003075
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003076 ret = 1;
3077 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003078 }
3079
3080 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003081 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003082
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003083 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003084 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003085
Paul Bakker66d5d072014-06-17 16:39:18 +02003086 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003087 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003088 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3089 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003091 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003093 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003094 {
3095 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003096 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003097
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003098 ret = 1;
3099 goto cleanup;
3100 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003101 }
3102
3103 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003104 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003105
Paul Bakker5121ce52009-01-03 21:22:43 +00003106cleanup:
3107
3108 if( ret != 0 && verbose != 0 )
Kenneth Soerensen518d4352020-04-01 17:22:45 +02003109 mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003111 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3112 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003113
3114 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003115 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003116
3117 return( ret );
3118}
3119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003120#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003122#endif /* MBEDTLS_BIGNUM_C */