blob: c553d0c5affee0ea30c6659bcd7ee0d45b056c08 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Paul Bakker5121ce52009-01-03 21:22:43 +000045 */
Simon Butcher15b15d12015-11-26 19:35:03 +000046
Paul Bakker5121ce52009-01-03 21:22:43 +000047/*
Simon Butcher15b15d12015-11-26 19:35:03 +000048 * The following sources were referenced in the design of this Multi-precision
49 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000050 *
Simon Butcher15b15d12015-11-26 19:35:03 +000051 * [1] Handbook of Applied Cryptography - 1997
52 * Menezes, van Oorschot and Vanstone
53 *
54 * [2] Multi-Precision Math
55 * Tom St Denis
56 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
57 *
58 * [3] GNU Multi-Precision Arithmetic Library
59 * https://gmplib.org/manual/index.html
60 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000061 */
Paul Bakker5121ce52009-01-03 21:22:43 +000062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000064#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020065#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020067#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000068
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000070
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000071#include "mbedtls/bignum.h"
72#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050073#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000074
Tom Cosgrove7b420a82021-11-15 09:59:53 +000075#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000076#include <string.h>
77
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000079#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020080#else
Rich Evans00ab4702015-02-06 13:43:58 +000081#include <stdio.h>
82#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020084#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020086#endif
87
Hanno Becker73d7d792018-12-11 10:35:51 +000088#define MPI_VALIDATE_RET( cond ) \
89 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
90#define MPI_VALIDATE( cond ) \
91 MBEDTLS_INTERNAL_VALIDATE( cond )
92
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000094#define biL (ciL << 3) /* bits in limb */
95#define biH (ciL << 2) /* half limb size */
96
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010097#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
98
Paul Bakker5121ce52009-01-03 21:22:43 +000099/*
100 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200101 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200103#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
104#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500106/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -0500107static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
108{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500109 mbedtls_platform_zeroize( v, ciL * n );
110}
111
Paul Bakker5121ce52009-01-03 21:22:43 +0000112/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000113 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000116{
Hanno Becker73d7d792018-12-11 10:35:51 +0000117 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000118
Paul Bakker6c591fa2011-05-05 11:49:20 +0000119 X->s = 1;
120 X->n = 0;
121 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000122}
123
124/*
Paul Bakker6c591fa2011-05-05 11:49:20 +0000125 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000128{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000129 if( X == NULL )
130 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000131
Paul Bakker6c591fa2011-05-05 11:49:20 +0000132 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200134 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000136 }
137
Paul Bakker6c591fa2011-05-05 11:49:20 +0000138 X->s = 1;
139 X->n = 0;
140 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000141}
142
143/*
144 * Enlarge to the specified number of limbs
145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000147{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000149 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200152 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000153
Paul Bakker5121ce52009-01-03 21:22:43 +0000154 if( X->n < nblimbs )
155 {
Simon Butcher29176892016-05-20 00:19:09 +0100156 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200157 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000158
Paul Bakker5121ce52009-01-03 21:22:43 +0000159 if( X->p != NULL )
160 {
161 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200162 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000164 }
165
166 X->n = nblimbs;
167 X->p = p;
168 }
169
170 return( 0 );
171}
172
173/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174 * Resize down as much as possible,
175 * while keeping at least the specified number of limbs
176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100178{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000181 MPI_VALIDATE_RET( X != NULL );
182
183 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
184 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100185
Gilles Peskine27c15c72020-01-20 21:17:43 +0100186 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100187 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine56427c22020-01-21 13:59:51 +0100189 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100190
191 for( i = X->n - 1; i > 0; i-- )
192 if( X->p[i] != 0 )
193 break;
194 i++;
195
196 if( i < nblimbs )
197 i = nblimbs;
198
Simon Butcher29176892016-05-20 00:19:09 +0100199 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200200 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100201
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100202 if( X->p != NULL )
203 {
204 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200205 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100207 }
208
209 X->n = i;
210 X->p = p;
211
212 return( 0 );
213}
214
215/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000216 * Copy the contents of Y into X
217 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000219{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100220 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000221 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000222 MPI_VALIDATE_RET( X != NULL );
223 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000224
225 if( X == Y )
226 return( 0 );
227
Gilles Peskine3e9f5222020-01-20 21:12:50 +0100228 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200229 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200231 return( 0 );
232 }
233
Paul Bakker5121ce52009-01-03 21:22:43 +0000234 for( i = Y->n - 1; i > 0; i-- )
235 if( Y->p[i] != 0 )
236 break;
237 i++;
238
239 X->s = Y->s;
240
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100241 if( X->n < i )
242 {
243 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
244 }
245 else
246 {
247 memset( X->p + i, 0, ( X->n - i ) * ciL );
248 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000249
Paul Bakker5121ce52009-01-03 21:22:43 +0000250 memcpy( X->p, Y->p, i * ciL );
251
252cleanup:
253
254 return( ret );
255}
256
257/*
258 * Swap the contents of X and Y
259 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000261{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000263 MPI_VALIDATE( X != NULL );
264 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 memcpy( &T, X, sizeof( mbedtls_mpi ) );
267 memcpy( X, Y, sizeof( mbedtls_mpi ) );
268 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000269}
270
Manuel Pégourié-Gonnarddc6a5f22021-06-07 09:51:00 +0200271/**
272 * Select between two sign values in constant-time.
273 *
274 * This is functionally equivalent to second ? a : b but uses only bit
275 * operations in order to avoid branches.
276 *
277 * \param[in] a The first sign; must be either +1 or -1.
278 * \param[in] b The second sign; must be either +1 or -1.
279 * \param[in] second Must be either 1 (return b) or 0 (return a).
280 *
281 * \return The selected sign value.
282 */
283static int mpi_safe_cond_select_sign( int a, int b, unsigned char second )
284{
285 /* In order to avoid questions about what we can reasonnably assume about
286 * the representations of signed integers, move everything to unsigned
287 * by taking advantage of the fact that a and b are either +1 or -1. */
288 unsigned ua = a + 1;
289 unsigned ub = b + 1;
290
Manuel Pégourié-Gonnard12f02382021-06-10 09:36:41 +0200291 /* second was 0 or 1, mask is 0 or 2 as are ua and ub */
292 const unsigned mask = second << 1;
Manuel Pégourié-Gonnarddc6a5f22021-06-07 09:51:00 +0200293
294 /* select ua or ub */
295 unsigned ur = ( ua & ~mask ) | ( ub & mask );
296
297 /* ur is now 0 or 2, convert back to -1 or +1 */
298 return( (int) ur - 1 );
299}
300
Paul Bakker5121ce52009-01-03 21:22:43 +0000301/*
Gilles Peskinec81c5882020-06-04 19:14:58 +0200302 * Conditionally assign dest = src, without leaking information
303 * about whether the assignment was made or not.
304 * dest and src must be arrays of limbs of size n.
305 * assign must be 0 or 1.
306 */
307static void mpi_safe_cond_assign( size_t n,
308 mbedtls_mpi_uint *dest,
309 const mbedtls_mpi_uint *src,
310 unsigned char assign )
311{
312 size_t i;
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200313
314 /* MSVC has a warning about unary minus on unsigned integer types,
315 * but this is well-defined and precisely what we want to do here. */
316#if defined(_MSC_VER)
317#pragma warning( push )
318#pragma warning( disable : 4146 )
319#endif
320
321 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
322 const mbedtls_mpi_uint mask = -assign;
323
324#if defined(_MSC_VER)
325#pragma warning( pop )
326#endif
327
Gilles Peskinec81c5882020-06-04 19:14:58 +0200328 for( i = 0; i < n; i++ )
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200329 dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
Gilles Peskinec81c5882020-06-04 19:14:58 +0200330}
331
332/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100333 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100334 * about whether the assignment was made or not.
335 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100336 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100338{
339 int ret = 0;
340 size_t i;
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200341 mbedtls_mpi_uint limb_mask;
Hanno Becker73d7d792018-12-11 10:35:51 +0000342 MPI_VALIDATE_RET( X != NULL );
343 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100344
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200345 /* MSVC has a warning about unary minus on unsigned integer types,
346 * but this is well-defined and precisely what we want to do here. */
347#if defined(_MSC_VER)
348#pragma warning( push )
349#pragma warning( disable : 4146 )
350#endif
351
Pascal Junodb99183d2015-03-11 16:49:45 +0100352 /* make sure assign is 0 or 1 in a time-constant manner */
Manuel Pégourié-Gonnarde9eca7f2021-06-17 13:25:03 +0200353 assign = (assign | (unsigned char)-assign) >> (sizeof( assign ) * 8 - 1);
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200354 /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200355 limb_mask = -assign;
356
357#if defined(_MSC_VER)
358#pragma warning( pop )
359#endif
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100362
Manuel Pégourié-Gonnarddc6a5f22021-06-07 09:51:00 +0200363 X->s = mpi_safe_cond_select_sign( X->s, Y->s, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100364
Gilles Peskinec81c5882020-06-04 19:14:58 +0200365 mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100366
Gilles Peskinec81c5882020-06-04 19:14:58 +0200367 for( i = Y->n; i < X->n; i++ )
Manuel Pégourié-Gonnard245a8062021-05-31 11:48:45 +0200368 X->p[i] &= ~limb_mask;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100369
370cleanup:
371 return( ret );
372}
373
374/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100375 * Conditionally swap X and Y, without leaking information
376 * about whether the swap was made or not.
377 * Here it is not ok to simply swap the pointers, which whould lead to
378 * different memory access patterns when X and Y are used afterwards.
379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100381{
382 int ret, s;
383 size_t i;
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200384 mbedtls_mpi_uint limb_mask;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000386 MPI_VALIDATE_RET( X != NULL );
387 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100388
389 if( X == Y )
390 return( 0 );
391
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200392 /* MSVC has a warning about unary minus on unsigned integer types,
393 * but this is well-defined and precisely what we want to do here. */
394#if defined(_MSC_VER)
395#pragma warning( push )
396#pragma warning( disable : 4146 )
397#endif
398
Pascal Junodb99183d2015-03-11 16:49:45 +0100399 /* make sure swap is 0 or 1 in a time-constant manner */
Manuel Pégourié-Gonnarde9eca7f2021-06-17 13:25:03 +0200400 swap = (swap | (unsigned char)-swap) >> (sizeof( swap ) * 8 - 1);
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200401 /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200402 limb_mask = -swap;
403
404#if defined(_MSC_VER)
405#pragma warning( pop )
406#endif
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
409 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100410
411 s = X->s;
Manuel Pégourié-Gonnarddc6a5f22021-06-07 09:51:00 +0200412 X->s = mpi_safe_cond_select_sign( X->s, Y->s, swap );
413 Y->s = mpi_safe_cond_select_sign( Y->s, s, swap );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100414
415
416 for( i = 0; i < X->n; i++ )
417 {
418 tmp = X->p[i];
Manuel Pégourié-Gonnarda1283cc2021-06-03 10:54:01 +0200419 X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
420 Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100421 }
422
423cleanup:
424 return( ret );
425}
426
427/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000428 * Set value from integer
429 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000431{
432 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000433 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000434
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436 memset( X->p, 0, X->n * ciL );
437
438 X->p[0] = ( z < 0 ) ? -z : z;
439 X->s = ( z < 0 ) ? -1 : 1;
440
441cleanup:
442
443 return( ret );
444}
445
446/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000447 * Get a specific bit
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000450{
Hanno Becker73d7d792018-12-11 10:35:51 +0000451 MPI_VALIDATE_RET( X != NULL );
452
Paul Bakker2f5947e2011-05-18 15:47:11 +0000453 if( X->n * biL <= pos )
454 return( 0 );
455
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200456 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000457}
458
Gilles Peskine11cdb052018-11-20 16:47:47 +0100459/* Get a specific byte, without range checks. */
460#define GET_BYTE( X, i ) \
461 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
462
Paul Bakker2f5947e2011-05-18 15:47:11 +0000463/*
464 * Set a bit to a specific value of 0 or 1
465 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000467{
468 int ret = 0;
469 size_t off = pos / biL;
470 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000471 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000472
473 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200475
Paul Bakker2f5947e2011-05-18 15:47:11 +0000476 if( X->n * biL <= pos )
477 {
478 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200479 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000482 }
483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
485 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000486
487cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200488
Paul Bakker2f5947e2011-05-18 15:47:11 +0000489 return( ret );
490}
491
492/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200493 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000496{
Paul Bakker23986e52011-04-24 08:57:21 +0000497 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000498 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
500 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000501 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
503 return( count );
504
505 return( 0 );
506}
507
508/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000509 * Count leading zero bits in a given integer
510 */
511static size_t mbedtls_clz( const mbedtls_mpi_uint x )
512{
513 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100514 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000515
516 for( j = 0; j < biL; j++ )
517 {
518 if( x & mask ) break;
519
520 mask >>= 1;
521 }
522
523 return j;
524}
525
526/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200527 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000528 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200529size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000530{
Paul Bakker23986e52011-04-24 08:57:21 +0000531 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200533 if( X->n == 0 )
534 return( 0 );
535
Paul Bakker5121ce52009-01-03 21:22:43 +0000536 for( i = X->n - 1; i > 0; i-- )
537 if( X->p[i] != 0 )
538 break;
539
Simon Butcher15b15d12015-11-26 19:35:03 +0000540 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000541
Paul Bakker23986e52011-04-24 08:57:21 +0000542 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000543}
544
545/*
546 * Return the total size in bytes
547 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000549{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200550 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000551}
552
553/*
554 * Convert an ASCII character to digit value
555 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000557{
558 *d = 255;
559
560 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
561 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
562 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564 if( *d >= (mbedtls_mpi_uint) radix )
565 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
567 return( 0 );
568}
569
570/*
571 * Import from an ASCII string
572 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000574{
Paul Bakker23986e52011-04-24 08:57:21 +0000575 int ret;
576 size_t i, j, slen, n;
Gilles Peskine984fd072021-04-03 18:26:13 +0200577 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 mbedtls_mpi_uint d;
579 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000580 MPI_VALIDATE_RET( X != NULL );
581 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
583 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000584 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
Gilles Peskine984fd072021-04-03 18:26:13 +0200588 if( s[0] == '-' )
589 {
590 ++s;
591 sign = -1;
592 }
593
Paul Bakkerff60ee62010-03-16 21:09:09 +0000594 slen = strlen( s );
595
Paul Bakker5121ce52009-01-03 21:22:43 +0000596 if( radix == 16 )
597 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100598 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200599 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
600
Paul Bakkerff60ee62010-03-16 21:09:09 +0000601 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
604 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
Paul Bakker23986e52011-04-24 08:57:21 +0000606 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000607 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200609 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000610 }
611 }
612 else
613 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000615
Paul Bakkerff60ee62010-03-16 21:09:09 +0000616 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000617 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
619 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Gilles Peskine984fd072021-04-03 18:26:13 +0200620 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 }
622 }
623
Gilles Peskine984fd072021-04-03 18:26:13 +0200624 if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
625 X->s = -1;
626
Paul Bakker5121ce52009-01-03 21:22:43 +0000627cleanup:
628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
631 return( ret );
632}
633
634/*
Ron Eldora16fa292018-11-20 14:07:01 +0200635 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000636 */
Ron Eldora16fa292018-11-20 14:07:01 +0200637static int mpi_write_hlp( mbedtls_mpi *X, int radix,
638 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000639{
640 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200642 size_t length = 0;
643 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
Ron Eldora16fa292018-11-20 14:07:01 +0200645 do
646 {
647 if( length >= buflen )
648 {
649 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
650 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
Ron Eldora16fa292018-11-20 14:07:01 +0200652 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
653 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
654 /*
655 * Write the residue in the current position, as an ASCII character.
656 */
657 if( r < 0xA )
658 *(--p_end) = (char)( '0' + r );
659 else
660 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Ron Eldora16fa292018-11-20 14:07:01 +0200662 length++;
663 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000664
Ron Eldora16fa292018-11-20 14:07:01 +0200665 memmove( *p, p_end, length );
666 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
668cleanup:
669
670 return( ret );
671}
672
673/*
674 * Export into an ASCII string
675 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100676int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
677 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000678{
Paul Bakker23986e52011-04-24 08:57:21 +0000679 int ret = 0;
680 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000683 MPI_VALIDATE_RET( X != NULL );
684 MPI_VALIDATE_RET( olen != NULL );
685 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000688 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000690 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
691 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
692 * `n`. If radix > 4, this might be a strict
693 * overapproximation of the number of
694 * radix-adic digits needed to present `n`. */
695 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
696 * present `n`. */
697
Janos Follath870ed002019-03-06 13:43:02 +0000698 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000699 n += 1; /* Compensate for the divisions above, which round down `n`
700 * in case it's not even. */
701 n += 1; /* Potential '-'-sign. */
702 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
703 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100705 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000706 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100707 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000709 }
710
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100711 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
714 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000715 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000716 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000717 buflen--;
718 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
720 if( radix == 16 )
721 {
Paul Bakker23986e52011-04-24 08:57:21 +0000722 int c;
723 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
Paul Bakker23986e52011-04-24 08:57:21 +0000725 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000726 {
Paul Bakker23986e52011-04-24 08:57:21 +0000727 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000728 {
Paul Bakker23986e52011-04-24 08:57:21 +0000729 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000730
Paul Bakker6c343d72014-07-10 14:36:19 +0200731 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000732 continue;
733
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000734 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000735 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000736 k = 1;
737 }
738 }
739 }
740 else
741 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000743
744 if( T.s == -1 )
745 T.s = 1;
746
Ron Eldora16fa292018-11-20 14:07:01 +0200747 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000748 }
749
750 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100751 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000752
753cleanup:
754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000756
757 return( ret );
758}
759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000761/*
762 * Read X from an opened file
763 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000765{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000767 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000768 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000769 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000770 * Buffer should have space for (short) label and decimal formatted MPI,
771 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000772 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000774
Hanno Becker73d7d792018-12-11 10:35:51 +0000775 MPI_VALIDATE_RET( X != NULL );
776 MPI_VALIDATE_RET( fin != NULL );
777
778 if( radix < 2 || radix > 16 )
779 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
780
Paul Bakker5121ce52009-01-03 21:22:43 +0000781 memset( s, 0, sizeof( s ) );
782 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200783 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000784
785 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000786 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000788
Hanno Beckerb2034b72017-04-26 11:46:46 +0100789 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
790 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000791
792 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100793 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000794 if( mpi_get_digit( &d, radix, *p ) != 0 )
795 break;
796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000798}
799
800/*
801 * Write X into an opened file (or stdout if fout == NULL)
802 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000804{
Paul Bakker23986e52011-04-24 08:57:21 +0000805 int ret;
806 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000807 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000808 * Buffer should have space for (short) label and decimal formatted MPI,
809 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000810 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000812 MPI_VALIDATE_RET( X != NULL );
813
814 if( radix < 2 || radix > 16 )
815 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000816
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100817 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000818
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100819 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000820
821 if( p == NULL ) p = "";
822
823 plen = strlen( p );
824 slen = strlen( s );
825 s[slen++] = '\r';
826 s[slen++] = '\n';
827
828 if( fout != NULL )
829 {
830 if( fwrite( p, 1, plen, fout ) != plen ||
831 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 }
834 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200835 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000836
837cleanup:
838
839 return( ret );
840}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000842
Hanno Beckerda1655a2017-10-18 14:21:44 +0100843
844/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
845 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000846
847static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
848{
849 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100850 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000851 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100852
853 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
854 {
855 tmp <<= CHAR_BIT;
856 tmp |= (mbedtls_mpi_uint) *x_ptr;
857 }
858
Hanno Beckerf8720072018-11-08 11:53:49 +0000859 return( tmp );
860}
861
862static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
863{
864#if defined(__BYTE_ORDER__)
865
866/* Nothing to do on bigendian systems. */
867#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
868 return( x );
869#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
870
871#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
872
873/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000874#if defined(__GNUC__) && defined(__GNUC_PREREQ)
875#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000876#define have_bswap
877#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000878#endif
879
880#if defined(__clang__) && defined(__has_builtin)
881#if __has_builtin(__builtin_bswap32) && \
882 __has_builtin(__builtin_bswap64)
883#define have_bswap
884#endif
885#endif
886
Hanno Beckerf8720072018-11-08 11:53:49 +0000887#if defined(have_bswap)
888 /* The compiler is hopefully able to statically evaluate this! */
889 switch( sizeof(mbedtls_mpi_uint) )
890 {
891 case 4:
892 return( __builtin_bswap32(x) );
893 case 8:
894 return( __builtin_bswap64(x) );
895 }
896#endif
897#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
898#endif /* __BYTE_ORDER__ */
899
900 /* Fall back to C-based reordering if we don't know the byte order
901 * or we couldn't use a compiler-specific builtin. */
902 return( mpi_uint_bigendian_to_host_c( x ) );
903}
904
Hanno Becker2be8a552018-10-25 12:40:09 +0100905static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100906{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100907 mbedtls_mpi_uint *cur_limb_left;
908 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100909 if( limbs == 0 )
910 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100911
912 /*
913 * Traverse limbs and
914 * - adapt byte-order in each limb
915 * - swap the limbs themselves.
916 * For that, simultaneously traverse the limbs from left to right
917 * and from right to left, as long as the left index is not bigger
918 * than the right index (it's not a problem if limbs is odd and the
919 * indices coincide in the last iteration).
920 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100921 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
922 cur_limb_left <= cur_limb_right;
923 cur_limb_left++, cur_limb_right-- )
924 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000925 mbedtls_mpi_uint tmp;
926 /* Note that if cur_limb_left == cur_limb_right,
927 * this code effectively swaps the bytes only once. */
928 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
929 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
930 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100931 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100932}
933
Paul Bakker5121ce52009-01-03 21:22:43 +0000934/*
935 * Import X from unsigned binary data, big endian
936 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000938{
Paul Bakker23986e52011-04-24 08:57:21 +0000939 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100940 size_t const limbs = CHARS_TO_LIMBS( buflen );
941 size_t const overhead = ( limbs * ciL ) - buflen;
942 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000943
Hanno Becker8ce11a32018-12-19 16:18:52 +0000944 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000945 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
946
Hanno Becker073c1992017-10-17 15:17:27 +0100947 /* Ensure that target MPI has exactly the necessary number of limbs */
948 if( X->n != limbs )
949 {
950 mbedtls_mpi_free( X );
951 mbedtls_mpi_init( X );
952 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
953 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000955
Hanno Becker0e810b92019-01-03 17:13:11 +0000956 /* Avoid calling `memcpy` with NULL source argument,
957 * even if buflen is 0. */
958 if( buf != NULL )
959 {
960 Xp = (unsigned char*) X->p;
961 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100962
Hanno Becker0e810b92019-01-03 17:13:11 +0000963 mpi_bigendian_to_host( X->p, limbs );
964 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000965
966cleanup:
967
968 return( ret );
969}
970
971/*
972 * Export X into unsigned binary data, big endian
973 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100974int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
975 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000976{
Hanno Becker73d7d792018-12-11 10:35:51 +0000977 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100978 size_t bytes_to_copy;
979 unsigned char *p;
980 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000981
Hanno Becker73d7d792018-12-11 10:35:51 +0000982 MPI_VALIDATE_RET( X != NULL );
983 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
984
985 stored_bytes = X->n * ciL;
986
Gilles Peskine11cdb052018-11-20 16:47:47 +0100987 if( stored_bytes < buflen )
988 {
989 /* There is enough space in the output buffer. Write initial
990 * null bytes and record the position at which to start
991 * writing the significant bytes. In this case, the execution
992 * trace of this function does not depend on the value of the
993 * number. */
994 bytes_to_copy = stored_bytes;
995 p = buf + buflen - stored_bytes;
996 memset( buf, 0, buflen - stored_bytes );
997 }
998 else
999 {
1000 /* The output buffer is smaller than the allocated size of X.
1001 * However X may fit if its leading bytes are zero. */
1002 bytes_to_copy = buflen;
1003 p = buf;
1004 for( i = bytes_to_copy; i < stored_bytes; i++ )
1005 {
1006 if( GET_BYTE( X, i ) != 0 )
1007 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
1008 }
1009 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001010
Gilles Peskine11cdb052018-11-20 16:47:47 +01001011 for( i = 0; i < bytes_to_copy; i++ )
1012 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +00001013
1014 return( 0 );
1015}
1016
1017/*
1018 * Left-shift: X <<= count
1019 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001021{
Paul Bakker23986e52011-04-24 08:57:21 +00001022 int ret;
1023 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001025 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001026
1027 v0 = count / (biL );
1028 t1 = count & (biL - 1);
1029
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001030 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001031
Paul Bakkerf9688572011-05-05 10:00:45 +00001032 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034
1035 ret = 0;
1036
1037 /*
1038 * shift by count / limb_size
1039 */
1040 if( v0 > 0 )
1041 {
Paul Bakker23986e52011-04-24 08:57:21 +00001042 for( i = X->n; i > v0; i-- )
1043 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001044
Paul Bakker23986e52011-04-24 08:57:21 +00001045 for( ; i > 0; i-- )
1046 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001047 }
1048
1049 /*
1050 * shift by count % limb_size
1051 */
1052 if( t1 > 0 )
1053 {
1054 for( i = v0; i < X->n; i++ )
1055 {
1056 r1 = X->p[i] >> (biL - t1);
1057 X->p[i] <<= t1;
1058 X->p[i] |= r0;
1059 r0 = r1;
1060 }
1061 }
1062
1063cleanup:
1064
1065 return( ret );
1066}
1067
1068/*
1069 * Right-shift: X >>= count
1070 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001071int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001072{
Paul Bakker23986e52011-04-24 08:57:21 +00001073 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001075 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001076
1077 v0 = count / biL;
1078 v1 = count & (biL - 1);
1079
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001080 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001082
Paul Bakker5121ce52009-01-03 21:22:43 +00001083 /*
1084 * shift by count / limb_size
1085 */
1086 if( v0 > 0 )
1087 {
1088 for( i = 0; i < X->n - v0; i++ )
1089 X->p[i] = X->p[i + v0];
1090
1091 for( ; i < X->n; i++ )
1092 X->p[i] = 0;
1093 }
1094
1095 /*
1096 * shift by count % limb_size
1097 */
1098 if( v1 > 0 )
1099 {
Paul Bakker23986e52011-04-24 08:57:21 +00001100 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 {
Paul Bakker23986e52011-04-24 08:57:21 +00001102 r1 = X->p[i - 1] << (biL - v1);
1103 X->p[i - 1] >>= v1;
1104 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001105 r0 = r1;
1106 }
1107 }
1108
1109 return( 0 );
1110}
1111
1112/*
1113 * Compare unsigned values
1114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001116{
Paul Bakker23986e52011-04-24 08:57:21 +00001117 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001118 MPI_VALIDATE_RET( X != NULL );
1119 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001120
Paul Bakker23986e52011-04-24 08:57:21 +00001121 for( i = X->n; i > 0; i-- )
1122 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001123 break;
1124
Paul Bakker23986e52011-04-24 08:57:21 +00001125 for( j = Y->n; j > 0; j-- )
1126 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001127 break;
1128
Paul Bakker23986e52011-04-24 08:57:21 +00001129 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 return( 0 );
1131
1132 if( i > j ) return( 1 );
1133 if( j > i ) return( -1 );
1134
Paul Bakker23986e52011-04-24 08:57:21 +00001135 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001136 {
Paul Bakker23986e52011-04-24 08:57:21 +00001137 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1138 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 }
1140
1141 return( 0 );
1142}
1143
1144/*
1145 * Compare signed values
1146 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001147int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001148{
Paul Bakker23986e52011-04-24 08:57:21 +00001149 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001150 MPI_VALIDATE_RET( X != NULL );
1151 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
Paul Bakker23986e52011-04-24 08:57:21 +00001153 for( i = X->n; i > 0; i-- )
1154 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001155 break;
1156
Paul Bakker23986e52011-04-24 08:57:21 +00001157 for( j = Y->n; j > 0; j-- )
1158 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001159 break;
1160
Paul Bakker23986e52011-04-24 08:57:21 +00001161 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001162 return( 0 );
1163
1164 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001165 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
1167 if( X->s > 0 && Y->s < 0 ) return( 1 );
1168 if( Y->s > 0 && X->s < 0 ) return( -1 );
1169
Paul Bakker23986e52011-04-24 08:57:21 +00001170 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 {
Paul Bakker23986e52011-04-24 08:57:21 +00001172 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1173 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174 }
1175
1176 return( 0 );
1177}
1178
Janos Follath45ec9902019-10-14 09:09:32 +01001179/** Decide if an integer is less than the other, without branches.
1180 *
1181 * \param x First integer.
1182 * \param y Second integer.
1183 *
1184 * \return 1 if \p x is less than \p y, 0 otherwise
1185 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001186static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1187 const mbedtls_mpi_uint y )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001188{
1189 mbedtls_mpi_uint ret;
1190 mbedtls_mpi_uint cond;
1191
1192 /*
1193 * Check if the most significant bits (MSB) of the operands are different.
1194 */
1195 cond = ( x ^ y );
1196 /*
1197 * If the MSB are the same then the difference x-y will be negative (and
1198 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1199 */
1200 ret = ( x - y ) & ~cond;
1201 /*
1202 * If the MSB are different, then the operand with the MSB of 1 is the
1203 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1204 * the MSB of y is 0.)
1205 */
1206 ret |= y & cond;
1207
1208
Janos Follath7a34bcf2019-10-14 08:59:14 +01001209 ret = ret >> ( biL - 1 );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001210
Janos Follath359a01e2019-10-29 15:08:46 +00001211 return (unsigned) ret;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001212}
1213
1214/*
1215 * Compare signed values in constant time
1216 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001217int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1218 unsigned *ret )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001219{
1220 size_t i;
Janos Follathbd87a592019-10-28 12:23:18 +00001221 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001222 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001223
1224 MPI_VALIDATE_RET( X != NULL );
1225 MPI_VALIDATE_RET( Y != NULL );
1226 MPI_VALIDATE_RET( ret != NULL );
1227
1228 if( X->n != Y->n )
1229 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1230
1231 /*
Janos Follath58525182019-10-28 12:12:15 +00001232 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1233 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001234 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001235 X_is_negative = ( X->s & 2 ) >> 1;
1236 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath867a3ab2019-10-11 14:21:53 +01001237
1238 /*
1239 * If the signs are different, then the positive operand is the bigger.
Janos Follath1f21c1d2019-10-28 12:31:34 +00001240 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1241 * is false if X is positive (X_is_negative == 0).
Janos Follath867a3ab2019-10-11 14:21:53 +01001242 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001243 cond = ( X_is_negative ^ Y_is_negative );
1244 *ret = cond & X_is_negative;
Janos Follath867a3ab2019-10-11 14:21:53 +01001245
1246 /*
Janos Follathbd87a592019-10-28 12:23:18 +00001247 * This is a constant-time function. We might have the result, but we still
Janos Follath867a3ab2019-10-11 14:21:53 +01001248 * need to go through the loop. Record if we have the result already.
1249 */
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001250 done = cond;
1251
1252 for( i = X->n; i > 0; i-- )
1253 {
1254 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001255 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1256 * X and Y are negative.
Janos Follath867a3ab2019-10-11 14:21:53 +01001257 *
1258 * Again even if we can make a decision, we just mark the result and
1259 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001260 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001261 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1262 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathfbe4c942019-10-28 12:37:21 +00001263 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001264
1265 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001266 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1267 * X and Y are positive.
Janos Follath867a3ab2019-10-11 14:21:53 +01001268 *
1269 * Again even if we can make a decision, we just mark the result and
1270 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001271 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001272 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1273 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathfbe4c942019-10-28 12:37:21 +00001274 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001275 }
1276
1277 return( 0 );
1278}
1279
Paul Bakker5121ce52009-01-03 21:22:43 +00001280/*
1281 * Compare signed values
1282 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001284{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 mbedtls_mpi Y;
1286 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001287 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001288
1289 *p = ( z < 0 ) ? -z : z;
1290 Y.s = ( z < 0 ) ? -1 : 1;
1291 Y.n = 1;
1292 Y.p = p;
1293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001295}
1296
1297/*
1298 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1299 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001301{
Paul Bakker23986e52011-04-24 08:57:21 +00001302 int ret;
1303 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001304 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001305 MPI_VALIDATE_RET( X != NULL );
1306 MPI_VALIDATE_RET( A != NULL );
1307 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001308
1309 if( X == B )
1310 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001312 }
1313
1314 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001316
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001317 /*
1318 * X should always be positive as a result of unsigned additions.
1319 */
1320 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001321
Paul Bakker23986e52011-04-24 08:57:21 +00001322 for( j = B->n; j > 0; j-- )
1323 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001324 break;
1325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001327
1328 o = B->p; p = X->p; c = 0;
1329
Janos Follath6c922682015-10-30 17:43:11 +01001330 /*
1331 * tmp is used because it might happen that p == o
1332 */
Paul Bakker23986e52011-04-24 08:57:21 +00001333 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001334 {
Janos Follath6c922682015-10-30 17:43:11 +01001335 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001336 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001337 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 }
1339
1340 while( c != 0 )
1341 {
1342 if( i >= X->n )
1343 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345 p = X->p + i;
1346 }
1347
Paul Bakker2d319fd2012-09-16 21:34:26 +00001348 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001349 }
1350
1351cleanup:
1352
1353 return( ret );
1354}
1355
Gilles Peskinede719d52020-06-09 10:39:38 +02001356/**
Gilles Peskine36acd542020-06-08 21:58:22 +02001357 * Helper for mbedtls_mpi subtraction.
1358 *
1359 * Calculate d - s where d and s have the same size.
1360 * This function operates modulo (2^ciL)^n and returns the carry
1361 * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
1362 *
1363 * \param n Number of limbs of \p d and \p s.
1364 * \param[in,out] d On input, the left operand.
1365 * On output, the result of the subtraction:
Gilles Peskinede719d52020-06-09 10:39:38 +02001366 * \param[in] s The right operand.
Gilles Peskine36acd542020-06-08 21:58:22 +02001367 *
1368 * \return 1 if `d < s`.
1369 * 0 if `d >= s`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001370 */
Gilles Peskine36acd542020-06-08 21:58:22 +02001371static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1372 mbedtls_mpi_uint *d,
1373 const mbedtls_mpi_uint *s )
Paul Bakker5121ce52009-01-03 21:22:43 +00001374{
Paul Bakker23986e52011-04-24 08:57:21 +00001375 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001377
1378 for( i = c = 0; i < n; i++, s++, d++ )
1379 {
1380 z = ( *d < c ); *d -= c;
1381 c = ( *d < *s ) + z; *d -= *s;
1382 }
1383
Gilles Peskine36acd542020-06-08 21:58:22 +02001384 return( c );
Paul Bakker5121ce52009-01-03 21:22:43 +00001385}
1386
1387/*
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001388 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001391{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001393 int ret;
1394 size_t n;
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001395 mbedtls_mpi_uint carry;
Hanno Becker73d7d792018-12-11 10:35:51 +00001396 MPI_VALIDATE_RET( X != NULL );
1397 MPI_VALIDATE_RET( A != NULL );
1398 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401
1402 if( X == B )
1403 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001404 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 B = &TB;
1406 }
1407
1408 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001410
Paul Bakker1ef7a532009-06-20 10:50:55 +00001411 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001412 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001413 */
1414 X->s = 1;
1415
Paul Bakker5121ce52009-01-03 21:22:43 +00001416 ret = 0;
1417
Paul Bakker23986e52011-04-24 08:57:21 +00001418 for( n = B->n; n > 0; n-- )
1419 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001420 break;
Gilles Peskine6260b702021-01-27 22:30:43 +01001421 if( n > A->n )
1422 {
1423 /* B >= (2^ciL)^n > A */
1424 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1425 goto cleanup;
1426 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001427
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001428 carry = mpi_sub_hlp( n, X->p, B->p );
1429 if( carry != 0 )
Gilles Peskine36acd542020-06-08 21:58:22 +02001430 {
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001431 /* Propagate the carry to the first nonzero limb of X. */
1432 for( ; n < X->n && X->p[n] == 0; n++ )
1433 --X->p[n];
1434 /* If we ran out of space for the carry, it means that the result
1435 * is negative. */
1436 if( n == X->n )
Gilles Peskine84697ca2020-07-23 01:16:46 +02001437 {
1438 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1439 goto cleanup;
1440 }
Gilles Peskine08fd43c2020-06-08 22:50:35 +02001441 --X->p[n];
Gilles Peskine36acd542020-06-08 21:58:22 +02001442 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001443
1444cleanup:
1445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001447
1448 return( ret );
1449}
1450
1451/*
1452 * Signed addition: X = A + B
1453 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001454int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001455{
Hanno Becker73d7d792018-12-11 10:35:51 +00001456 int ret, s;
1457 MPI_VALIDATE_RET( X != NULL );
1458 MPI_VALIDATE_RET( A != NULL );
1459 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001460
Hanno Becker73d7d792018-12-11 10:35:51 +00001461 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001462 if( A->s * B->s < 0 )
1463 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001465 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467 X->s = s;
1468 }
1469 else
1470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001472 X->s = -s;
1473 }
1474 }
1475 else
1476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001478 X->s = s;
1479 }
1480
1481cleanup:
1482
1483 return( ret );
1484}
1485
1486/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001487 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001488 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001490{
Hanno Becker73d7d792018-12-11 10:35:51 +00001491 int ret, s;
1492 MPI_VALIDATE_RET( X != NULL );
1493 MPI_VALIDATE_RET( A != NULL );
1494 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
Hanno Becker73d7d792018-12-11 10:35:51 +00001496 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001497 if( A->s * B->s > 0 )
1498 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001500 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 X->s = s;
1503 }
1504 else
1505 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507 X->s = -s;
1508 }
1509 }
1510 else
1511 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513 X->s = s;
1514 }
1515
1516cleanup:
1517
1518 return( ret );
1519}
1520
1521/*
1522 * Signed addition: X = A + b
1523 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001525{
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001526 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001527 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001528 MPI_VALIDATE_RET( X != NULL );
1529 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001530
1531 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001532 B.s = ( b < 0 ) ? -1 : 1;
1533 B.n = 1;
1534 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001536 return( mbedtls_mpi_add_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001537}
1538
1539/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001540 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001543{
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001544 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001546 MPI_VALIDATE_RET( X != NULL );
1547 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001548
1549 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001550 B.s = ( b < 0 ) ? -1 : 1;
1551 B.n = 1;
1552 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001554 return( mbedtls_mpi_sub_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555}
1556
1557/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001559 */
1560static
1561#if defined(__APPLE__) && defined(__arm__)
1562/*
1563 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1564 * appears to need this to prevent bad ARM code generation at -O3.
1565 */
1566__attribute__ ((noinline))
1567#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568void 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 +00001569{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001570 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
1572#if defined(MULADDC_HUIT)
1573 for( ; i >= 8; i -= 8 )
1574 {
1575 MULADDC_INIT
1576 MULADDC_HUIT
1577 MULADDC_STOP
1578 }
1579
1580 for( ; i > 0; i-- )
1581 {
1582 MULADDC_INIT
1583 MULADDC_CORE
1584 MULADDC_STOP
1585 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001586#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001587 for( ; i >= 16; i -= 16 )
1588 {
1589 MULADDC_INIT
1590 MULADDC_CORE MULADDC_CORE
1591 MULADDC_CORE MULADDC_CORE
1592 MULADDC_CORE MULADDC_CORE
1593 MULADDC_CORE MULADDC_CORE
1594
1595 MULADDC_CORE MULADDC_CORE
1596 MULADDC_CORE MULADDC_CORE
1597 MULADDC_CORE MULADDC_CORE
1598 MULADDC_CORE MULADDC_CORE
1599 MULADDC_STOP
1600 }
1601
1602 for( ; i >= 8; i -= 8 )
1603 {
1604 MULADDC_INIT
1605 MULADDC_CORE MULADDC_CORE
1606 MULADDC_CORE MULADDC_CORE
1607
1608 MULADDC_CORE MULADDC_CORE
1609 MULADDC_CORE MULADDC_CORE
1610 MULADDC_STOP
1611 }
1612
1613 for( ; i > 0; i-- )
1614 {
1615 MULADDC_INIT
1616 MULADDC_CORE
1617 MULADDC_STOP
1618 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001619#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
1621 t++;
1622
1623 do {
1624 *d += c; c = ( *d < c ); d++;
1625 }
1626 while( c != 0 );
1627}
1628
1629/*
1630 * Baseline multiplication: X = A * B (HAC 14.12)
1631 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001633{
Paul Bakker23986e52011-04-24 08:57:21 +00001634 int ret;
1635 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 mbedtls_mpi TA, TB;
Gilles Peskine44e6bb62021-06-15 21:44:32 +02001637 int result_is_zero = 0;
Hanno Becker73d7d792018-12-11 10:35:51 +00001638 MPI_VALIDATE_RET( X != NULL );
1639 MPI_VALIDATE_RET( A != NULL );
1640 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1645 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001646
Paul Bakker23986e52011-04-24 08:57:21 +00001647 for( i = A->n; i > 0; i-- )
1648 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001649 break;
Gilles Peskine1d6b1dc2021-06-17 14:35:25 +02001650 if( i == 0 )
Gilles Peskine44e6bb62021-06-15 21:44:32 +02001651 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001652
Paul Bakker23986e52011-04-24 08:57:21 +00001653 for( j = B->n; j > 0; j-- )
1654 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001655 break;
Gilles Peskine1d6b1dc2021-06-17 14:35:25 +02001656 if( j == 0 )
Gilles Peskine44e6bb62021-06-15 21:44:32 +02001657 result_is_zero = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001658
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1660 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001662 for( ; j > 0; j-- )
1663 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
Gilles Peskineab6ab6a2021-06-10 15:51:54 +02001665 /* If the result is 0, we don't shortcut the operation, which reduces
1666 * but does not eliminate side channels leaking the zero-ness. We do
1667 * need to take care to set the sign bit properly since the library does
1668 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine44e6bb62021-06-15 21:44:32 +02001669 if( result_is_zero )
Gilles Peskineab6ab6a2021-06-10 15:51:54 +02001670 X->s = 1;
Gilles Peskineab6ab6a2021-06-10 15:51:54 +02001671 else
1672 X->s = A->s * B->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
1674cleanup:
1675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001677
1678 return( ret );
1679}
1680
1681/*
1682 * Baseline multiplication: X = A * b
1683 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001685{
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001686 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001688 MPI_VALIDATE_RET( X != NULL );
1689 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001691 B.s = 1;
1692 B.n = 1;
1693 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001694 p[0] = b;
1695
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001696 return( mbedtls_mpi_mul_mpi( X, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697}
1698
1699/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001700 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1701 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001702 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001703static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1704 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001705{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001706#if defined(MBEDTLS_HAVE_UDBL)
1707 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001708#else
Simon Butcher9803d072016-01-03 00:24:34 +00001709 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1710 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001711 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1712 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001713 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001714#endif
1715
Simon Butcher15b15d12015-11-26 19:35:03 +00001716 /*
1717 * Check for overflow
1718 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001719 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001720 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001721 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001722
Simon Butcherf5ba0452015-12-27 23:01:55 +00001723 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001724 }
1725
1726#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001727 dividend = (mbedtls_t_udbl) u1 << biL;
1728 dividend |= (mbedtls_t_udbl) u0;
1729 quotient = dividend / d;
1730 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1731 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1732
1733 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001734 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001735
1736 return (mbedtls_mpi_uint) quotient;
1737#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001738
1739 /*
1740 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1741 * Vol. 2 - Seminumerical Algorithms, Knuth
1742 */
1743
1744 /*
1745 * Normalize the divisor, d, and dividend, u0, u1
1746 */
1747 s = mbedtls_clz( d );
1748 d = d << s;
1749
1750 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001751 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001752 u0 = u0 << s;
1753
1754 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001755 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001756
1757 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001758 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001759
1760 /*
1761 * Find the first quotient and remainder
1762 */
1763 q1 = u1 / d1;
1764 r0 = u1 - d1 * q1;
1765
1766 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1767 {
1768 q1 -= 1;
1769 r0 += d1;
1770
1771 if ( r0 >= radix ) break;
1772 }
1773
Simon Butcherf5ba0452015-12-27 23:01:55 +00001774 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001775 q0 = rAX / d1;
1776 r0 = rAX - q0 * d1;
1777
1778 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1779 {
1780 q0 -= 1;
1781 r0 += d1;
1782
1783 if ( r0 >= radix ) break;
1784 }
1785
1786 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001787 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001788
1789 quotient = q1 * radix + q0;
1790
1791 return quotient;
1792#endif
1793}
1794
1795/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001796 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001797 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001798int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1799 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001800{
Paul Bakker23986e52011-04-24 08:57:21 +00001801 int ret;
1802 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001804 MPI_VALIDATE_RET( A != NULL );
1805 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1808 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1811 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001814 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1816 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817 return( 0 );
1818 }
1819
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1821 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001822 X.s = Y.s = 1;
1823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1825 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1826 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1827 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001829 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001830 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001831 {
1832 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1834 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001835 }
1836 else k = 0;
1837
1838 n = X.n - 1;
1839 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001841
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 {
1844 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
1849 for( i = n; i > t ; i-- )
1850 {
1851 if( X.p[i] >= Y.p[t] )
1852 Z.p[i - t - 1] = ~0;
1853 else
1854 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001855 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1856 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001857 }
1858
1859 Z.p[i - t - 1]++;
1860 do
1861 {
1862 Z.p[i - t - 1]--;
1863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001865 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001866 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001870 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1871 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 T2.p[2] = X.p[i];
1873 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1877 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1878 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001881 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1883 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1884 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 Z.p[i - t - 1]--;
1886 }
1887 }
1888
1889 if( Q != NULL )
1890 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892 Q->s = A->s * B->s;
1893 }
1894
1895 if( R != NULL )
1896 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001898 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001900
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 R->s = 1;
1903 }
1904
1905cleanup:
1906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1908 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001909
1910 return( ret );
1911}
1912
1913/*
1914 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001915 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001916int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1917 const mbedtls_mpi *A,
1918 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001919{
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001920 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001922 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
1924 p[0] = ( b < 0 ) ? -b : b;
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001925 B.s = ( b < 0 ) ? -1 : 1;
1926 B.n = 1;
1927 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
Yuto Takanod7cd60f2021-07-14 15:03:09 +01001929 return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930}
1931
1932/*
1933 * Modulo: R = A mod B
1934 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001935int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001936{
1937 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001938 MPI_VALIDATE_RET( R != NULL );
1939 MPI_VALIDATE_RET( A != NULL );
1940 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1943 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001944
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1948 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1951 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001952
1953cleanup:
1954
1955 return( ret );
1956}
1957
1958/*
1959 * Modulo: r = A mod b
1960 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001962{
Paul Bakker23986e52011-04-24 08:57:21 +00001963 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001965 MPI_VALIDATE_RET( r != NULL );
1966 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
1968 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001969 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001970
1971 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
1974 /*
1975 * handle trivial cases
1976 */
1977 if( b == 1 )
1978 {
1979 *r = 0;
1980 return( 0 );
1981 }
1982
1983 if( b == 2 )
1984 {
1985 *r = A->p[0] & 1;
1986 return( 0 );
1987 }
1988
1989 /*
1990 * general case
1991 */
Paul Bakker23986e52011-04-24 08:57:21 +00001992 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001993 {
Paul Bakker23986e52011-04-24 08:57:21 +00001994 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001995 y = ( y << biH ) | ( x >> biH );
1996 z = y / b;
1997 y -= z * b;
1998
1999 x <<= biH;
2000 y = ( y << biH ) | ( x >> biH );
2001 z = y / b;
2002 y -= z * b;
2003 }
2004
Paul Bakkerce40a6d2009-06-23 19:46:08 +00002005 /*
2006 * If A is negative, then the current y represents a negative value.
2007 * Flipping it to the positive side.
2008 */
2009 if( A->s < 0 && y != 0 )
2010 y = b - y;
2011
Paul Bakker5121ce52009-01-03 21:22:43 +00002012 *r = y;
2013
2014 return( 0 );
2015}
2016
2017/*
2018 * Fast Montgomery initialization (thanks to Tom St Denis)
2019 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002021{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002023 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00002024
2025 x = m0;
2026 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01002028 for( i = biL; i >= 8; i /= 2 )
2029 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
2031 *mm = ~x + 1;
2032}
2033
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02002034/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
2035 *
2036 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine635a3742020-06-08 22:37:50 +02002037 * It must have at least as many limbs as N
2038 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02002039 * On successful completion, A contains the result of
2040 * the multiplication A * B * R^-1 mod N where
2041 * R = (2^ciL)^n.
2042 * \param[in] B One of the numbers to multiply.
2043 * It must be nonzero and must not have more limbs than N
2044 * (B->n <= N->n).
2045 * \param[in] N The modulo. N must be odd.
2046 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
2047 * This is -N^-1 mod 2^ciL.
2048 * \param[in,out] T A bignum for temporary storage.
2049 * It must be at least twice the limb size of N plus 2
2050 * (T->n >= 2 * (N->n + 1)).
2051 * Its initial content is unused and
2052 * its final content is indeterminate.
2053 * Note that unlike the usual convention in the library
2054 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00002055 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002056static 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 +02002057 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002058{
Paul Bakker23986e52011-04-24 08:57:21 +00002059 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00002061
2062 memset( T->p, 0, T->n * ciL );
2063
2064 d = T->p;
2065 n = N->n;
2066 m = ( B->n < n ) ? B->n : n;
2067
2068 for( i = 0; i < n; i++ )
2069 {
2070 /*
2071 * T = (T + u0*B + u1*N) / 2^biL
2072 */
2073 u0 = A->p[i];
2074 u1 = ( d[0] + u0 * B->p[0] ) * mm;
2075
2076 mpi_mul_hlp( m, B->p, d, u0 );
2077 mpi_mul_hlp( n, N->p, d, u1 );
2078
2079 *d++ = u0; d[n + 1] = 0;
2080 }
2081
Gilles Peskine635a3742020-06-08 22:37:50 +02002082 /* At this point, d is either the desired result or the desired result
2083 * plus N. We now potentially subtract N, avoiding leaking whether the
2084 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002085
Gilles Peskine635a3742020-06-08 22:37:50 +02002086 /* Copy the n least significant limbs of d to A, so that
2087 * A = d if d < N (recall that N has n limbs). */
2088 memcpy( A->p, d, n * ciL );
Gilles Peskinede719d52020-06-09 10:39:38 +02002089 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine635a3742020-06-08 22:37:50 +02002090 * do the calculation without using conditional tests. */
2091 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine8f672662020-06-04 21:05:24 +02002092 d[n] += 1;
Gilles Peskine36acd542020-06-08 21:58:22 +02002093 d[n] -= mpi_sub_hlp( n, d, N->p );
Gilles Peskine635a3742020-06-08 22:37:50 +02002094 /* If d0 < N then d < (2^biL)^n
2095 * so d[n] == 0 and we want to keep A as it is.
2096 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2097 * so d[n] == 1 and we want to set A to the result of the subtraction
2098 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2099 * This exactly corresponds to a conditional assignment. */
2100 mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101}
2102
2103/*
2104 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine3ce3ddf2020-06-04 15:00:49 +02002105 *
2106 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002107 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002108static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2109 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002110{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 mbedtls_mpi_uint z = 1;
2112 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002113
Paul Bakker8ddb6452013-02-27 14:56:33 +01002114 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002115 U.p = &z;
2116
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002117 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002118}
2119
2120/*
Manuel Pégourié-Gonnard432ebba2021-06-03 10:42:46 +02002121 * Constant-flow boolean "equal" comparison:
2122 * return x == y
2123 *
2124 * This function can be used to write constant-time code by replacing branches
2125 * with bit operations - it can be used in conjunction with
2126 * mbedtls_ssl_cf_mask_from_bit().
2127 *
2128 * This function is implemented without using comparison operators, as those
2129 * might be translated to branches by some compilers on some platforms.
2130 */
2131static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2132{
2133 /* diff = 0 if x == y, non-zero otherwise */
2134 const size_t diff = x ^ y;
2135
2136 /* MSVC has a warning about unary minus on unsigned integer types,
2137 * but this is well-defined and precisely what we want to do here. */
2138#if defined(_MSC_VER)
2139#pragma warning( push )
2140#pragma warning( disable : 4146 )
2141#endif
2142
2143 /* diff_msb's most significant bit is equal to x != y */
Manuel Pégourié-Gonnarde9eca7f2021-06-17 13:25:03 +02002144 const size_t diff_msb = ( diff | (size_t) -diff );
Manuel Pégourié-Gonnard432ebba2021-06-03 10:42:46 +02002145
2146#if defined(_MSC_VER)
2147#pragma warning( pop )
2148#endif
2149
2150 /* diff1 = (x != y) ? 1 : 0 */
2151 const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2152
2153 return( 1 ^ diff1 );
2154}
2155
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002156/**
2157 * Select an MPI from a table without leaking the index.
2158 *
2159 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2160 * reads the entire table in order to avoid leaking the value of idx to an
2161 * attacker able to observe memory access patterns.
2162 *
2163 * \param[out] R Where to write the selected MPI.
2164 * \param[in] T The table to read from.
2165 * \param[in] T_size The number of elements in the table.
2166 * \param[in] idx The index of the element to select;
2167 * this must satisfy 0 <= idx < T_size.
2168 *
2169 * \return \c 0 on success, or a negative error code.
2170 */
2171static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2172{
Manuel Pégourié-Gonnardde2ab2a2021-06-15 12:37:23 +02002173 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard6aba8fc2021-06-15 13:28:50 +02002174 size_t i;
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002175
Manuel Pégourié-Gonnard6aba8fc2021-06-15 13:28:50 +02002176 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard432ebba2021-06-03 10:42:46 +02002177 {
2178 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
Manuel Pégourié-Gonnard4fc96df2021-06-10 09:34:00 +02002179 (unsigned char) mbedtls_mpi_cf_bool_eq( i, idx ) ) );
Manuel Pégourié-Gonnard432ebba2021-06-03 10:42:46 +02002180 }
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002181
2182cleanup:
2183 return( ret );
2184}
2185
Paul Bakker5121ce52009-01-03 21:22:43 +00002186/*
2187 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2188 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002189int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2190 const mbedtls_mpi *E, const mbedtls_mpi *N,
Yuto Takano1cded872021-07-14 10:20:09 +01002191 mbedtls_mpi *prec_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002192{
Paul Bakker23986e52011-04-24 08:57:21 +00002193 int ret;
2194 size_t wbits, wsize, one = 1;
2195 size_t i, j, nblimbs;
2196 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 mbedtls_mpi_uint ei, mm, state;
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002198 mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002199 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
Hanno Becker73d7d792018-12-11 10:35:51 +00002201 MPI_VALIDATE_RET( X != NULL );
2202 MPI_VALIDATE_RET( A != NULL );
2203 MPI_VALIDATE_RET( E != NULL );
2204 MPI_VALIDATE_RET( N != NULL );
2205
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002206 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002207 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2210 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002211
Chris Jonesad59a2a2020-11-25 15:12:39 +00002212 if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2213 mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2214 return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2215
Paul Bakkerf6198c12012-05-16 08:02:29 +00002216 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002217 * Init temps and window size
2218 */
2219 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2221 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002222 mbedtls_mpi_init( &WW );
Paul Bakker5121ce52009-01-03 21:22:43 +00002223 memset( W, 0, sizeof( W ) );
2224
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002225 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002226
2227 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2228 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2229
Peter Kolbusb83d41d2018-12-11 14:01:44 -06002230#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2232 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06002233#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002234
Paul Bakker5121ce52009-01-03 21:22:43 +00002235 j = N->n + 1;
Gilles Peskinec559eac2021-06-08 23:17:42 +02002236 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2237 * and mpi_montred() calls later. Here we ensure that W[1] and X are
2238 * large enough, and later we'll grow other W[i] to the same length.
2239 * They must not be shrunk midway through this function!
2240 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002241 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2242 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2243 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002244
2245 /*
Paul Bakker50546922012-05-19 08:40:49 +00002246 * Compensate for negative A (and correct at the end)
2247 */
2248 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002249 if( neg )
2250 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002252 Apos.s = 1;
2253 A = &Apos;
2254 }
2255
2256 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 * If 1st call, pre-compute R^2 mod N
2258 */
Yuto Takano1cded872021-07-14 10:20:09 +01002259 if( prec_RR == NULL || prec_RR->p == NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +00002260 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2262 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2263 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002264
Yuto Takano1cded872021-07-14 10:20:09 +01002265 if( prec_RR != NULL )
2266 memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 }
2268 else
Yuto Takano1cded872021-07-14 10:20:09 +01002269 memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002270
2271 /*
2272 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2273 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2275 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002276 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Gilles Peskinec559eac2021-06-08 23:17:42 +02002278 /* Re-grow W[1] if necessary. This should be only necessary in one corner
2279 * case: when A == 0 represented with A.n == 0, mbedtls_mpi_copy shrinks
2280 * W[1] to 0 limbs. */
2281 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n +1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002283 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002284
2285 /*
2286 * X = R^2 * R^-1 mod N = R mod N
2287 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002289 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
2291 if( wsize > 1 )
2292 {
2293 /*
2294 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2295 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002296 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2299 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002300
2301 for( i = 0; i < wsize - 1; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002302 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002303
Paul Bakker5121ce52009-01-03 21:22:43 +00002304 /*
2305 * W[i] = W[i - 1] * W[1]
2306 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002307 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2310 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002312 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313 }
2314 }
2315
2316 nblimbs = E->n;
2317 bufsize = 0;
2318 nbits = 0;
2319 wbits = 0;
2320 state = 0;
2321
2322 while( 1 )
2323 {
2324 if( bufsize == 0 )
2325 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002326 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 break;
2328
Paul Bakker0d7702c2013-10-29 16:18:35 +01002329 nblimbs--;
2330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 }
2333
2334 bufsize--;
2335
2336 ei = (E->p[nblimbs] >> bufsize) & 1;
2337
2338 /*
2339 * skip leading 0s
2340 */
2341 if( ei == 0 && state == 0 )
2342 continue;
2343
2344 if( ei == 0 && state == 1 )
2345 {
2346 /*
2347 * out of window, square X
2348 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002349 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350 continue;
2351 }
2352
2353 /*
2354 * add ei to current window
2355 */
2356 state = 2;
2357
2358 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002359 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
2361 if( nbits == wsize )
2362 {
2363 /*
2364 * X = X^wsize R^-1 mod N
2365 */
2366 for( i = 0; i < wsize; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002367 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
2369 /*
2370 * X = X * W[wbits] R^-1 mod N
2371 */
Manuel Pégourié-Gonnard4fc96df2021-06-10 09:34:00 +02002372 MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002373 mpi_montmul( X, &WW, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002374
2375 state--;
2376 nbits = 0;
2377 wbits = 0;
2378 }
2379 }
2380
2381 /*
2382 * process the remaining bits
2383 */
2384 for( i = 0; i < nbits; i++ )
2385 {
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002386 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
2388 wbits <<= 1;
2389
Paul Bakker66d5d072014-06-17 16:39:18 +02002390 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002391 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392 }
2393
2394 /*
2395 * X = A^E * R * R^-1 mod N = A^E mod N
2396 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002397 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002398
Hanno Beckera4af1c42017-04-18 09:07:45 +01002399 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002400 {
2401 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002403 }
2404
Paul Bakker5121ce52009-01-03 21:22:43 +00002405cleanup:
2406
Paul Bakker66d5d072014-06-17 16:39:18 +02002407 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Manuel Pégourié-Gonnard87bd4442021-03-09 11:22:20 +01002411 mbedtls_mpi_free( &WW );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002412
Yuto Takano1cded872021-07-14 10:20:09 +01002413 if( prec_RR == NULL || prec_RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002415
2416 return( ret );
2417}
2418
Paul Bakker5121ce52009-01-03 21:22:43 +00002419/*
2420 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2421 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002423{
Paul Bakker23986e52011-04-24 08:57:21 +00002424 int ret;
2425 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002427
Hanno Becker73d7d792018-12-11 10:35:51 +00002428 MPI_VALIDATE_RET( G != NULL );
2429 MPI_VALIDATE_RET( A != NULL );
2430 MPI_VALIDATE_RET( B != NULL );
2431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2435 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 lz = mbedtls_mpi_lsb( &TA );
2438 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002439
Gilles Peskine5504d172021-06-09 13:26:43 +02002440 /* The loop below gives the correct result when A==0 but not when B==0.
2441 * So have a special case for B==0. Leverage the fact that we just
2442 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2443 * slightly more efficient than cmp_int(). */
2444 if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2445 {
2446 ret = mbedtls_mpi_copy( G, A );
2447 goto cleanup;
2448 }
2449
Paul Bakker66d5d072014-06-17 16:39:18 +02002450 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002451 lz = lzt;
2452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2454 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002455
Paul Bakker5121ce52009-01-03 21:22:43 +00002456 TA.s = TB.s = 1;
2457
Gilles Peskineafbf1912021-06-16 13:42:04 +02002458 /* We mostly follow the procedure described in HAC 14.54, but with some
2459 * minor differences:
2460 * - Sequences of multiplications or divisions by 2 are grouped into a
2461 * single shift operation.
Gilles Peskine18efd1c2021-06-21 18:58:39 +02002462 * - The procedure in HAC assumes that 0 < TB <= TA.
2463 * - The condition TB <= TA is not actually necessary for correctness.
2464 * TA and TB have symmetric roles except for the loop termination
2465 * condition, and the shifts at the beginning of the loop body
2466 * remove any significance from the ordering of TA vs TB before
2467 * the shifts.
2468 * - If TA = 0, the loop goes through 0 iterations and the result is
2469 * correctly TB.
2470 * - The case TB = 0 was short-circuited above.
Gilles Peskineafbf1912021-06-16 13:42:04 +02002471 *
2472 * For the correctness proof below, decompose the original values of
2473 * A and B as
2474 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2475 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2476 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2477 * and gcd(A',B') is odd or 0.
2478 *
2479 * At the beginning, we have TA = |A|/2^a and TB = |B|/2^b.
2480 * The code maintains the following invariant:
2481 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine2949d3a2021-06-15 22:09:39 +02002482 */
2483
Gilles Peskineafbf1912021-06-16 13:42:04 +02002484 /* Proof that the loop terminates:
2485 * At each iteration, either the right-shift by 1 is made on a nonzero
2486 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2487 * by at least 1, or the right-shift by 1 is made on zero and then
2488 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2489 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2490 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002491 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002492 {
Gilles Peskineafbf1912021-06-16 13:42:04 +02002493 /* Divisions by 2 preserve the invariant (I). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2495 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002496
Gilles Peskineafbf1912021-06-16 13:42:04 +02002497 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2498 * TA-TB is even so the division by 2 has an integer result.
2499 * Invariant (I) is preserved since any odd divisor of both TA and TB
2500 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2501 * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
2502 * divides TA.
2503 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002505 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2507 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002508 }
2509 else
2510 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2512 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513 }
Gilles Peskineafbf1912021-06-16 13:42:04 +02002514 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 }
2516
Gilles Peskineafbf1912021-06-16 13:42:04 +02002517 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2518 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2519 * - If there was at least one loop iteration, then one of TA or TB is odd,
2520 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2521 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2522 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskinef95d4332021-06-21 11:40:38 +02002523 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskineafbf1912021-06-16 13:42:04 +02002524 */
2525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2527 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002528
2529cleanup:
2530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002531 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002532
2533 return( ret );
2534}
2535
Paul Bakker33dc46b2014-04-30 16:11:39 +02002536/*
2537 * Fill X with size bytes of random.
2538 *
2539 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002540 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002541 * deterministic, eg for tests).
2542 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002544 int (*f_rng)(void *, unsigned char *, size_t),
2545 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002546{
Paul Bakker23986e52011-04-24 08:57:21 +00002547 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002548 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002549 size_t const overhead = ( limbs * ciL ) - size;
2550 unsigned char *Xp;
2551
Hanno Becker8ce11a32018-12-19 16:18:52 +00002552 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002553 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002554
Hanno Beckerda1655a2017-10-18 14:21:44 +01002555 /* Ensure that target MPI has exactly the necessary number of limbs */
2556 if( X->n != limbs )
2557 {
2558 mbedtls_mpi_free( X );
2559 mbedtls_mpi_init( X );
2560 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2561 }
2562 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002563
Hanno Beckerda1655a2017-10-18 14:21:44 +01002564 Xp = (unsigned char*) X->p;
Gilles Peskine05251142020-11-25 16:15:14 +01002565 MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002566
Hanno Becker2be8a552018-10-25 12:40:09 +01002567 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002568
2569cleanup:
2570 return( ret );
2571}
2572
Paul Bakker5121ce52009-01-03 21:22:43 +00002573/*
2574 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2575 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002577{
2578 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002580 MPI_VALIDATE_RET( X != NULL );
2581 MPI_VALIDATE_RET( A != NULL );
2582 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002583
Hanno Becker4bcb4912017-04-18 15:49:39 +01002584 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2588 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2589 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002594 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 goto cleanup;
2597 }
2598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002599 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2600 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2601 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2602 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2605 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2606 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2607 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002608
2609 do
2610 {
2611 while( ( TU.p[0] & 1 ) == 0 )
2612 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002613 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002614
2615 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2616 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2618 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002619 }
2620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002621 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2622 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002623 }
2624
2625 while( ( TV.p[0] & 1 ) == 0 )
2626 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002627 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002628
2629 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2630 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002631 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2632 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 }
2634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2636 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002637 }
2638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002639 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002640 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002641 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2642 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2643 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002644 }
2645 else
2646 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2648 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2649 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002650 }
2651 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002652 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002653
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2655 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2658 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
2662cleanup:
2663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002664 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2665 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2666 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002667
2668 return( ret );
2669}
2670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002672
Paul Bakker5121ce52009-01-03 21:22:43 +00002673static const int small_prime[] =
2674{
2675 3, 5, 7, 11, 13, 17, 19, 23,
2676 29, 31, 37, 41, 43, 47, 53, 59,
2677 61, 67, 71, 73, 79, 83, 89, 97,
2678 101, 103, 107, 109, 113, 127, 131, 137,
2679 139, 149, 151, 157, 163, 167, 173, 179,
2680 181, 191, 193, 197, 199, 211, 223, 227,
2681 229, 233, 239, 241, 251, 257, 263, 269,
2682 271, 277, 281, 283, 293, 307, 311, 313,
2683 317, 331, 337, 347, 349, 353, 359, 367,
2684 373, 379, 383, 389, 397, 401, 409, 419,
2685 421, 431, 433, 439, 443, 449, 457, 461,
2686 463, 467, 479, 487, 491, 499, 503, 509,
2687 521, 523, 541, 547, 557, 563, 569, 571,
2688 577, 587, 593, 599, 601, 607, 613, 617,
2689 619, 631, 641, 643, 647, 653, 659, 661,
2690 673, 677, 683, 691, 701, 709, 719, 727,
2691 733, 739, 743, 751, 757, 761, 769, 773,
2692 787, 797, 809, 811, 821, 823, 827, 829,
2693 839, 853, 857, 859, 863, 877, 881, 883,
2694 887, 907, 911, 919, 929, 937, 941, 947,
2695 953, 967, 971, 977, 983, 991, 997, -103
2696};
2697
2698/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002699 * Small divisors test (X must be positive)
2700 *
2701 * Return values:
2702 * 0: no small factor (possible prime, more tests needed)
2703 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002705 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002706 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002707static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002708{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002709 int ret = 0;
2710 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002712
Paul Bakker5121ce52009-01-03 21:22:43 +00002713 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002714 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002715
2716 for( i = 0; small_prime[i] > 0; i++ )
2717 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002718 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002719 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002721 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002722
2723 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002724 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002725 }
2726
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002727cleanup:
2728 return( ret );
2729}
2730
2731/*
2732 * Miller-Rabin pseudo-primality test (HAC 4.24)
2733 */
Janos Follathda31fa12018-09-03 14:45:23 +01002734static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002735 int (*f_rng)(void *, unsigned char *, size_t),
2736 void *p_rng )
2737{
Pascal Junodb99183d2015-03-11 16:49:45 +01002738 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002739 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002740 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002741
Hanno Becker8ce11a32018-12-19 16:18:52 +00002742 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002743 MPI_VALIDATE_RET( f_rng != NULL );
2744
2745 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2746 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002748
Paul Bakker5121ce52009-01-03 21:22:43 +00002749 /*
2750 * W = |X| - 1
2751 * R = W >> lsb( W )
2752 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002753 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2754 s = mbedtls_mpi_lsb( &W );
2755 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2756 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002757
Janos Follathda31fa12018-09-03 14:45:23 +01002758 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002759 {
2760 /*
2761 * pick a random A, 1 < A < |X| - 1
2762 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002763 count = 0;
2764 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002765 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002766
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002767 j = mbedtls_mpi_bitlen( &A );
2768 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002769 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002770 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002771 }
2772
2773 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002774 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2775 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002776 }
2777
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002778 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2779 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002780
2781 /*
2782 * A = A^R mod |X|
2783 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002784 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002785
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002786 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2787 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002788 continue;
2789
2790 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002791 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002792 {
2793 /*
2794 * A = A * A mod |X|
2795 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002796 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2797 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002799 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002800 break;
2801
2802 j++;
2803 }
2804
2805 /*
2806 * not prime if A != |X| - 1 or A == 1
2807 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002808 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2809 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002810 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002812 break;
2813 }
2814 }
2815
2816cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002817 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2818 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002819 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002820
2821 return( ret );
2822}
2823
2824/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002825 * Pseudo-primality test: small factors, then Miller-Rabin
2826 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002827int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2828 int (*f_rng)(void *, unsigned char *, size_t),
2829 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002830{
2831 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002832 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002833 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002834 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002835
2836 XX.s = 1;
2837 XX.n = X->n;
2838 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002839
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002840 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2841 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2842 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002844 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002845 return( 0 );
2846
2847 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2848 {
2849 if( ret == 1 )
2850 return( 0 );
2851
2852 return( ret );
2853 }
2854
Janos Follathda31fa12018-09-03 14:45:23 +01002855 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002856}
2857
Janos Follatha0b67c22018-09-18 14:48:23 +01002858#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002859/*
2860 * Pseudo-primality test, error probability 2^-80
2861 */
2862int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2863 int (*f_rng)(void *, unsigned char *, size_t),
2864 void *p_rng )
2865{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002866 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002867 MPI_VALIDATE_RET( f_rng != NULL );
2868
Janos Follatha0b67c22018-09-18 14:48:23 +01002869 /*
2870 * In the past our key generation aimed for an error rate of at most
2871 * 2^-80. Since this function is deprecated, aim for the same certainty
2872 * here as well.
2873 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002874 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002875}
Janos Follatha0b67c22018-09-18 14:48:23 +01002876#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002877
2878/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002879 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002880 *
Janos Follathf301d232018-08-14 13:34:01 +01002881 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2882 * be either 1024 bits or 1536 bits long, and flags must contain
2883 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002884 */
Janos Follath7c025a92018-08-14 11:08:41 +01002885int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002886 int (*f_rng)(void *, unsigned char *, size_t),
2887 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002888{
Jethro Beekman66689272018-02-14 19:24:10 -08002889#ifdef MBEDTLS_HAVE_INT64
2890// ceil(2^63.5)
2891#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2892#else
2893// ceil(2^31.5)
2894#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2895#endif
2896 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002897 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002898 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002899 mbedtls_mpi_uint r;
2900 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002901
Hanno Becker8ce11a32018-12-19 16:18:52 +00002902 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002903 MPI_VALIDATE_RET( f_rng != NULL );
2904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002905 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2906 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002907
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002908 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002909
2910 n = BITS_TO_LIMBS( nbits );
2911
Janos Follathda31fa12018-09-03 14:45:23 +01002912 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2913 {
2914 /*
2915 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2916 */
2917 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2918 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2919 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2920 }
2921 else
2922 {
2923 /*
2924 * 2^-100 error probability, number of rounds computed based on HAC,
2925 * fact 4.48
2926 */
2927 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2928 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2929 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2930 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2931 }
2932
Jethro Beekman66689272018-02-14 19:24:10 -08002933 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002934 {
Jethro Beekman66689272018-02-14 19:24:10 -08002935 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2936 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2937 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2938
2939 k = n * biL;
2940 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2941 X->p[0] |= 1;
2942
Janos Follath7c025a92018-08-14 11:08:41 +01002943 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002944 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002945 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002946
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002947 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002948 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002949 }
Jethro Beekman66689272018-02-14 19:24:10 -08002950 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002951 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002952 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002953 * An necessary condition for Y and X = 2Y + 1 to be prime
2954 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2955 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002956 */
Jethro Beekman66689272018-02-14 19:24:10 -08002957
2958 X->p[0] |= 2;
2959
2960 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2961 if( r == 0 )
2962 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2963 else if( r == 1 )
2964 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2965
2966 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2967 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2968 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2969
2970 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002971 {
Jethro Beekman66689272018-02-14 19:24:10 -08002972 /*
2973 * First, check small factors for X and Y
2974 * before doing Miller-Rabin on any of them
2975 */
2976 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2977 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002978 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002979 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002980 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002981 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002982 goto cleanup;
2983
2984 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2985 goto cleanup;
2986
2987 /*
2988 * Next candidates. We want to preserve Y = (X-1) / 2 and
2989 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2990 * so up Y by 6 and X by 12.
2991 */
2992 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2993 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002994 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002995 }
2996 }
2997
2998cleanup:
2999
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003000 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00003001
3002 return( ret );
3003}
3004
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003005#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003006
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003007#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003008
Paul Bakker23986e52011-04-24 08:57:21 +00003009#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003010
3011static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3012{
3013 { 693, 609, 21 },
3014 { 1764, 868, 28 },
3015 { 768454923, 542167814, 1 }
3016};
3017
Paul Bakker5121ce52009-01-03 21:22:43 +00003018/*
3019 * Checkup routine
3020 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003021int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00003022{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003023 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003024 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003025
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003026 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
3027 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003029 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003030 "EFE021C2645FD1DC586E69184AF4A31E" \
3031 "D5F53E93B5F123FA41680867BA110131" \
3032 "944FE7952E2517337780CB0DB80E61AA" \
3033 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003035 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003036 "B2E7EFD37075B9F03FF989C7C5051C20" \
3037 "34D2A323810251127E7BF8625A4F49A5" \
3038 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3039 "5B5C25763222FEFCCFC38B832366C29E" ) );
3040
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003041 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003042 "0066A198186C18C10B2F5ED9B522752A" \
3043 "9830B69916E535C8F047518A889A43A5" \
3044 "94B6BED27A168D31D4A52F88925AA8F5" ) );
3045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003046 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003048 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003049 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3050 "9E857EA95A03512E2BAE7391688D264A" \
3051 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3052 "8001B72E848A38CAE1C65F78E56ABDEF" \
3053 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3054 "ECF677152EF804370C1A305CAF3B5BF1" \
3055 "30879B56C61DE584A0F53A2447A51E" ) );
3056
3057 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003058 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003060 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003061 {
3062 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003063 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003064
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003065 ret = 1;
3066 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003067 }
3068
3069 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003070 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003072 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003073
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003074 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003075 "256567336059E52CAE22925474705F39A94" ) );
3076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003077 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003078 "6613F26162223DF488E9CD48CC132C7A" \
3079 "0AC93C701B001B092E4E5B9F73BCD27B" \
3080 "9EE50D0657C77F374E903CDFA4C642" ) );
3081
3082 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003083 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003085 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3086 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003087 {
3088 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003089 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003090
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003091 ret = 1;
3092 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003093 }
3094
3095 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003096 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003097
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003098 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003100 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003101 "36E139AEA55215609D2816998ED020BB" \
3102 "BD96C37890F65171D948E9BC7CBAA4D9" \
3103 "325D24D6A3C12710F10A09FA08AB87" ) );
3104
3105 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003106 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003108 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003109 {
3110 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003111 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003112
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003113 ret = 1;
3114 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003115 }
3116
3117 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003118 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003120 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00003121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003122 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00003123 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3124 "C3DBA76456363A10869622EAC2DD84EC" \
3125 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3126
3127 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003128 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00003129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003130 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00003131 {
3132 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003133 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003134
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003135 ret = 1;
3136 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003137 }
3138
3139 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003140 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003141
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003142 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003143 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003144
Paul Bakker66d5d072014-06-17 16:39:18 +02003145 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003146 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003147 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3148 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003150 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003152 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003153 {
3154 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003155 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003156
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003157 ret = 1;
3158 goto cleanup;
3159 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003160 }
3161
3162 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003163 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003164
Paul Bakker5121ce52009-01-03 21:22:43 +00003165cleanup:
3166
3167 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003168 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00003169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003170 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3171 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00003172
3173 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003174 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00003175
3176 return( ret );
3177}
3178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003179#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003181#endif /* MBEDTLS_BIGNUM_C */