blob: 7d1843029dc2e9b182486419bc1df9deb4e4f176 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
Gilles Peskine27c15c72020-01-20 21:17:43 +0100160 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine56427c22020-01-21 13:59:51 +0100163 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164
165 for( i = X->n - 1; i > 0; i-- )
166 if( X->p[i] != 0 )
167 break;
168 i++;
169
170 if( i < nblimbs )
171 i = nblimbs;
172
Simon Butcher29176892016-05-20 00:19:09 +0100173 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200174 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100176 if( X->p != NULL )
177 {
178 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200179 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100181 }
182
183 X->n = i;
184 X->p = p;
185
186 return( 0 );
187}
188
189/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000190 * Copy the contents of Y into X
191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000193{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100194 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000195 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000196 MPI_VALIDATE_RET( X != NULL );
197 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
199 if( X == Y )
200 return( 0 );
201
Gilles Peskine3e9f5222020-01-20 21:12:50 +0100202 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200205 return( 0 );
206 }
207
Paul Bakker5121ce52009-01-03 21:22:43 +0000208 for( i = Y->n - 1; i > 0; i-- )
209 if( Y->p[i] != 0 )
210 break;
211 i++;
212
213 X->s = Y->s;
214
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100215 if( X->n < i )
216 {
217 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
218 }
219 else
220 {
221 memset( X->p + i, 0, ( X->n - i ) * ciL );
222 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 memcpy( X->p, Y->p, i * ciL );
225
226cleanup:
227
228 return( ret );
229}
230
231/*
232 * Swap the contents of X and Y
233 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000235{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000237 MPI_VALIDATE( X != NULL );
238 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 memcpy( &T, X, sizeof( mbedtls_mpi ) );
241 memcpy( X, Y, sizeof( mbedtls_mpi ) );
242 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000243}
244
245/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100246 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100247 * about whether the assignment was made or not.
248 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100251{
252 int ret = 0;
253 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000254 MPI_VALIDATE_RET( X != NULL );
255 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100256
Pascal Junodb99183d2015-03-11 16:49:45 +0100257 /* make sure assign is 0 or 1 in a time-constant manner */
258 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100261
Paul Bakker66d5d072014-06-17 16:39:18 +0200262 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100263
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100264 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200265 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100266
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100267 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200268 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100269
270cleanup:
271 return( ret );
272}
273
274/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275 * Conditionally swap X and Y, without leaking information
276 * about whether the swap was made or not.
277 * Here it is not ok to simply swap the pointers, which whould lead to
278 * different memory access patterns when X and Y are used afterwards.
279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281{
282 int ret, s;
283 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000285 MPI_VALIDATE_RET( X != NULL );
286 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100287
288 if( X == Y )
289 return( 0 );
290
Pascal Junodb99183d2015-03-11 16:49:45 +0100291 /* make sure swap is 0 or 1 in a time-constant manner */
292 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
295 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100296
297 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200298 X->s = X->s * ( 1 - swap ) + Y->s * swap;
299 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100300
301
302 for( i = 0; i < X->n; i++ )
303 {
304 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200305 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
306 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100307 }
308
309cleanup:
310 return( ret );
311}
312
313/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000314 * Set value from integer
315 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000317{
318 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000319 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000322 memset( X->p, 0, X->n * ciL );
323
324 X->p[0] = ( z < 0 ) ? -z : z;
325 X->s = ( z < 0 ) ? -1 : 1;
326
327cleanup:
328
329 return( ret );
330}
331
332/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000333 * Get a specific bit
334 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000336{
Hanno Becker73d7d792018-12-11 10:35:51 +0000337 MPI_VALIDATE_RET( X != NULL );
338
Paul Bakker2f5947e2011-05-18 15:47:11 +0000339 if( X->n * biL <= pos )
340 return( 0 );
341
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200342 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343}
344
Gilles Peskine11cdb052018-11-20 16:47:47 +0100345/* Get a specific byte, without range checks. */
346#define GET_BYTE( X, i ) \
347 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
348
Paul Bakker2f5947e2011-05-18 15:47:11 +0000349/*
350 * Set a bit to a specific value of 0 or 1
351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000353{
354 int ret = 0;
355 size_t off = pos / biL;
356 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000357 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000358
359 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200361
Paul Bakker2f5947e2011-05-18 15:47:11 +0000362 if( X->n * biL <= pos )
363 {
364 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200365 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000368 }
369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
371 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000372
373cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200374
Paul Bakker2f5947e2011-05-18 15:47:11 +0000375 return( ret );
376}
377
378/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200379 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000380 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000382{
Paul Bakker23986e52011-04-24 08:57:21 +0000383 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000384 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000385
386 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000387 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000388 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
389 return( count );
390
391 return( 0 );
392}
393
394/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000395 * Count leading zero bits in a given integer
396 */
397static size_t mbedtls_clz( const mbedtls_mpi_uint x )
398{
399 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100400 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000401
402 for( j = 0; j < biL; j++ )
403 {
404 if( x & mask ) break;
405
406 mask >>= 1;
407 }
408
409 return j;
410}
411
412/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200413 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000414 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200415size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000416{
Paul Bakker23986e52011-04-24 08:57:21 +0000417 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000418
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200419 if( X->n == 0 )
420 return( 0 );
421
Paul Bakker5121ce52009-01-03 21:22:43 +0000422 for( i = X->n - 1; i > 0; i-- )
423 if( X->p[i] != 0 )
424 break;
425
Simon Butcher15b15d12015-11-26 19:35:03 +0000426 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
Paul Bakker23986e52011-04-24 08:57:21 +0000428 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000429}
430
431/*
432 * Return the total size in bytes
433 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000435{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200436 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000437}
438
439/*
440 * Convert an ASCII character to digit value
441 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000443{
444 *d = 255;
445
446 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
447 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
448 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 if( *d >= (mbedtls_mpi_uint) radix )
451 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452
453 return( 0 );
454}
455
456/*
457 * Import from an ASCII string
458 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000460{
Paul Bakker23986e52011-04-24 08:57:21 +0000461 int ret;
462 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 mbedtls_mpi_uint d;
464 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000465 MPI_VALIDATE_RET( X != NULL );
466 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467
468 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000469 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Paul Bakkerff60ee62010-03-16 21:09:09 +0000473 slen = strlen( s );
474
Paul Bakker5121ce52009-01-03 21:22:43 +0000475 if( radix == 16 )
476 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100477 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200478 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
479
Paul Bakkerff60ee62010-03-16 21:09:09 +0000480 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
483 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
Paul Bakker23986e52011-04-24 08:57:21 +0000485 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000486 {
Paul Bakker23986e52011-04-24 08:57:21 +0000487 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 {
489 X->s = -1;
490 break;
491 }
492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200494 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000495 }
496 }
497 else
498 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
Paul Bakkerff60ee62010-03-16 21:09:09 +0000501 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 {
503 if( i == 0 && s[i] == '-' )
504 {
505 X->s = -1;
506 continue;
507 }
508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
510 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000511
512 if( X->s == 1 )
513 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000515 }
516 else
517 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000519 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000520 }
521 }
522
523cleanup:
524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000526
527 return( ret );
528}
529
530/*
Ron Eldora16fa292018-11-20 14:07:01 +0200531 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 */
Ron Eldora16fa292018-11-20 14:07:01 +0200533static int mpi_write_hlp( mbedtls_mpi *X, int radix,
534 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000535{
536 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200538 size_t length = 0;
539 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000540
Ron Eldora16fa292018-11-20 14:07:01 +0200541 do
542 {
543 if( length >= buflen )
544 {
545 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
546 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
Ron Eldora16fa292018-11-20 14:07:01 +0200548 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
549 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
550 /*
551 * Write the residue in the current position, as an ASCII character.
552 */
553 if( r < 0xA )
554 *(--p_end) = (char)( '0' + r );
555 else
556 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
Ron Eldora16fa292018-11-20 14:07:01 +0200558 length++;
559 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Ron Eldora16fa292018-11-20 14:07:01 +0200561 memmove( *p, p_end, length );
562 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
564cleanup:
565
566 return( ret );
567}
568
569/*
570 * Export into an ASCII string
571 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100572int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
573 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000574{
Paul Bakker23986e52011-04-24 08:57:21 +0000575 int ret = 0;
576 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000577 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000579 MPI_VALIDATE_RET( X != NULL );
580 MPI_VALIDATE_RET( olen != NULL );
581 MPI_VALIDATE_RET( buflen == 0 || buf != 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
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000586 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
587 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
588 * `n`. If radix > 4, this might be a strict
589 * overapproximation of the number of
590 * radix-adic digits needed to present `n`. */
591 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
592 * present `n`. */
593
Janos Follath870ed002019-03-06 13:43:02 +0000594 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000595 n += 1; /* Compensate for the divisions above, which round down `n`
596 * in case it's not even. */
597 n += 1; /* Potential '-'-sign. */
598 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
599 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000600
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100601 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000602 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100603 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000605 }
606
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100607 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000611 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000612 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000613 buflen--;
614 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000615
616 if( radix == 16 )
617 {
Paul Bakker23986e52011-04-24 08:57:21 +0000618 int c;
619 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000620
Paul Bakker23986e52011-04-24 08:57:21 +0000621 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000622 {
Paul Bakker23986e52011-04-24 08:57:21 +0000623 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000624 {
Paul Bakker23986e52011-04-24 08:57:21 +0000625 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000626
Paul Bakker6c343d72014-07-10 14:36:19 +0200627 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000628 continue;
629
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000630 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000631 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 k = 1;
633 }
634 }
635 }
636 else
637 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000639
640 if( T.s == -1 )
641 T.s = 1;
642
Ron Eldora16fa292018-11-20 14:07:01 +0200643 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000644 }
645
646 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100647 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000648
649cleanup:
650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
653 return( ret );
654}
655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000657/*
658 * Read X from an opened file
659 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000661{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000663 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000664 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000665 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000666 * Buffer should have space for (short) label and decimal formatted MPI,
667 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000668 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
Hanno Becker73d7d792018-12-11 10:35:51 +0000671 MPI_VALIDATE_RET( X != NULL );
672 MPI_VALIDATE_RET( fin != NULL );
673
674 if( radix < 2 || radix > 16 )
675 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
676
Paul Bakker5121ce52009-01-03 21:22:43 +0000677 memset( s, 0, sizeof( s ) );
678 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
681 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000682 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000684
Hanno Beckerb2034b72017-04-26 11:46:46 +0100685 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
686 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
688 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100689 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000690 if( mpi_get_digit( &d, radix, *p ) != 0 )
691 break;
692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000694}
695
696/*
697 * Write X into an opened file (or stdout if fout == NULL)
698 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000700{
Paul Bakker23986e52011-04-24 08:57:21 +0000701 int ret;
702 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000703 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000704 * Buffer should have space for (short) label and decimal formatted MPI,
705 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000706 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000708 MPI_VALIDATE_RET( X != NULL );
709
710 if( radix < 2 || radix > 16 )
711 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000712
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100713 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100715 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
717 if( p == NULL ) p = "";
718
719 plen = strlen( p );
720 slen = strlen( s );
721 s[slen++] = '\r';
722 s[slen++] = '\n';
723
724 if( fout != NULL )
725 {
726 if( fwrite( p, 1, plen, fout ) != plen ||
727 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000729 }
730 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733cleanup:
734
735 return( ret );
736}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
Hanno Beckerda1655a2017-10-18 14:21:44 +0100739
740/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
741 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000742
743static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
744{
745 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100746 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000747 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100748
749 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
750 {
751 tmp <<= CHAR_BIT;
752 tmp |= (mbedtls_mpi_uint) *x_ptr;
753 }
754
Hanno Beckerf8720072018-11-08 11:53:49 +0000755 return( tmp );
756}
757
758static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
759{
760#if defined(__BYTE_ORDER__)
761
762/* Nothing to do on bigendian systems. */
763#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
764 return( x );
765#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
766
767#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
768
769/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000770#if defined(__GNUC__) && defined(__GNUC_PREREQ)
771#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000772#define have_bswap
773#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000774#endif
775
776#if defined(__clang__) && defined(__has_builtin)
777#if __has_builtin(__builtin_bswap32) && \
778 __has_builtin(__builtin_bswap64)
779#define have_bswap
780#endif
781#endif
782
Hanno Beckerf8720072018-11-08 11:53:49 +0000783#if defined(have_bswap)
784 /* The compiler is hopefully able to statically evaluate this! */
785 switch( sizeof(mbedtls_mpi_uint) )
786 {
787 case 4:
788 return( __builtin_bswap32(x) );
789 case 8:
790 return( __builtin_bswap64(x) );
791 }
792#endif
793#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
794#endif /* __BYTE_ORDER__ */
795
796 /* Fall back to C-based reordering if we don't know the byte order
797 * or we couldn't use a compiler-specific builtin. */
798 return( mpi_uint_bigendian_to_host_c( x ) );
799}
800
Hanno Becker2be8a552018-10-25 12:40:09 +0100801static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100802{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100803 mbedtls_mpi_uint *cur_limb_left;
804 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100805 if( limbs == 0 )
806 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100807
808 /*
809 * Traverse limbs and
810 * - adapt byte-order in each limb
811 * - swap the limbs themselves.
812 * For that, simultaneously traverse the limbs from left to right
813 * and from right to left, as long as the left index is not bigger
814 * than the right index (it's not a problem if limbs is odd and the
815 * indices coincide in the last iteration).
816 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100817 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
818 cur_limb_left <= cur_limb_right;
819 cur_limb_left++, cur_limb_right-- )
820 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000821 mbedtls_mpi_uint tmp;
822 /* Note that if cur_limb_left == cur_limb_right,
823 * this code effectively swaps the bytes only once. */
824 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
825 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
826 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100827 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100828}
829
Paul Bakker5121ce52009-01-03 21:22:43 +0000830/*
831 * Import X from unsigned binary data, big endian
832 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000834{
Paul Bakker23986e52011-04-24 08:57:21 +0000835 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100836 size_t const limbs = CHARS_TO_LIMBS( buflen );
837 size_t const overhead = ( limbs * ciL ) - buflen;
838 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000839
Hanno Becker8ce11a32018-12-19 16:18:52 +0000840 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000841 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
842
Hanno Becker073c1992017-10-17 15:17:27 +0100843 /* Ensure that target MPI has exactly the necessary number of limbs */
844 if( X->n != limbs )
845 {
846 mbedtls_mpi_free( X );
847 mbedtls_mpi_init( X );
848 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
849 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000851
Hanno Becker0e810b92019-01-03 17:13:11 +0000852 /* Avoid calling `memcpy` with NULL source argument,
853 * even if buflen is 0. */
854 if( buf != NULL )
855 {
856 Xp = (unsigned char*) X->p;
857 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100858
Hanno Becker0e810b92019-01-03 17:13:11 +0000859 mpi_bigendian_to_host( X->p, limbs );
860 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000861
862cleanup:
863
864 return( ret );
865}
866
867/*
868 * Export X into unsigned binary data, big endian
869 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100870int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
871 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872{
Hanno Becker73d7d792018-12-11 10:35:51 +0000873 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100874 size_t bytes_to_copy;
875 unsigned char *p;
876 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000877
Hanno Becker73d7d792018-12-11 10:35:51 +0000878 MPI_VALIDATE_RET( X != NULL );
879 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
880
881 stored_bytes = X->n * ciL;
882
Gilles Peskine11cdb052018-11-20 16:47:47 +0100883 if( stored_bytes < buflen )
884 {
885 /* There is enough space in the output buffer. Write initial
886 * null bytes and record the position at which to start
887 * writing the significant bytes. In this case, the execution
888 * trace of this function does not depend on the value of the
889 * number. */
890 bytes_to_copy = stored_bytes;
891 p = buf + buflen - stored_bytes;
892 memset( buf, 0, buflen - stored_bytes );
893 }
894 else
895 {
896 /* The output buffer is smaller than the allocated size of X.
897 * However X may fit if its leading bytes are zero. */
898 bytes_to_copy = buflen;
899 p = buf;
900 for( i = bytes_to_copy; i < stored_bytes; i++ )
901 {
902 if( GET_BYTE( X, i ) != 0 )
903 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
904 }
905 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
Gilles Peskine11cdb052018-11-20 16:47:47 +0100907 for( i = 0; i < bytes_to_copy; i++ )
908 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
910 return( 0 );
911}
912
913/*
914 * Left-shift: X <<= count
915 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000917{
Paul Bakker23986e52011-04-24 08:57:21 +0000918 int ret;
919 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000921 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000922
923 v0 = count / (biL );
924 t1 = count & (biL - 1);
925
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200926 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000927
Paul Bakkerf9688572011-05-05 10:00:45 +0000928 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000930
931 ret = 0;
932
933 /*
934 * shift by count / limb_size
935 */
936 if( v0 > 0 )
937 {
Paul Bakker23986e52011-04-24 08:57:21 +0000938 for( i = X->n; i > v0; i-- )
939 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000940
Paul Bakker23986e52011-04-24 08:57:21 +0000941 for( ; i > 0; i-- )
942 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 }
944
945 /*
946 * shift by count % limb_size
947 */
948 if( t1 > 0 )
949 {
950 for( i = v0; i < X->n; i++ )
951 {
952 r1 = X->p[i] >> (biL - t1);
953 X->p[i] <<= t1;
954 X->p[i] |= r0;
955 r0 = r1;
956 }
957 }
958
959cleanup:
960
961 return( ret );
962}
963
964/*
965 * Right-shift: X >>= count
966 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200967int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000968{
Paul Bakker23986e52011-04-24 08:57:21 +0000969 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000971 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
973 v0 = count / biL;
974 v1 = count & (biL - 1);
975
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100976 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100978
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 /*
980 * shift by count / limb_size
981 */
982 if( v0 > 0 )
983 {
984 for( i = 0; i < X->n - v0; i++ )
985 X->p[i] = X->p[i + v0];
986
987 for( ; i < X->n; i++ )
988 X->p[i] = 0;
989 }
990
991 /*
992 * shift by count % limb_size
993 */
994 if( v1 > 0 )
995 {
Paul Bakker23986e52011-04-24 08:57:21 +0000996 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 {
Paul Bakker23986e52011-04-24 08:57:21 +0000998 r1 = X->p[i - 1] << (biL - v1);
999 X->p[i - 1] >>= v1;
1000 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 r0 = r1;
1002 }
1003 }
1004
1005 return( 0 );
1006}
1007
1008/*
1009 * Compare unsigned values
1010 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001012{
Paul Bakker23986e52011-04-24 08:57:21 +00001013 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001014 MPI_VALIDATE_RET( X != NULL );
1015 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001016
Paul Bakker23986e52011-04-24 08:57:21 +00001017 for( i = X->n; i > 0; i-- )
1018 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001019 break;
1020
Paul Bakker23986e52011-04-24 08:57:21 +00001021 for( j = Y->n; j > 0; j-- )
1022 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 break;
1024
Paul Bakker23986e52011-04-24 08:57:21 +00001025 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001026 return( 0 );
1027
1028 if( i > j ) return( 1 );
1029 if( j > i ) return( -1 );
1030
Paul Bakker23986e52011-04-24 08:57:21 +00001031 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001032 {
Paul Bakker23986e52011-04-24 08:57:21 +00001033 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1034 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001035 }
1036
1037 return( 0 );
1038}
1039
1040/*
1041 * Compare signed values
1042 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001043int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001044{
Paul Bakker23986e52011-04-24 08:57:21 +00001045 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001046 MPI_VALIDATE_RET( X != NULL );
1047 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001048
Paul Bakker23986e52011-04-24 08:57:21 +00001049 for( i = X->n; i > 0; i-- )
1050 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 break;
1052
Paul Bakker23986e52011-04-24 08:57:21 +00001053 for( j = Y->n; j > 0; j-- )
1054 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 break;
1056
Paul Bakker23986e52011-04-24 08:57:21 +00001057 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 return( 0 );
1059
1060 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001061 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062
1063 if( X->s > 0 && Y->s < 0 ) return( 1 );
1064 if( Y->s > 0 && X->s < 0 ) return( -1 );
1065
Paul Bakker23986e52011-04-24 08:57:21 +00001066 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001067 {
Paul Bakker23986e52011-04-24 08:57:21 +00001068 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1069 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 }
1071
1072 return( 0 );
1073}
1074
Janos Follath45ec9902019-10-14 09:09:32 +01001075/** Decide if an integer is less than the other, without branches.
1076 *
1077 * \param x First integer.
1078 * \param y Second integer.
1079 *
1080 * \return 1 if \p x is less than \p y, 0 otherwise
1081 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001082static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1083 const mbedtls_mpi_uint y )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001084{
1085 mbedtls_mpi_uint ret;
1086 mbedtls_mpi_uint cond;
1087
1088 /*
1089 * Check if the most significant bits (MSB) of the operands are different.
1090 */
1091 cond = ( x ^ y );
1092 /*
1093 * If the MSB are the same then the difference x-y will be negative (and
1094 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1095 */
1096 ret = ( x - y ) & ~cond;
1097 /*
1098 * If the MSB are different, then the operand with the MSB of 1 is the
1099 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1100 * the MSB of y is 0.)
1101 */
1102 ret |= y & cond;
1103
1104
Janos Follath7a34bcf2019-10-14 08:59:14 +01001105 ret = ret >> ( biL - 1 );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001106
Janos Follath359a01e2019-10-29 15:08:46 +00001107 return (unsigned) ret;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001108}
1109
1110/*
1111 * Compare signed values in constant time
1112 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001113int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1114 unsigned *ret )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001115{
1116 size_t i;
Janos Follathbd87a592019-10-28 12:23:18 +00001117 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001118 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001119
1120 MPI_VALIDATE_RET( X != NULL );
1121 MPI_VALIDATE_RET( Y != NULL );
1122 MPI_VALIDATE_RET( ret != NULL );
1123
1124 if( X->n != Y->n )
1125 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1126
1127 /*
Janos Follath58525182019-10-28 12:12:15 +00001128 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1129 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001130 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001131 X_is_negative = ( X->s & 2 ) >> 1;
1132 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath867a3ab2019-10-11 14:21:53 +01001133
1134 /*
1135 * If the signs are different, then the positive operand is the bigger.
Janos Follath1f21c1d2019-10-28 12:31:34 +00001136 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1137 * is false if X is positive (X_is_negative == 0).
Janos Follath867a3ab2019-10-11 14:21:53 +01001138 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001139 cond = ( X_is_negative ^ Y_is_negative );
1140 *ret = cond & X_is_negative;
Janos Follath867a3ab2019-10-11 14:21:53 +01001141
1142 /*
Janos Follathbd87a592019-10-28 12:23:18 +00001143 * This is a constant-time function. We might have the result, but we still
Janos Follath867a3ab2019-10-11 14:21:53 +01001144 * need to go through the loop. Record if we have the result already.
1145 */
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001146 done = cond;
1147
1148 for( i = X->n; i > 0; i-- )
1149 {
1150 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001151 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1152 * X and Y are negative.
Janos Follath867a3ab2019-10-11 14:21:53 +01001153 *
1154 * Again even if we can make a decision, we just mark the result and
1155 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001156 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001157 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1158 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathfbe4c942019-10-28 12:37:21 +00001159 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001160
1161 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001162 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1163 * X and Y are positive.
Janos Follath867a3ab2019-10-11 14:21:53 +01001164 *
1165 * Again even if we can make a decision, we just mark the result and
1166 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001167 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001168 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1169 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathfbe4c942019-10-28 12:37:21 +00001170 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001171 }
1172
1173 return( 0 );
1174}
1175
Paul Bakker5121ce52009-01-03 21:22:43 +00001176/*
1177 * Compare signed values
1178 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001180{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 mbedtls_mpi Y;
1182 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001183 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
1185 *p = ( z < 0 ) ? -z : z;
1186 Y.s = ( z < 0 ) ? -1 : 1;
1187 Y.n = 1;
1188 Y.p = p;
1189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001191}
1192
1193/*
1194 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001197{
Paul Bakker23986e52011-04-24 08:57:21 +00001198 int ret;
1199 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001200 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001201 MPI_VALIDATE_RET( X != NULL );
1202 MPI_VALIDATE_RET( A != NULL );
1203 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204
1205 if( X == B )
1206 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001208 }
1209
1210 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001212
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001213 /*
1214 * X should always be positive as a result of unsigned additions.
1215 */
1216 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001217
Paul Bakker23986e52011-04-24 08:57:21 +00001218 for( j = B->n; j > 0; j-- )
1219 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 break;
1221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001223
1224 o = B->p; p = X->p; c = 0;
1225
Janos Follath6c922682015-10-30 17:43:11 +01001226 /*
1227 * tmp is used because it might happen that p == o
1228 */
Paul Bakker23986e52011-04-24 08:57:21 +00001229 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 {
Janos Follath6c922682015-10-30 17:43:11 +01001231 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001232 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001233 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 }
1235
1236 while( c != 0 )
1237 {
1238 if( i >= X->n )
1239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 p = X->p + i;
1242 }
1243
Paul Bakker2d319fd2012-09-16 21:34:26 +00001244 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001245 }
1246
1247cleanup:
1248
1249 return( ret );
1250}
1251
1252/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001254 */
Gilles Peskinee9073a62020-06-04 15:01:32 +02001255static void mpi_sub_hlp( size_t n,
1256 const mbedtls_mpi_uint *s,
1257 mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001258{
Paul Bakker23986e52011-04-24 08:57:21 +00001259 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
1262 for( i = c = 0; i < n; i++, s++, d++ )
1263 {
1264 z = ( *d < c ); *d -= c;
1265 c = ( *d < *s ) + z; *d -= *s;
1266 }
1267
1268 while( c != 0 )
1269 {
1270 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001271 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001272 }
1273}
1274
1275/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001276 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001279{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001281 int ret;
1282 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001283 MPI_VALIDATE_RET( X != NULL );
1284 MPI_VALIDATE_RET( A != NULL );
1285 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001287 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1288 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001291
1292 if( X == B )
1293 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001295 B = &TB;
1296 }
1297
1298 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001300
Paul Bakker1ef7a532009-06-20 10:50:55 +00001301 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001302 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001303 */
1304 X->s = 1;
1305
Paul Bakker5121ce52009-01-03 21:22:43 +00001306 ret = 0;
1307
Paul Bakker23986e52011-04-24 08:57:21 +00001308 for( n = B->n; n > 0; n-- )
1309 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001310 break;
1311
Paul Bakker23986e52011-04-24 08:57:21 +00001312 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001313
1314cleanup:
1315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001316 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001317
1318 return( ret );
1319}
1320
1321/*
1322 * Signed addition: X = A + B
1323 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001325{
Hanno Becker73d7d792018-12-11 10:35:51 +00001326 int ret, s;
1327 MPI_VALIDATE_RET( X != NULL );
1328 MPI_VALIDATE_RET( A != NULL );
1329 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001330
Hanno Becker73d7d792018-12-11 10:35:51 +00001331 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 if( A->s * B->s < 0 )
1333 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 X->s = s;
1338 }
1339 else
1340 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 X->s = -s;
1343 }
1344 }
1345 else
1346 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 X->s = s;
1349 }
1350
1351cleanup:
1352
1353 return( ret );
1354}
1355
1356/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001357 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001360{
Hanno Becker73d7d792018-12-11 10:35:51 +00001361 int ret, s;
1362 MPI_VALIDATE_RET( X != NULL );
1363 MPI_VALIDATE_RET( A != NULL );
1364 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001365
Hanno Becker73d7d792018-12-11 10:35:51 +00001366 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 if( A->s * B->s > 0 )
1368 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001370 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001372 X->s = s;
1373 }
1374 else
1375 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001377 X->s = -s;
1378 }
1379 }
1380 else
1381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383 X->s = s;
1384 }
1385
1386cleanup:
1387
1388 return( ret );
1389}
1390
1391/*
1392 * Signed addition: X = A + b
1393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001395{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 mbedtls_mpi _B;
1397 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001398 MPI_VALIDATE_RET( X != NULL );
1399 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
1401 p[0] = ( b < 0 ) ? -b : b;
1402 _B.s = ( b < 0 ) ? -1 : 1;
1403 _B.n = 1;
1404 _B.p = p;
1405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407}
1408
1409/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001410 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001411 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001413{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 mbedtls_mpi _B;
1415 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001416 MPI_VALIDATE_RET( X != NULL );
1417 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001418
1419 p[0] = ( b < 0 ) ? -b : b;
1420 _B.s = ( b < 0 ) ? -1 : 1;
1421 _B.n = 1;
1422 _B.p = p;
1423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425}
1426
1427/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001429 */
1430static
1431#if defined(__APPLE__) && defined(__arm__)
1432/*
1433 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1434 * appears to need this to prevent bad ARM code generation at -O3.
1435 */
1436__attribute__ ((noinline))
1437#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438void 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 +00001439{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001441
1442#if defined(MULADDC_HUIT)
1443 for( ; i >= 8; i -= 8 )
1444 {
1445 MULADDC_INIT
1446 MULADDC_HUIT
1447 MULADDC_STOP
1448 }
1449
1450 for( ; i > 0; i-- )
1451 {
1452 MULADDC_INIT
1453 MULADDC_CORE
1454 MULADDC_STOP
1455 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001456#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001457 for( ; i >= 16; i -= 16 )
1458 {
1459 MULADDC_INIT
1460 MULADDC_CORE MULADDC_CORE
1461 MULADDC_CORE MULADDC_CORE
1462 MULADDC_CORE MULADDC_CORE
1463 MULADDC_CORE MULADDC_CORE
1464
1465 MULADDC_CORE MULADDC_CORE
1466 MULADDC_CORE MULADDC_CORE
1467 MULADDC_CORE MULADDC_CORE
1468 MULADDC_CORE MULADDC_CORE
1469 MULADDC_STOP
1470 }
1471
1472 for( ; i >= 8; i -= 8 )
1473 {
1474 MULADDC_INIT
1475 MULADDC_CORE MULADDC_CORE
1476 MULADDC_CORE MULADDC_CORE
1477
1478 MULADDC_CORE MULADDC_CORE
1479 MULADDC_CORE MULADDC_CORE
1480 MULADDC_STOP
1481 }
1482
1483 for( ; i > 0; i-- )
1484 {
1485 MULADDC_INIT
1486 MULADDC_CORE
1487 MULADDC_STOP
1488 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001489#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
1491 t++;
1492
1493 do {
1494 *d += c; c = ( *d < c ); d++;
1495 }
1496 while( c != 0 );
1497}
1498
1499/*
1500 * Baseline multiplication: X = A * B (HAC 14.12)
1501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001503{
Paul Bakker23986e52011-04-24 08:57:21 +00001504 int ret;
1505 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001507 MPI_VALIDATE_RET( X != NULL );
1508 MPI_VALIDATE_RET( A != NULL );
1509 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1514 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001515
Paul Bakker23986e52011-04-24 08:57:21 +00001516 for( i = A->n; i > 0; i-- )
1517 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 break;
1519
Paul Bakker23986e52011-04-24 08:57:21 +00001520 for( j = B->n; j > 0; j-- )
1521 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001522 break;
1523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1525 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001527 for( ; j > 0; j-- )
1528 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001529
1530 X->s = A->s * B->s;
1531
1532cleanup:
1533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
1536 return( ret );
1537}
1538
1539/*
1540 * Baseline multiplication: X = A * b
1541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001543{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 mbedtls_mpi _B;
1545 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 _B.s = 1;
1550 _B.n = 1;
1551 _B.p = p;
1552 p[0] = b;
1553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555}
1556
1557/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001558 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1559 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001560 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001561static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1562 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001563{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001564#if defined(MBEDTLS_HAVE_UDBL)
1565 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001566#else
Simon Butcher9803d072016-01-03 00:24:34 +00001567 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1568 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001569 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1570 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001571 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001572#endif
1573
Simon Butcher15b15d12015-11-26 19:35:03 +00001574 /*
1575 * Check for overflow
1576 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001577 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001578 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001579 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001580
Simon Butcherf5ba0452015-12-27 23:01:55 +00001581 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001582 }
1583
1584#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001585 dividend = (mbedtls_t_udbl) u1 << biL;
1586 dividend |= (mbedtls_t_udbl) u0;
1587 quotient = dividend / d;
1588 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1589 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1590
1591 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001592 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001593
1594 return (mbedtls_mpi_uint) quotient;
1595#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001596
1597 /*
1598 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1599 * Vol. 2 - Seminumerical Algorithms, Knuth
1600 */
1601
1602 /*
1603 * Normalize the divisor, d, and dividend, u0, u1
1604 */
1605 s = mbedtls_clz( d );
1606 d = d << s;
1607
1608 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001609 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001610 u0 = u0 << s;
1611
1612 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001613 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001614
1615 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001616 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001617
1618 /*
1619 * Find the first quotient and remainder
1620 */
1621 q1 = u1 / d1;
1622 r0 = u1 - d1 * q1;
1623
1624 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1625 {
1626 q1 -= 1;
1627 r0 += d1;
1628
1629 if ( r0 >= radix ) break;
1630 }
1631
Simon Butcherf5ba0452015-12-27 23:01:55 +00001632 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001633 q0 = rAX / d1;
1634 r0 = rAX - q0 * d1;
1635
1636 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1637 {
1638 q0 -= 1;
1639 r0 += d1;
1640
1641 if ( r0 >= radix ) break;
1642 }
1643
1644 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001645 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001646
1647 quotient = q1 * radix + q0;
1648
1649 return quotient;
1650#endif
1651}
1652
1653/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001655 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001656int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1657 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001658{
Paul Bakker23986e52011-04-24 08:57:21 +00001659 int ret;
1660 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001662 MPI_VALIDATE_RET( A != NULL );
1663 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1666 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1669 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001672 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1674 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 return( 0 );
1676 }
1677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1679 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001680 X.s = Y.s = 1;
1681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1683 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1684 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1685 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001687 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001688 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 {
1690 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1692 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693 }
1694 else k = 0;
1695
1696 n = X.n - 1;
1697 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001701 {
1702 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001703 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
1707 for( i = n; i > t ; i-- )
1708 {
1709 if( X.p[i] >= Y.p[t] )
1710 Z.p[i - t - 1] = ~0;
1711 else
1712 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001713 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1714 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001715 }
1716
1717 Z.p[i - t - 1]++;
1718 do
1719 {
1720 Z.p[i - t - 1]--;
1721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001723 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001724 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001728 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1729 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001730 T2.p[2] = X.p[i];
1731 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1735 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1736 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001740 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1741 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1742 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001743 Z.p[i - t - 1]--;
1744 }
1745 }
1746
1747 if( Q != NULL )
1748 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001750 Q->s = A->s * B->s;
1751 }
1752
1753 if( R != NULL )
1754 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001756 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 R->s = 1;
1761 }
1762
1763cleanup:
1764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1766 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
1768 return( ret );
1769}
1770
1771/*
1772 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001773 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001774int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1775 const mbedtls_mpi *A,
1776 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001777{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778 mbedtls_mpi _B;
1779 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001780 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781
1782 p[0] = ( b < 0 ) ? -b : b;
1783 _B.s = ( b < 0 ) ? -1 : 1;
1784 _B.n = 1;
1785 _B.p = p;
1786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001788}
1789
1790/*
1791 * Modulo: R = A mod B
1792 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001794{
1795 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001796 MPI_VALIDATE_RET( R != NULL );
1797 MPI_VALIDATE_RET( A != NULL );
1798 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1801 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1806 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1809 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
1811cleanup:
1812
1813 return( ret );
1814}
1815
1816/*
1817 * Modulo: r = A mod b
1818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001820{
Paul Bakker23986e52011-04-24 08:57:21 +00001821 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001823 MPI_VALIDATE_RET( r != NULL );
1824 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
1826 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
1829 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
1832 /*
1833 * handle trivial cases
1834 */
1835 if( b == 1 )
1836 {
1837 *r = 0;
1838 return( 0 );
1839 }
1840
1841 if( b == 2 )
1842 {
1843 *r = A->p[0] & 1;
1844 return( 0 );
1845 }
1846
1847 /*
1848 * general case
1849 */
Paul Bakker23986e52011-04-24 08:57:21 +00001850 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 {
Paul Bakker23986e52011-04-24 08:57:21 +00001852 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 y = ( y << biH ) | ( x >> biH );
1854 z = y / b;
1855 y -= z * b;
1856
1857 x <<= biH;
1858 y = ( y << biH ) | ( x >> biH );
1859 z = y / b;
1860 y -= z * b;
1861 }
1862
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001863 /*
1864 * If A is negative, then the current y represents a negative value.
1865 * Flipping it to the positive side.
1866 */
1867 if( A->s < 0 && y != 0 )
1868 y = b - y;
1869
Paul Bakker5121ce52009-01-03 21:22:43 +00001870 *r = y;
1871
1872 return( 0 );
1873}
1874
1875/*
1876 * Fast Montgomery initialization (thanks to Tom St Denis)
1877 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001879{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001881 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
1883 x = m0;
1884 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001886 for( i = biL; i >= 8; i /= 2 )
1887 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
1889 *mm = ~x + 1;
1890}
1891
1892/*
1893 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1894 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02001895static 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 +02001896 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001897{
Paul Bakker23986e52011-04-24 08:57:21 +00001898 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001900
1901 memset( T->p, 0, T->n * ciL );
1902
1903 d = T->p;
1904 n = N->n;
1905 m = ( B->n < n ) ? B->n : n;
1906
1907 for( i = 0; i < n; i++ )
1908 {
1909 /*
1910 * T = (T + u0*B + u1*N) / 2^biL
1911 */
1912 u0 = A->p[i];
1913 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1914
1915 mpi_mul_hlp( m, B->p, d, u0 );
1916 mpi_mul_hlp( n, N->p, d, u1 );
1917
1918 *d++ = u0; d[n + 1] = 0;
1919 }
1920
Paul Bakker66d5d072014-06-17 16:39:18 +02001921 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001924 mpi_sub_hlp( n, N->p, A->p );
1925 else
1926 /* prevent timing attacks */
1927 mpi_sub_hlp( n, A->p, T->p );
1928}
1929
1930/*
1931 * Montgomery reduction: A = A * R^-1 mod N
1932 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02001933static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1934 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001935{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001936 mbedtls_mpi_uint z = 1;
1937 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001938
Paul Bakker8ddb6452013-02-27 14:56:33 +01001939 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001940 U.p = &z;
1941
Gilles Peskinebdcb3962020-06-04 20:55:15 +02001942 mpi_montmul( A, &U, N, mm, T );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943}
1944
1945/*
1946 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1947 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001948int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1949 const mbedtls_mpi *E, const mbedtls_mpi *N,
1950 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001951{
Paul Bakker23986e52011-04-24 08:57:21 +00001952 int ret;
1953 size_t wbits, wsize, one = 1;
1954 size_t i, j, nblimbs;
1955 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 mbedtls_mpi_uint ei, mm, state;
1957 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001958 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001959
Hanno Becker73d7d792018-12-11 10:35:51 +00001960 MPI_VALIDATE_RET( X != NULL );
1961 MPI_VALIDATE_RET( A != NULL );
1962 MPI_VALIDATE_RET( E != NULL );
1963 MPI_VALIDATE_RET( N != NULL );
1964
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001965 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1969 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001970
1971 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001972 * Init temps and window size
1973 */
1974 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1976 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977 memset( W, 0, sizeof( W ) );
1978
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001979 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980
1981 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1982 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1983
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001984#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1986 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001987#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001988
Paul Bakker5121ce52009-01-03 21:22:43 +00001989 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1991 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1992 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
1994 /*
Paul Bakker50546922012-05-19 08:40:49 +00001995 * Compensate for negative A (and correct at the end)
1996 */
1997 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001998 if( neg )
1999 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002000 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002001 Apos.s = 1;
2002 A = &Apos;
2003 }
2004
2005 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002006 * If 1st call, pre-compute R^2 mod N
2007 */
2008 if( _RR == NULL || _RR->p == NULL )
2009 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2011 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2012 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002013
2014 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002016 }
2017 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
2020 /*
2021 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2022 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2024 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002025 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002028 mpi_montmul( &W[1], &RR, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002029
2030 /*
2031 * X = R^2 * R^-1 mod N = R mod N
2032 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002034 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002035
2036 if( wsize > 1 )
2037 {
2038 /*
2039 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2040 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002041 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002042
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2044 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
2046 for( i = 0; i < wsize - 1; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002047 mpi_montmul( &W[j], &W[j], N, mm, &T );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002048
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 /*
2050 * W[i] = W[i - 1] * W[1]
2051 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002052 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2055 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002057 mpi_montmul( &W[i], &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 }
2059 }
2060
2061 nblimbs = E->n;
2062 bufsize = 0;
2063 nbits = 0;
2064 wbits = 0;
2065 state = 0;
2066
2067 while( 1 )
2068 {
2069 if( bufsize == 0 )
2070 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002071 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002072 break;
2073
Paul Bakker0d7702c2013-10-29 16:18:35 +01002074 nblimbs--;
2075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002077 }
2078
2079 bufsize--;
2080
2081 ei = (E->p[nblimbs] >> bufsize) & 1;
2082
2083 /*
2084 * skip leading 0s
2085 */
2086 if( ei == 0 && state == 0 )
2087 continue;
2088
2089 if( ei == 0 && state == 1 )
2090 {
2091 /*
2092 * out of window, square X
2093 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002094 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002095 continue;
2096 }
2097
2098 /*
2099 * add ei to current window
2100 */
2101 state = 2;
2102
2103 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002104 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002105
2106 if( nbits == wsize )
2107 {
2108 /*
2109 * X = X^wsize R^-1 mod N
2110 */
2111 for( i = 0; i < wsize; i++ )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002112 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002113
2114 /*
2115 * X = X * W[wbits] R^-1 mod N
2116 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002117 mpi_montmul( X, &W[wbits], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002118
2119 state--;
2120 nbits = 0;
2121 wbits = 0;
2122 }
2123 }
2124
2125 /*
2126 * process the remaining bits
2127 */
2128 for( i = 0; i < nbits; i++ )
2129 {
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002130 mpi_montmul( X, X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002131
2132 wbits <<= 1;
2133
Paul Bakker66d5d072014-06-17 16:39:18 +02002134 if( ( wbits & ( one << wsize ) ) != 0 )
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002135 mpi_montmul( X, &W[1], N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002136 }
2137
2138 /*
2139 * X = A^E * R * R^-1 mod N = A^E mod N
2140 */
Gilles Peskinebdcb3962020-06-04 20:55:15 +02002141 mpi_montred( X, N, mm, &T );
Paul Bakker5121ce52009-01-03 21:22:43 +00002142
Hanno Beckera4af1c42017-04-18 09:07:45 +01002143 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002144 {
2145 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002147 }
2148
Paul Bakker5121ce52009-01-03 21:22:43 +00002149cleanup:
2150
Paul Bakker66d5d072014-06-17 16:39:18 +02002151 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002155
Paul Bakker75a28602014-03-31 12:08:17 +02002156 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002158
2159 return( ret );
2160}
2161
Paul Bakker5121ce52009-01-03 21:22:43 +00002162/*
2163 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2164 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002166{
Paul Bakker23986e52011-04-24 08:57:21 +00002167 int ret;
2168 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002170
Hanno Becker73d7d792018-12-11 10:35:51 +00002171 MPI_VALIDATE_RET( G != NULL );
2172 MPI_VALIDATE_RET( A != NULL );
2173 MPI_VALIDATE_RET( B != NULL );
2174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2178 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 lz = mbedtls_mpi_lsb( &TA );
2181 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002182
Paul Bakker66d5d072014-06-17 16:39:18 +02002183 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002184 lz = lzt;
2185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2187 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002188
Paul Bakker5121ce52009-01-03 21:22:43 +00002189 TA.s = TB.s = 1;
2190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002192 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2194 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 }
2201 else
2202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2204 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205 }
2206 }
2207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2209 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
2211cleanup:
2212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214
2215 return( ret );
2216}
2217
Paul Bakker33dc46b2014-04-30 16:11:39 +02002218/*
2219 * Fill X with size bytes of random.
2220 *
2221 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002222 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002223 * deterministic, eg for tests).
2224 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002226 int (*f_rng)(void *, unsigned char *, size_t),
2227 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002228{
Paul Bakker23986e52011-04-24 08:57:21 +00002229 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002230 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002231 size_t const overhead = ( limbs * ciL ) - size;
2232 unsigned char *Xp;
2233
Hanno Becker8ce11a32018-12-19 16:18:52 +00002234 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002235 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002236
Hanno Beckerda1655a2017-10-18 14:21:44 +01002237 /* Ensure that target MPI has exactly the necessary number of limbs */
2238 if( X->n != limbs )
2239 {
2240 mbedtls_mpi_free( X );
2241 mbedtls_mpi_init( X );
2242 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2243 }
2244 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002245
Hanno Beckerda1655a2017-10-18 14:21:44 +01002246 Xp = (unsigned char*) X->p;
2247 f_rng( p_rng, Xp + overhead, size );
2248
Hanno Becker2be8a552018-10-25 12:40:09 +01002249 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002250
2251cleanup:
2252 return( ret );
2253}
2254
Paul Bakker5121ce52009-01-03 21:22:43 +00002255/*
2256 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002259{
2260 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002262 MPI_VALIDATE_RET( X != NULL );
2263 MPI_VALIDATE_RET( A != NULL );
2264 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002265
Hanno Becker4bcb4912017-04-18 15:49:39 +01002266 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2270 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2271 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 goto cleanup;
2279 }
2280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2282 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2283 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2284 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2287 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2288 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2289 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
2291 do
2292 {
2293 while( ( TU.p[0] & 1 ) == 0 )
2294 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002296
2297 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2298 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2300 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002301 }
2302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2304 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 }
2306
2307 while( ( TV.p[0] & 1 ) == 0 )
2308 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310
2311 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2312 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2314 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315 }
2316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2318 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 }
2320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002322 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2324 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2325 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002326 }
2327 else
2328 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2331 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 }
2333 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2337 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2340 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
2344cleanup:
2345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2347 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2348 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002349
2350 return( ret );
2351}
2352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002354
Paul Bakker5121ce52009-01-03 21:22:43 +00002355static const int small_prime[] =
2356{
2357 3, 5, 7, 11, 13, 17, 19, 23,
2358 29, 31, 37, 41, 43, 47, 53, 59,
2359 61, 67, 71, 73, 79, 83, 89, 97,
2360 101, 103, 107, 109, 113, 127, 131, 137,
2361 139, 149, 151, 157, 163, 167, 173, 179,
2362 181, 191, 193, 197, 199, 211, 223, 227,
2363 229, 233, 239, 241, 251, 257, 263, 269,
2364 271, 277, 281, 283, 293, 307, 311, 313,
2365 317, 331, 337, 347, 349, 353, 359, 367,
2366 373, 379, 383, 389, 397, 401, 409, 419,
2367 421, 431, 433, 439, 443, 449, 457, 461,
2368 463, 467, 479, 487, 491, 499, 503, 509,
2369 521, 523, 541, 547, 557, 563, 569, 571,
2370 577, 587, 593, 599, 601, 607, 613, 617,
2371 619, 631, 641, 643, 647, 653, 659, 661,
2372 673, 677, 683, 691, 701, 709, 719, 727,
2373 733, 739, 743, 751, 757, 761, 769, 773,
2374 787, 797, 809, 811, 821, 823, 827, 829,
2375 839, 853, 857, 859, 863, 877, 881, 883,
2376 887, 907, 911, 919, 929, 937, 941, 947,
2377 953, 967, 971, 977, 983, 991, 997, -103
2378};
2379
2380/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002381 * Small divisors test (X must be positive)
2382 *
2383 * Return values:
2384 * 0: no small factor (possible prime, more tests needed)
2385 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002386 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002387 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002388 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002390{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002391 int ret = 0;
2392 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002394
Paul Bakker5121ce52009-01-03 21:22:43 +00002395 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
2398 for( i = 0; small_prime[i] > 0; i++ )
2399 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002401 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
2405 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002407 }
2408
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002409cleanup:
2410 return( ret );
2411}
2412
2413/*
2414 * Miller-Rabin pseudo-primality test (HAC 4.24)
2415 */
Janos Follathda31fa12018-09-03 14:45:23 +01002416static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002417 int (*f_rng)(void *, unsigned char *, size_t),
2418 void *p_rng )
2419{
Pascal Junodb99183d2015-03-11 16:49:45 +01002420 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002421 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002423
Hanno Becker8ce11a32018-12-19 16:18:52 +00002424 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002425 MPI_VALIDATE_RET( f_rng != NULL );
2426
2427 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2428 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002430
Paul Bakker5121ce52009-01-03 21:22:43 +00002431 /*
2432 * W = |X| - 1
2433 * R = W >> lsb( W )
2434 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002435 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2436 s = mbedtls_mpi_lsb( &W );
2437 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2438 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002439
Janos Follathda31fa12018-09-03 14:45:23 +01002440 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002441 {
2442 /*
2443 * pick a random A, 1 < A < |X| - 1
2444 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002445 count = 0;
2446 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002447 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002448
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002449 j = mbedtls_mpi_bitlen( &A );
2450 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002451 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002452 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002453 }
2454
2455 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002456 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2457 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002458 }
2459
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002460 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2461 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
2463 /*
2464 * A = A^R mod |X|
2465 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2469 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002470 continue;
2471
2472 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002474 {
2475 /*
2476 * A = A * A mod |X|
2477 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2479 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002482 break;
2483
2484 j++;
2485 }
2486
2487 /*
2488 * not prime if A != |X| - 1 or A == 1
2489 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2491 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002492 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002493 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002494 break;
2495 }
2496 }
2497
2498cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002499 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2500 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002502
2503 return( ret );
2504}
2505
2506/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002507 * Pseudo-primality test: small factors, then Miller-Rabin
2508 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002509int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2510 int (*f_rng)(void *, unsigned char *, size_t),
2511 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002512{
2513 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002515 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002516 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002517
2518 XX.s = 1;
2519 XX.n = X->n;
2520 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002522 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2523 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2524 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002527 return( 0 );
2528
2529 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2530 {
2531 if( ret == 1 )
2532 return( 0 );
2533
2534 return( ret );
2535 }
2536
Janos Follathda31fa12018-09-03 14:45:23 +01002537 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002538}
2539
Janos Follatha0b67c22018-09-18 14:48:23 +01002540#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002541/*
2542 * Pseudo-primality test, error probability 2^-80
2543 */
2544int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2545 int (*f_rng)(void *, unsigned char *, size_t),
2546 void *p_rng )
2547{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002548 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002549 MPI_VALIDATE_RET( f_rng != NULL );
2550
Janos Follatha0b67c22018-09-18 14:48:23 +01002551 /*
2552 * In the past our key generation aimed for an error rate of at most
2553 * 2^-80. Since this function is deprecated, aim for the same certainty
2554 * here as well.
2555 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002556 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002557}
Janos Follatha0b67c22018-09-18 14:48:23 +01002558#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002559
2560/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002561 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002562 *
Janos Follathf301d232018-08-14 13:34:01 +01002563 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2564 * be either 1024 bits or 1536 bits long, and flags must contain
2565 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002566 */
Janos Follath7c025a92018-08-14 11:08:41 +01002567int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002568 int (*f_rng)(void *, unsigned char *, size_t),
2569 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002570{
Jethro Beekman66689272018-02-14 19:24:10 -08002571#ifdef MBEDTLS_HAVE_INT64
2572// ceil(2^63.5)
2573#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2574#else
2575// ceil(2^31.5)
2576#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2577#endif
2578 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002579 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002580 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 mbedtls_mpi_uint r;
2582 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002583
Hanno Becker8ce11a32018-12-19 16:18:52 +00002584 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002585 MPI_VALIDATE_RET( f_rng != NULL );
2586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2588 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
2592 n = BITS_TO_LIMBS( nbits );
2593
Janos Follathda31fa12018-09-03 14:45:23 +01002594 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2595 {
2596 /*
2597 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2598 */
2599 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2600 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2601 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2602 }
2603 else
2604 {
2605 /*
2606 * 2^-100 error probability, number of rounds computed based on HAC,
2607 * fact 4.48
2608 */
2609 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2610 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2611 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2612 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2613 }
2614
Jethro Beekman66689272018-02-14 19:24:10 -08002615 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002616 {
Jethro Beekman66689272018-02-14 19:24:10 -08002617 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2618 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2619 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2620
2621 k = n * biL;
2622 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2623 X->p[0] |= 1;
2624
Janos Follath7c025a92018-08-14 11:08:41 +01002625 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002626 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002627 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002630 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002631 }
Jethro Beekman66689272018-02-14 19:24:10 -08002632 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002634 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002635 * An necessary condition for Y and X = 2Y + 1 to be prime
2636 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2637 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002638 */
Jethro Beekman66689272018-02-14 19:24:10 -08002639
2640 X->p[0] |= 2;
2641
2642 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2643 if( r == 0 )
2644 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2645 else if( r == 1 )
2646 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2647
2648 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2649 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2650 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2651
2652 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002653 {
Jethro Beekman66689272018-02-14 19:24:10 -08002654 /*
2655 * First, check small factors for X and Y
2656 * before doing Miller-Rabin on any of them
2657 */
2658 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2659 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002660 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002661 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002662 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002663 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002664 goto cleanup;
2665
2666 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2667 goto cleanup;
2668
2669 /*
2670 * Next candidates. We want to preserve Y = (X-1) / 2 and
2671 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2672 * so up Y by 6 and X by 12.
2673 */
2674 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2675 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002676 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002677 }
2678 }
2679
2680cleanup:
2681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
2684 return( ret );
2685}
2686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002688
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
Paul Bakker23986e52011-04-24 08:57:21 +00002691#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002692
2693static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2694{
2695 { 693, 609, 21 },
2696 { 1764, 868, 28 },
2697 { 768454923, 542167814, 1 }
2698};
2699
Paul Bakker5121ce52009-01-03 21:22:43 +00002700/*
2701 * Checkup routine
2702 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002703int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002704{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002705 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002706 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2709 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002712 "EFE021C2645FD1DC586E69184AF4A31E" \
2713 "D5F53E93B5F123FA41680867BA110131" \
2714 "944FE7952E2517337780CB0DB80E61AA" \
2715 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002717 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002718 "B2E7EFD37075B9F03FF989C7C5051C20" \
2719 "34D2A323810251127E7BF8625A4F49A5" \
2720 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2721 "5B5C25763222FEFCCFC38B832366C29E" ) );
2722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002723 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002724 "0066A198186C18C10B2F5ED9B522752A" \
2725 "9830B69916E535C8F047518A889A43A5" \
2726 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002728 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002731 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2732 "9E857EA95A03512E2BAE7391688D264A" \
2733 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2734 "8001B72E848A38CAE1C65F78E56ABDEF" \
2735 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2736 "ECF677152EF804370C1A305CAF3B5BF1" \
2737 "30879B56C61DE584A0F53A2447A51E" ) );
2738
2739 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002740 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002741
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002742 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002743 {
2744 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002745 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002746
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002747 ret = 1;
2748 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002749 }
2750
2751 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002753
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002757 "256567336059E52CAE22925474705F39A94" ) );
2758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002760 "6613F26162223DF488E9CD48CC132C7A" \
2761 "0AC93C701B001B092E4E5B9F73BCD27B" \
2762 "9EE50D0657C77F374E903CDFA4C642" ) );
2763
2764 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002765 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002766
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002767 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2768 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002769 {
2770 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002771 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002772
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002773 ret = 1;
2774 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002775 }
2776
2777 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002778 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002779
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002781
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002782 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002783 "36E139AEA55215609D2816998ED020BB" \
2784 "BD96C37890F65171D948E9BC7CBAA4D9" \
2785 "325D24D6A3C12710F10A09FA08AB87" ) );
2786
2787 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002788 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002790 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002791 {
2792 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002793 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002794
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002795 ret = 1;
2796 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002797 }
2798
2799 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002800 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002802 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002804 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002805 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2806 "C3DBA76456363A10869622EAC2DD84EC" \
2807 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2808
2809 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002810 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002811
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002812 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002813 {
2814 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002815 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002816
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002817 ret = 1;
2818 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002819 }
2820
2821 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002822 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002823
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002824 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002826
Paul Bakker66d5d072014-06-17 16:39:18 +02002827 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002828 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002829 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2830 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002832 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002834 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002835 {
2836 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002837 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002838
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002839 ret = 1;
2840 goto cleanup;
2841 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002842 }
2843
2844 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002845 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002846
Paul Bakker5121ce52009-01-03 21:22:43 +00002847cleanup:
2848
2849 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002850 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002852 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2853 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002854
2855 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002856 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002857
2858 return( ret );
2859}
2860
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002861#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002862
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002863#endif /* MBEDTLS_BIGNUM_C */