blob: 2cc8e224c1750f98f888cd626245eebacf2f6bdc [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 {
Hanno Becker484caf02019-05-29 14:41:44 +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 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300135 mbedtls_platform_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 Peskine06607472020-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 Peskine8830bd22020-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
Hanno Becker484caf02019-05-29 14:41:44 +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 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300178 mbedtls_platform_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 Peskine51c2e062020-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 {
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200221 mbedtls_platform_memset( X->p + i, 0, ( X->n - i ) * ciL );
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100222 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
Teppo Järvelin91d79382019-10-02 09:09:31 +0300224 mbedtls_platform_memcpy( X->p, Y->p, i * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000225
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
Teppo Järvelin91d79382019-10-02 09:09:31 +0300240 mbedtls_platform_memcpy( &T, X, sizeof( mbedtls_mpi ) );
241 mbedtls_platform_memcpy( X, Y, sizeof( mbedtls_mpi ) );
242 mbedtls_platform_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 ) );
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200322 mbedtls_platform_memset( X->p, 0, X->n * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000323
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
Piotr Nowicki5d5841f2020-06-05 16:33:24 +0200561 if( 0 != mbedtls_platform_memmove( *p, p_end, length ) )
562 {
563 ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
564 goto cleanup;
565 }
Ron Eldora16fa292018-11-20 14:07:01 +0200566 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000567
568cleanup:
569
570 return( ret );
571}
572
573/*
574 * Export into an ASCII string
575 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100576int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
577 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000578{
Paul Bakker23986e52011-04-24 08:57:21 +0000579 int ret = 0;
580 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000583 MPI_VALIDATE_RET( X != NULL );
584 MPI_VALIDATE_RET( olen != NULL );
585 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000586
587 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000588 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000589
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000590 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
591 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
592 * `n`. If radix > 4, this might be a strict
593 * overapproximation of the number of
594 * radix-adic digits needed to present `n`. */
595 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
596 * present `n`. */
597
Janos Follath870ed002019-03-06 13:43:02 +0000598 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000599 n += 1; /* Compensate for the divisions above, which round down `n`
600 * in case it's not even. */
601 n += 1; /* Potential '-'-sign. */
602 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
603 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000604
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100605 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000606 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100607 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609 }
610
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100611 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613
614 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000615 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000616 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000617 buflen--;
618 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
620 if( radix == 16 )
621 {
Paul Bakker23986e52011-04-24 08:57:21 +0000622 int c;
623 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000624
Paul Bakker23986e52011-04-24 08:57:21 +0000625 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000626 {
Paul Bakker23986e52011-04-24 08:57:21 +0000627 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000628 {
Paul Bakker23986e52011-04-24 08:57:21 +0000629 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000630
Paul Bakker6c343d72014-07-10 14:36:19 +0200631 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 continue;
633
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000634 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000635 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000636 k = 1;
637 }
638 }
639 }
640 else
641 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000643
644 if( T.s == -1 )
645 T.s = 1;
646
Ron Eldora16fa292018-11-20 14:07:01 +0200647 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000648 }
649
650 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100651 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
653cleanup:
654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000656
657 return( ret );
658}
659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000661/*
662 * Read X from an opened file
663 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000665{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000667 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000669 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000670 * Buffer should have space for (short) label and decimal formatted MPI,
671 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000672 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000674
Hanno Becker73d7d792018-12-11 10:35:51 +0000675 MPI_VALIDATE_RET( X != NULL );
676 MPI_VALIDATE_RET( fin != NULL );
677
678 if( radix < 2 || radix > 16 )
679 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
680
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200681 mbedtls_platform_memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000682 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000684
685 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000686 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000688
Hanno Beckerb2034b72017-04-26 11:46:46 +0100689 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
690 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
692 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100693 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000694 if( mpi_get_digit( &d, radix, *p ) != 0 )
695 break;
696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698}
699
700/*
701 * Write X into an opened file (or stdout if fout == NULL)
702 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000704{
Paul Bakker23986e52011-04-24 08:57:21 +0000705 int ret;
706 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000707 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000708 * Buffer should have space for (short) label and decimal formatted MPI,
709 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000710 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000712 MPI_VALIDATE_RET( X != NULL );
713
714 if( radix < 2 || radix > 16 )
715 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200717 mbedtls_platform_memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000718
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100719 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
721 if( p == NULL ) p = "";
722
723 plen = strlen( p );
724 slen = strlen( s );
725 s[slen++] = '\r';
726 s[slen++] = '\n';
727
728 if( fout != NULL )
729 {
730 if( fwrite( p, 1, plen, fout ) != plen ||
731 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000733 }
734 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000736
737cleanup:
738
739 return( ret );
740}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
Hanno Beckerda1655a2017-10-18 14:21:44 +0100743
744/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
745 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000746
747static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
748{
749 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100750 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000751 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100752
753 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
754 {
755 tmp <<= CHAR_BIT;
756 tmp |= (mbedtls_mpi_uint) *x_ptr;
757 }
758
Hanno Beckerf8720072018-11-08 11:53:49 +0000759 return( tmp );
760}
761
762static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
763{
764#if defined(__BYTE_ORDER__)
765
766/* Nothing to do on bigendian systems. */
767#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
768 return( x );
769#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
770
771#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
772
773/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000774#if defined(__GNUC__) && defined(__GNUC_PREREQ)
775#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000776#define have_bswap
777#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000778#endif
779
780#if defined(__clang__) && defined(__has_builtin)
781#if __has_builtin(__builtin_bswap32) && \
782 __has_builtin(__builtin_bswap64)
783#define have_bswap
784#endif
785#endif
786
Hanno Beckerf8720072018-11-08 11:53:49 +0000787#if defined(have_bswap)
788 /* The compiler is hopefully able to statically evaluate this! */
789 switch( sizeof(mbedtls_mpi_uint) )
790 {
791 case 4:
792 return( __builtin_bswap32(x) );
793 case 8:
794 return( __builtin_bswap64(x) );
795 }
796#endif
797#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
798#endif /* __BYTE_ORDER__ */
799
800 /* Fall back to C-based reordering if we don't know the byte order
801 * or we couldn't use a compiler-specific builtin. */
802 return( mpi_uint_bigendian_to_host_c( x ) );
803}
804
Hanno Becker2be8a552018-10-25 12:40:09 +0100805static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100806{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100807 mbedtls_mpi_uint *cur_limb_left;
808 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100809 if( limbs == 0 )
810 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100811
812 /*
813 * Traverse limbs and
814 * - adapt byte-order in each limb
815 * - swap the limbs themselves.
816 * For that, simultaneously traverse the limbs from left to right
817 * and from right to left, as long as the left index is not bigger
818 * than the right index (it's not a problem if limbs is odd and the
819 * indices coincide in the last iteration).
820 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100821 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
822 cur_limb_left <= cur_limb_right;
823 cur_limb_left++, cur_limb_right-- )
824 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000825 mbedtls_mpi_uint tmp;
826 /* Note that if cur_limb_left == cur_limb_right,
827 * this code effectively swaps the bytes only once. */
828 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
829 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
830 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100831 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100832}
833
Paul Bakker5121ce52009-01-03 21:22:43 +0000834/*
835 * Import X from unsigned binary data, big endian
836 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000838{
Paul Bakker23986e52011-04-24 08:57:21 +0000839 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100840 size_t const limbs = CHARS_TO_LIMBS( buflen );
841 size_t const overhead = ( limbs * ciL ) - buflen;
842 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000843
Hanno Becker8ce11a32018-12-19 16:18:52 +0000844 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000845 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
846
Hanno Becker073c1992017-10-17 15:17:27 +0100847 /* Ensure that target MPI has exactly the necessary number of limbs */
848 if( X->n != limbs )
849 {
850 mbedtls_mpi_free( X );
851 mbedtls_mpi_init( X );
852 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
853 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000855
Teppo Järvelin91d79382019-10-02 09:09:31 +0300856 /* Avoid calling `mbedtls_platform_memcpy` with NULL source argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000857 * even if buflen is 0. */
858 if( buf != NULL )
859 {
860 Xp = (unsigned char*) X->p;
Teppo Järvelin91d79382019-10-02 09:09:31 +0300861 mbedtls_platform_memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100862
Hanno Becker0e810b92019-01-03 17:13:11 +0000863 mpi_bigendian_to_host( X->p, limbs );
864 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000865
866cleanup:
867
868 return( ret );
869}
870
871/*
872 * Export X into unsigned binary data, big endian
873 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100874int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
875 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000876{
Hanno Becker73d7d792018-12-11 10:35:51 +0000877 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100878 size_t bytes_to_copy;
879 unsigned char *p;
880 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000881
Hanno Becker73d7d792018-12-11 10:35:51 +0000882 MPI_VALIDATE_RET( X != NULL );
883 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
884
885 stored_bytes = X->n * ciL;
886
Gilles Peskine11cdb052018-11-20 16:47:47 +0100887 if( stored_bytes < buflen )
888 {
889 /* There is enough space in the output buffer. Write initial
890 * null bytes and record the position at which to start
891 * writing the significant bytes. In this case, the execution
892 * trace of this function does not depend on the value of the
893 * number. */
894 bytes_to_copy = stored_bytes;
895 p = buf + buflen - stored_bytes;
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200896 mbedtls_platform_memset( buf, 0, buflen - stored_bytes );
Gilles Peskine11cdb052018-11-20 16:47:47 +0100897 }
898 else
899 {
900 /* The output buffer is smaller than the allocated size of X.
901 * However X may fit if its leading bytes are zero. */
902 bytes_to_copy = buflen;
903 p = buf;
904 for( i = bytes_to_copy; i < stored_bytes; i++ )
905 {
906 if( GET_BYTE( X, i ) != 0 )
907 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
908 }
909 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000910
Gilles Peskine11cdb052018-11-20 16:47:47 +0100911 for( i = 0; i < bytes_to_copy; i++ )
912 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000913
914 return( 0 );
915}
916
917/*
918 * Left-shift: X <<= count
919 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000921{
Paul Bakker23986e52011-04-24 08:57:21 +0000922 int ret;
923 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000925 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
927 v0 = count / (biL );
928 t1 = count & (biL - 1);
929
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200930 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000931
Paul Bakkerf9688572011-05-05 10:00:45 +0000932 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000934
935 ret = 0;
936
937 /*
938 * shift by count / limb_size
939 */
940 if( v0 > 0 )
941 {
Paul Bakker23986e52011-04-24 08:57:21 +0000942 for( i = X->n; i > v0; i-- )
943 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000944
Paul Bakker23986e52011-04-24 08:57:21 +0000945 for( ; i > 0; i-- )
946 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000947 }
948
949 /*
950 * shift by count % limb_size
951 */
952 if( t1 > 0 )
953 {
954 for( i = v0; i < X->n; i++ )
955 {
956 r1 = X->p[i] >> (biL - t1);
957 X->p[i] <<= t1;
958 X->p[i] |= r0;
959 r0 = r1;
960 }
961 }
962
963cleanup:
964
965 return( ret );
966}
967
968/*
969 * Right-shift: X >>= count
970 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200971int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000972{
Paul Bakker23986e52011-04-24 08:57:21 +0000973 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200974 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000975 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000976
977 v0 = count / biL;
978 v1 = count & (biL - 1);
979
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100980 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100982
Paul Bakker5121ce52009-01-03 21:22:43 +0000983 /*
984 * shift by count / limb_size
985 */
986 if( v0 > 0 )
987 {
988 for( i = 0; i < X->n - v0; i++ )
989 X->p[i] = X->p[i + v0];
990
991 for( ; i < X->n; i++ )
992 X->p[i] = 0;
993 }
994
995 /*
996 * shift by count % limb_size
997 */
998 if( v1 > 0 )
999 {
Paul Bakker23986e52011-04-24 08:57:21 +00001000 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 {
Paul Bakker23986e52011-04-24 08:57:21 +00001002 r1 = X->p[i - 1] << (biL - v1);
1003 X->p[i - 1] >>= v1;
1004 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001005 r0 = r1;
1006 }
1007 }
1008
1009 return( 0 );
1010}
1011
1012/*
1013 * Compare unsigned values
1014 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001016{
Paul Bakker23986e52011-04-24 08:57:21 +00001017 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001018 MPI_VALIDATE_RET( X != NULL );
1019 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020
Paul Bakker23986e52011-04-24 08:57:21 +00001021 for( i = X->n; i > 0; i-- )
1022 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 break;
1024
Paul Bakker23986e52011-04-24 08:57:21 +00001025 for( j = Y->n; j > 0; j-- )
1026 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 break;
1028
Paul Bakker23986e52011-04-24 08:57:21 +00001029 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001030 return( 0 );
1031
1032 if( i > j ) return( 1 );
1033 if( j > i ) return( -1 );
1034
Paul Bakker23986e52011-04-24 08:57:21 +00001035 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001036 {
Paul Bakker23986e52011-04-24 08:57:21 +00001037 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1038 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 }
1040
1041 return( 0 );
1042}
1043
1044/*
1045 * Compare signed values
1046 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001048{
Paul Bakker23986e52011-04-24 08:57:21 +00001049 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001050 MPI_VALIDATE_RET( X != NULL );
1051 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001052
Paul Bakker23986e52011-04-24 08:57:21 +00001053 for( i = X->n; i > 0; i-- )
1054 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 break;
1056
Paul Bakker23986e52011-04-24 08:57:21 +00001057 for( j = Y->n; j > 0; j-- )
1058 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001059 break;
1060
Paul Bakker23986e52011-04-24 08:57:21 +00001061 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001062 return( 0 );
1063
1064 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001065 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001066
1067 if( X->s > 0 && Y->s < 0 ) return( 1 );
1068 if( Y->s > 0 && X->s < 0 ) return( -1 );
1069
Paul Bakker23986e52011-04-24 08:57:21 +00001070 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001071 {
Paul Bakker23986e52011-04-24 08:57:21 +00001072 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1073 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001074 }
1075
1076 return( 0 );
1077}
1078
Janos Follath34809472019-10-14 09:09:32 +01001079/** Decide if an integer is less than the other, without branches.
1080 *
1081 * \param x First integer.
1082 * \param y Second integer.
1083 *
1084 * \return 1 if \p x is less than \p y, 0 otherwise
1085 */
Janos Follath8faf1d62019-10-11 14:21:53 +01001086static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1087 const mbedtls_mpi_uint y )
Janos Follathc514ce42019-09-05 14:47:19 +01001088{
1089 mbedtls_mpi_uint ret;
1090 mbedtls_mpi_uint cond;
1091
1092 /*
1093 * Check if the most significant bits (MSB) of the operands are different.
1094 */
1095 cond = ( x ^ y );
1096 /*
1097 * If the MSB are the same then the difference x-y will be negative (and
1098 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1099 */
1100 ret = ( x - y ) & ~cond;
1101 /*
1102 * If the MSB are different, then the operand with the MSB of 1 is the
1103 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1104 * the MSB of y is 0.)
1105 */
1106 ret |= y & cond;
1107
1108
Janos Follatha8303772019-10-14 08:59:14 +01001109 ret = ret >> ( biL - 1 );
Janos Follathc514ce42019-09-05 14:47:19 +01001110
Janos Follath3d2b7692019-10-29 15:08:46 +00001111 return (unsigned) ret;
Janos Follathc514ce42019-09-05 14:47:19 +01001112}
1113
1114/*
1115 * Compare signed values in constant time
1116 */
Janos Follath8faf1d62019-10-11 14:21:53 +01001117int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1118 unsigned *ret )
Janos Follathc514ce42019-09-05 14:47:19 +01001119{
1120 size_t i;
Janos Follathcf7eeef2019-10-28 12:23:18 +00001121 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follathec4c42a2019-10-28 12:31:34 +00001122 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathc514ce42019-09-05 14:47:19 +01001123
1124 MPI_VALIDATE_RET( X != NULL );
1125 MPI_VALIDATE_RET( Y != NULL );
1126 MPI_VALIDATE_RET( ret != NULL );
1127
1128 if( X->n != Y->n )
1129 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1130
1131 /*
Janos Follathaa9e7a42019-10-28 12:12:15 +00001132 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1133 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathc514ce42019-09-05 14:47:19 +01001134 */
Janos Follathec4c42a2019-10-28 12:31:34 +00001135 X_is_negative = ( X->s & 2 ) >> 1;
1136 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath8faf1d62019-10-11 14:21:53 +01001137
1138 /*
1139 * If the signs are different, then the positive operand is the bigger.
Janos Follathec4c42a2019-10-28 12:31:34 +00001140 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1141 * is false if X is positive (X_is_negative == 0).
Janos Follath8faf1d62019-10-11 14:21:53 +01001142 */
Janos Follathec4c42a2019-10-28 12:31:34 +00001143 cond = ( X_is_negative ^ Y_is_negative );
1144 *ret = cond & X_is_negative;
Janos Follath8faf1d62019-10-11 14:21:53 +01001145
1146 /*
Janos Follathcf7eeef2019-10-28 12:23:18 +00001147 * This is a constant-time function. We might have the result, but we still
Janos Follath8faf1d62019-10-11 14:21:53 +01001148 * need to go through the loop. Record if we have the result already.
1149 */
Janos Follathc514ce42019-09-05 14:47:19 +01001150 done = cond;
1151
1152 for( i = X->n; i > 0; i-- )
1153 {
1154 /*
Janos Follathe9db2aa2019-11-05 12:24:52 +00001155 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1156 * X and Y are negative.
Janos Follath8faf1d62019-10-11 14:21:53 +01001157 *
1158 * Again even if we can make a decision, we just mark the result and
1159 * the fact that we are done and continue looping.
Janos Follathc514ce42019-09-05 14:47:19 +01001160 */
Janos Follathe9db2aa2019-11-05 12:24:52 +00001161 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1162 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathc8256e72019-10-28 12:37:21 +00001163 done |= cond;
Janos Follathc514ce42019-09-05 14:47:19 +01001164
1165 /*
Janos Follathe9db2aa2019-11-05 12:24:52 +00001166 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1167 * X and Y are positive.
Janos Follath8faf1d62019-10-11 14:21:53 +01001168 *
1169 * Again even if we can make a decision, we just mark the result and
1170 * the fact that we are done and continue looping.
Janos Follathc514ce42019-09-05 14:47:19 +01001171 */
Janos Follathe9db2aa2019-11-05 12:24:52 +00001172 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1173 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathc8256e72019-10-28 12:37:21 +00001174 done |= cond;
Janos Follathc514ce42019-09-05 14:47:19 +01001175 }
1176
1177 return( 0 );
1178}
1179
Paul Bakker5121ce52009-01-03 21:22:43 +00001180/*
1181 * Compare signed values
1182 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001184{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 mbedtls_mpi Y;
1186 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001187 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001188
1189 *p = ( z < 0 ) ? -z : z;
1190 Y.s = ( z < 0 ) ? -1 : 1;
1191 Y.n = 1;
1192 Y.p = p;
1193
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001194 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001195}
1196
1197/*
1198 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1199 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001200int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001201{
Paul Bakker23986e52011-04-24 08:57:21 +00001202 int ret;
1203 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001204 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001205 MPI_VALIDATE_RET( X != NULL );
1206 MPI_VALIDATE_RET( A != NULL );
1207 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001208
1209 if( X == B )
1210 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001212 }
1213
1214 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001216
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001217 /*
1218 * X should always be positive as a result of unsigned additions.
1219 */
1220 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001221
Paul Bakker23986e52011-04-24 08:57:21 +00001222 for( j = B->n; j > 0; j-- )
1223 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001224 break;
1225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001226 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001227
1228 o = B->p; p = X->p; c = 0;
1229
Janos Follath6c922682015-10-30 17:43:11 +01001230 /*
1231 * tmp is used because it might happen that p == o
1232 */
Paul Bakker23986e52011-04-24 08:57:21 +00001233 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 {
Janos Follath6c922682015-10-30 17:43:11 +01001235 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001236 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001237 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 }
1239
1240 while( c != 0 )
1241 {
1242 if( i >= X->n )
1243 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001244 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001245 p = X->p + i;
1246 }
1247
Paul Bakker2d319fd2012-09-16 21:34:26 +00001248 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001249 }
1250
1251cleanup:
1252
1253 return( ret );
1254}
1255
1256/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001260{
Paul Bakker23986e52011-04-24 08:57:21 +00001261 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001263
1264 for( i = c = 0; i < n; i++, s++, d++ )
1265 {
1266 z = ( *d < c ); *d -= c;
1267 c = ( *d < *s ) + z; *d -= *s;
1268 }
1269
1270 while( c != 0 )
1271 {
1272 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001273 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001274 }
1275}
1276
1277/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001278 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001281{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001282 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001283 int ret;
1284 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001285 MPI_VALIDATE_RET( X != NULL );
1286 MPI_VALIDATE_RET( A != NULL );
1287 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1290 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001293
1294 if( X == B )
1295 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001296 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001297 B = &TB;
1298 }
1299
1300 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001302
Paul Bakker1ef7a532009-06-20 10:50:55 +00001303 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001304 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001305 */
1306 X->s = 1;
1307
Paul Bakker5121ce52009-01-03 21:22:43 +00001308 ret = 0;
1309
Paul Bakker23986e52011-04-24 08:57:21 +00001310 for( n = B->n; n > 0; n-- )
1311 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001312 break;
1313
Paul Bakker23986e52011-04-24 08:57:21 +00001314 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001315
1316cleanup:
1317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001318 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001319
1320 return( ret );
1321}
1322
1323/*
1324 * Signed addition: X = A + B
1325 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001327{
Hanno Becker73d7d792018-12-11 10:35:51 +00001328 int ret, s;
1329 MPI_VALIDATE_RET( X != NULL );
1330 MPI_VALIDATE_RET( A != NULL );
1331 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001332
Hanno Becker73d7d792018-12-11 10:35:51 +00001333 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001334 if( A->s * B->s < 0 )
1335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 X->s = s;
1340 }
1341 else
1342 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001344 X->s = -s;
1345 }
1346 }
1347 else
1348 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001350 X->s = s;
1351 }
1352
1353cleanup:
1354
1355 return( ret );
1356}
1357
1358/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001359 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001362{
Hanno Becker73d7d792018-12-11 10:35:51 +00001363 int ret, s;
1364 MPI_VALIDATE_RET( X != NULL );
1365 MPI_VALIDATE_RET( A != NULL );
1366 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367
Hanno Becker73d7d792018-12-11 10:35:51 +00001368 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001369 if( A->s * B->s > 0 )
1370 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001372 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001373 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001374 X->s = s;
1375 }
1376 else
1377 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 X->s = -s;
1380 }
1381 }
1382 else
1383 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001385 X->s = s;
1386 }
1387
1388cleanup:
1389
1390 return( ret );
1391}
1392
1393/*
1394 * Signed addition: X = A + b
1395 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001397{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 mbedtls_mpi _B;
1399 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001400 MPI_VALIDATE_RET( X != NULL );
1401 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001402
1403 p[0] = ( b < 0 ) ? -b : b;
1404 _B.s = ( b < 0 ) ? -1 : 1;
1405 _B.n = 1;
1406 _B.p = p;
1407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409}
1410
1411/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001412 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001415{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 mbedtls_mpi _B;
1417 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001418 MPI_VALIDATE_RET( X != NULL );
1419 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001420
1421 p[0] = ( b < 0 ) ? -b : b;
1422 _B.s = ( b < 0 ) ? -1 : 1;
1423 _B.n = 1;
1424 _B.p = p;
1425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001427}
1428
1429/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001431 */
1432static
1433#if defined(__APPLE__) && defined(__arm__)
1434/*
1435 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1436 * appears to need this to prevent bad ARM code generation at -O3.
1437 */
1438__attribute__ ((noinline))
1439#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440void 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 +00001441{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001443
1444#if defined(MULADDC_HUIT)
1445 for( ; i >= 8; i -= 8 )
1446 {
1447 MULADDC_INIT
1448 MULADDC_HUIT
1449 MULADDC_STOP
1450 }
1451
1452 for( ; i > 0; i-- )
1453 {
1454 MULADDC_INIT
1455 MULADDC_CORE
1456 MULADDC_STOP
1457 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001458#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001459 for( ; i >= 16; i -= 16 )
1460 {
1461 MULADDC_INIT
1462 MULADDC_CORE MULADDC_CORE
1463 MULADDC_CORE MULADDC_CORE
1464 MULADDC_CORE MULADDC_CORE
1465 MULADDC_CORE MULADDC_CORE
1466
1467 MULADDC_CORE MULADDC_CORE
1468 MULADDC_CORE MULADDC_CORE
1469 MULADDC_CORE MULADDC_CORE
1470 MULADDC_CORE MULADDC_CORE
1471 MULADDC_STOP
1472 }
1473
1474 for( ; i >= 8; i -= 8 )
1475 {
1476 MULADDC_INIT
1477 MULADDC_CORE MULADDC_CORE
1478 MULADDC_CORE MULADDC_CORE
1479
1480 MULADDC_CORE MULADDC_CORE
1481 MULADDC_CORE MULADDC_CORE
1482 MULADDC_STOP
1483 }
1484
1485 for( ; i > 0; i-- )
1486 {
1487 MULADDC_INIT
1488 MULADDC_CORE
1489 MULADDC_STOP
1490 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001491#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001492
1493 t++;
1494
1495 do {
1496 *d += c; c = ( *d < c ); d++;
1497 }
1498 while( c != 0 );
1499}
1500
1501/*
1502 * Baseline multiplication: X = A * B (HAC 14.12)
1503 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001505{
Paul Bakker23986e52011-04-24 08:57:21 +00001506 int ret;
1507 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001508 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001509 MPI_VALIDATE_RET( X != NULL );
1510 MPI_VALIDATE_RET( A != NULL );
1511 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1516 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001517
Paul Bakker23986e52011-04-24 08:57:21 +00001518 for( i = A->n; i > 0; i-- )
1519 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001520 break;
1521
Paul Bakker23986e52011-04-24 08:57:21 +00001522 for( j = B->n; j > 0; j-- )
1523 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001524 break;
1525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001526 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1527 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001528
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001529 for( ; j > 0; j-- )
1530 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001531
1532 X->s = A->s * B->s;
1533
1534cleanup:
1535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
1538 return( ret );
1539}
1540
1541/*
1542 * Baseline multiplication: X = A * b
1543 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001545{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 mbedtls_mpi _B;
1547 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001548 MPI_VALIDATE_RET( X != NULL );
1549 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
1551 _B.s = 1;
1552 _B.n = 1;
1553 _B.p = p;
1554 p[0] = b;
1555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001557}
1558
1559/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001560 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1561 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001562 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001563static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1564 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001565{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001566#if defined(MBEDTLS_HAVE_UDBL)
1567 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001568#else
Simon Butcher9803d072016-01-03 00:24:34 +00001569 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1570 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001571 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1572 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001573 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001574#endif
1575
Simon Butcher15b15d12015-11-26 19:35:03 +00001576 /*
1577 * Check for overflow
1578 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001579 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001580 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001581 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001582
Simon Butcherf5ba0452015-12-27 23:01:55 +00001583 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001584 }
1585
1586#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001587 dividend = (mbedtls_t_udbl) u1 << biL;
1588 dividend |= (mbedtls_t_udbl) u0;
1589 quotient = dividend / d;
1590 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1591 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1592
1593 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001594 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001595
1596 return (mbedtls_mpi_uint) quotient;
1597#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001598
1599 /*
1600 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1601 * Vol. 2 - Seminumerical Algorithms, Knuth
1602 */
1603
1604 /*
1605 * Normalize the divisor, d, and dividend, u0, u1
1606 */
1607 s = mbedtls_clz( d );
1608 d = d << s;
1609
1610 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001611 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001612 u0 = u0 << s;
1613
1614 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001615 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001616
1617 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001618 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001619
1620 /*
1621 * Find the first quotient and remainder
1622 */
1623 q1 = u1 / d1;
1624 r0 = u1 - d1 * q1;
1625
1626 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1627 {
1628 q1 -= 1;
1629 r0 += d1;
1630
1631 if ( r0 >= radix ) break;
1632 }
1633
Simon Butcherf5ba0452015-12-27 23:01:55 +00001634 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001635 q0 = rAX / d1;
1636 r0 = rAX - q0 * d1;
1637
1638 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1639 {
1640 q0 -= 1;
1641 r0 += d1;
1642
1643 if ( r0 >= radix ) break;
1644 }
1645
1646 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001647 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001648
1649 quotient = q1 * radix + q0;
1650
1651 return quotient;
1652#endif
1653}
1654
1655/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001656 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001657 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001658int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1659 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001660{
Paul Bakker23986e52011-04-24 08:57:21 +00001661 int ret;
1662 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001664 MPI_VALIDATE_RET( A != NULL );
1665 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1668 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001669
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001670 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1671 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001674 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001675 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1676 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001677 return( 0 );
1678 }
1679
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1681 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001682 X.s = Y.s = 1;
1683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1685 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1686 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1687 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001688
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001689 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001690 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001691 {
1692 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1694 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001695 }
1696 else k = 0;
1697
1698 n = X.n - 1;
1699 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 {
1704 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001707 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001708
1709 for( i = n; i > t ; i-- )
1710 {
1711 if( X.p[i] >= Y.p[t] )
1712 Z.p[i - t - 1] = ~0;
1713 else
1714 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001715 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1716 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001717 }
1718
1719 Z.p[i - t - 1]++;
1720 do
1721 {
1722 Z.p[i - t - 1]--;
1723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001725 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001726 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001728
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001729 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001730 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1731 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001732 T2.p[2] = X.p[i];
1733 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001735
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1737 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1738 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001740 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001741 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001742 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1743 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1744 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001745 Z.p[i - t - 1]--;
1746 }
1747 }
1748
1749 if( Q != NULL )
1750 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001751 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001752 Q->s = A->s * B->s;
1753 }
1754
1755 if( R != NULL )
1756 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001758 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001762 R->s = 1;
1763 }
1764
1765cleanup:
1766
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001767 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1768 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001769
1770 return( ret );
1771}
1772
1773/*
1774 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001775 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001776int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1777 const mbedtls_mpi *A,
1778 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001779{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001780 mbedtls_mpi _B;
1781 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001782 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001783
1784 p[0] = ( b < 0 ) ? -b : b;
1785 _B.s = ( b < 0 ) ? -1 : 1;
1786 _B.n = 1;
1787 _B.p = p;
1788
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001790}
1791
1792/*
1793 * Modulo: R = A mod B
1794 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001796{
1797 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001798 MPI_VALIDATE_RET( R != NULL );
1799 MPI_VALIDATE_RET( A != NULL );
1800 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1803 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1808 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1811 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001812
1813cleanup:
1814
1815 return( ret );
1816}
1817
1818/*
1819 * Modulo: r = A mod b
1820 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001821int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001822{
Paul Bakker23986e52011-04-24 08:57:21 +00001823 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001825 MPI_VALIDATE_RET( r != NULL );
1826 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
1828 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001830
1831 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
1834 /*
1835 * handle trivial cases
1836 */
1837 if( b == 1 )
1838 {
1839 *r = 0;
1840 return( 0 );
1841 }
1842
1843 if( b == 2 )
1844 {
1845 *r = A->p[0] & 1;
1846 return( 0 );
1847 }
1848
1849 /*
1850 * general case
1851 */
Paul Bakker23986e52011-04-24 08:57:21 +00001852 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 {
Paul Bakker23986e52011-04-24 08:57:21 +00001854 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001855 y = ( y << biH ) | ( x >> biH );
1856 z = y / b;
1857 y -= z * b;
1858
1859 x <<= biH;
1860 y = ( y << biH ) | ( x >> biH );
1861 z = y / b;
1862 y -= z * b;
1863 }
1864
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001865 /*
1866 * If A is negative, then the current y represents a negative value.
1867 * Flipping it to the positive side.
1868 */
1869 if( A->s < 0 && y != 0 )
1870 y = b - y;
1871
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 *r = y;
1873
1874 return( 0 );
1875}
1876
1877/*
1878 * Fast Montgomery initialization (thanks to Tom St Denis)
1879 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001881{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001883 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001884
1885 x = m0;
1886 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001888 for( i = biL; i >= 8; i /= 2 )
1889 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
1891 *mm = ~x + 1;
1892}
1893
1894/*
1895 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1896 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001897static int 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 +02001898 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001899{
Paul Bakker23986e52011-04-24 08:57:21 +00001900 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001902
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001903 if( T->n < N->n + 1 || T->p == NULL )
1904 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1905
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +02001906 mbedtls_platform_memset( T->p, 0, T->n * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
1908 d = T->p;
1909 n = N->n;
1910 m = ( B->n < n ) ? B->n : n;
1911
1912 for( i = 0; i < n; i++ )
1913 {
1914 /*
1915 * T = (T + u0*B + u1*N) / 2^biL
1916 */
1917 u0 = A->p[i];
1918 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1919
1920 mpi_mul_hlp( m, B->p, d, u0 );
1921 mpi_mul_hlp( n, N->p, d, u1 );
1922
1923 *d++ = u0; d[n + 1] = 0;
1924 }
1925
Teppo Järvelin91d79382019-10-02 09:09:31 +03001926 mbedtls_platform_memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001929 mpi_sub_hlp( n, N->p, A->p );
1930 else
1931 /* prevent timing attacks */
1932 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001933
1934 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001935}
1936
1937/*
1938 * Montgomery reduction: A = A * R^-1 mod N
1939 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001940static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1941 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001942{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001943 mbedtls_mpi_uint z = 1;
1944 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
Paul Bakker8ddb6452013-02-27 14:56:33 +01001946 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001947 U.p = &z;
1948
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001949 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950}
1951
1952/*
1953 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1954 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001955int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1956 const mbedtls_mpi *E, const mbedtls_mpi *N,
1957 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001958{
Paul Bakker23986e52011-04-24 08:57:21 +00001959 int ret;
1960 size_t wbits, wsize, one = 1;
1961 size_t i, j, nblimbs;
1962 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 mbedtls_mpi_uint ei, mm, state;
1964 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001965 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
Hanno Becker73d7d792018-12-11 10:35:51 +00001967 MPI_VALIDATE_RET( X != NULL );
1968 MPI_VALIDATE_RET( A != NULL );
1969 MPI_VALIDATE_RET( E != NULL );
1970 MPI_VALIDATE_RET( N != NULL );
1971
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001972 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1976 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001977
1978 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001979 * Init temps and window size
1980 */
1981 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1983 mbedtls_mpi_init( &Apos );
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +02001984 mbedtls_platform_memset( W, 0, sizeof( W ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001986 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
1988 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1989 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1990
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001991#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1993 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001994#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001995
Paul Bakker5121ce52009-01-03 21:22:43 +00001996 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001997 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1998 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1999 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
2001 /*
Paul Bakker50546922012-05-19 08:40:49 +00002002 * Compensate for negative A (and correct at the end)
2003 */
2004 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002005 if( neg )
2006 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002008 Apos.s = 1;
2009 A = &Apos;
2010 }
2011
2012 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002013 * If 1st call, pre-compute R^2 mod N
2014 */
2015 if( _RR == NULL || _RR->p == NULL )
2016 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2018 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2019 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
2021 if( _RR != NULL )
Teppo Järvelin91d79382019-10-02 09:09:31 +03002022 mbedtls_platform_memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002023 }
2024 else
Teppo Järvelin91d79382019-10-02 09:09:31 +03002025 mbedtls_platform_memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
2027 /*
2028 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2029 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2031 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002032 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002035 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
2037 /*
2038 * X = R^2 * R^-1 mod N = R mod N
2039 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002041 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002042
2043 if( wsize > 1 )
2044 {
2045 /*
2046 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2047 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002048 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2051 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
2053 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002054 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002055
Paul Bakker5121ce52009-01-03 21:22:43 +00002056 /*
2057 * W[i] = W[i - 1] * W[1]
2058 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002059 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002060 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2062 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002063
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002064 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002065 }
2066 }
2067
2068 nblimbs = E->n;
2069 bufsize = 0;
2070 nbits = 0;
2071 wbits = 0;
2072 state = 0;
2073
2074 while( 1 )
2075 {
2076 if( bufsize == 0 )
2077 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002078 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002079 break;
2080
Paul Bakker0d7702c2013-10-29 16:18:35 +01002081 nblimbs--;
2082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002084 }
2085
2086 bufsize--;
2087
2088 ei = (E->p[nblimbs] >> bufsize) & 1;
2089
2090 /*
2091 * skip leading 0s
2092 */
2093 if( ei == 0 && state == 0 )
2094 continue;
2095
2096 if( ei == 0 && state == 1 )
2097 {
2098 /*
2099 * out of window, square X
2100 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002101 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002102 continue;
2103 }
2104
2105 /*
2106 * add ei to current window
2107 */
2108 state = 2;
2109
2110 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002111 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
2113 if( nbits == wsize )
2114 {
2115 /*
2116 * X = X^wsize R^-1 mod N
2117 */
2118 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002119 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
2121 /*
2122 * X = X * W[wbits] R^-1 mod N
2123 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002124 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002125
2126 state--;
2127 nbits = 0;
2128 wbits = 0;
2129 }
2130 }
2131
2132 /*
2133 * process the remaining bits
2134 */
2135 for( i = 0; i < nbits; i++ )
2136 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002137 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138
2139 wbits <<= 1;
2140
Paul Bakker66d5d072014-06-17 16:39:18 +02002141 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002142 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143 }
2144
2145 /*
2146 * X = A^E * R * R^-1 mod N = A^E mod N
2147 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002148 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
Hanno Beckera4af1c42017-04-18 09:07:45 +01002150 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002151 {
2152 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002154 }
2155
Paul Bakker5121ce52009-01-03 21:22:43 +00002156cleanup:
2157
Paul Bakker66d5d072014-06-17 16:39:18 +02002158 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002162
Paul Bakker75a28602014-03-31 12:08:17 +02002163 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002164 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002165
2166 return( ret );
2167}
2168
Paul Bakker5121ce52009-01-03 21:22:43 +00002169/*
2170 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2171 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002173{
Paul Bakker23986e52011-04-24 08:57:21 +00002174 int ret;
2175 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
Hanno Becker73d7d792018-12-11 10:35:51 +00002178 MPI_VALIDATE_RET( G != NULL );
2179 MPI_VALIDATE_RET( A != NULL );
2180 MPI_VALIDATE_RET( B != NULL );
2181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2185 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 lz = mbedtls_mpi_lsb( &TA );
2188 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002189
Paul Bakker66d5d072014-06-17 16:39:18 +02002190 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002191 lz = lzt;
2192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2194 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002195
Paul Bakker5121ce52009-01-03 21:22:43 +00002196 TA.s = TB.s = 1;
2197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002199 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2201 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2206 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 }
2208 else
2209 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2211 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002212 }
2213 }
2214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2216 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
2218cleanup:
2219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002221
2222 return( ret );
2223}
2224
Paul Bakker33dc46b2014-04-30 16:11:39 +02002225/*
2226 * Fill X with size bytes of random.
2227 *
2228 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002229 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002230 * deterministic, eg for tests).
2231 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002233 int (*f_rng)(void *, unsigned char *, size_t),
2234 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002235{
Paul Bakker23986e52011-04-24 08:57:21 +00002236 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002237 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002238 size_t const overhead = ( limbs * ciL ) - size;
2239 unsigned char *Xp;
2240
Hanno Becker8ce11a32018-12-19 16:18:52 +00002241 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002242 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002243
Hanno Beckerda1655a2017-10-18 14:21:44 +01002244 /* Ensure that target MPI has exactly the necessary number of limbs */
2245 if( X->n != limbs )
2246 {
2247 mbedtls_mpi_free( X );
2248 mbedtls_mpi_init( X );
2249 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2250 }
2251 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002252
Hanno Beckerda1655a2017-10-18 14:21:44 +01002253 Xp = (unsigned char*) X->p;
2254 f_rng( p_rng, Xp + overhead, size );
2255
Hanno Becker2be8a552018-10-25 12:40:09 +01002256 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002257
2258cleanup:
2259 return( ret );
2260}
2261
Paul Bakker5121ce52009-01-03 21:22:43 +00002262/*
2263 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002266{
2267 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002269 MPI_VALIDATE_RET( X != NULL );
2270 MPI_VALIDATE_RET( A != NULL );
2271 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002272
Hanno Becker4bcb4912017-04-18 15:49:39 +01002273 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2277 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2278 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002285 goto cleanup;
2286 }
2287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2289 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2290 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2291 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2294 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2295 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2296 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002297
2298 do
2299 {
2300 while( ( TU.p[0] & 1 ) == 0 )
2301 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
2304 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2305 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002306 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2307 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 }
2309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2311 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 }
2313
2314 while( ( TV.p[0] & 1 ) == 0 )
2315 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002317
2318 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2319 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2321 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002322 }
2323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2325 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002326 }
2327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2331 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2332 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 }
2334 else
2335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2337 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2338 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002339 }
2340 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2344 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2347 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
2351cleanup:
2352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2354 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2355 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
2357 return( ret );
2358}
2359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002361
Paul Bakker5121ce52009-01-03 21:22:43 +00002362static const int small_prime[] =
2363{
2364 3, 5, 7, 11, 13, 17, 19, 23,
2365 29, 31, 37, 41, 43, 47, 53, 59,
2366 61, 67, 71, 73, 79, 83, 89, 97,
2367 101, 103, 107, 109, 113, 127, 131, 137,
2368 139, 149, 151, 157, 163, 167, 173, 179,
2369 181, 191, 193, 197, 199, 211, 223, 227,
2370 229, 233, 239, 241, 251, 257, 263, 269,
2371 271, 277, 281, 283, 293, 307, 311, 313,
2372 317, 331, 337, 347, 349, 353, 359, 367,
2373 373, 379, 383, 389, 397, 401, 409, 419,
2374 421, 431, 433, 439, 443, 449, 457, 461,
2375 463, 467, 479, 487, 491, 499, 503, 509,
2376 521, 523, 541, 547, 557, 563, 569, 571,
2377 577, 587, 593, 599, 601, 607, 613, 617,
2378 619, 631, 641, 643, 647, 653, 659, 661,
2379 673, 677, 683, 691, 701, 709, 719, 727,
2380 733, 739, 743, 751, 757, 761, 769, 773,
2381 787, 797, 809, 811, 821, 823, 827, 829,
2382 839, 853, 857, 859, 863, 877, 881, 883,
2383 887, 907, 911, 919, 929, 937, 941, 947,
2384 953, 967, 971, 977, 983, 991, 997, -103
2385};
2386
2387/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002388 * Small divisors test (X must be positive)
2389 *
2390 * Return values:
2391 * 0: no small factor (possible prime, more tests needed)
2392 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002394 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002395 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002397{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002398 int ret = 0;
2399 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002400 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002401
Paul Bakker5121ce52009-01-03 21:22:43 +00002402 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
2405 for( i = 0; small_prime[i] > 0; i++ )
2406 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002408 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002410 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002411
2412 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002414 }
2415
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002416cleanup:
2417 return( ret );
2418}
2419
2420/*
2421 * Miller-Rabin pseudo-primality test (HAC 4.24)
2422 */
Janos Follathda31fa12018-09-03 14:45:23 +01002423static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002424 int (*f_rng)(void *, unsigned char *, size_t),
2425 void *p_rng )
2426{
Pascal Junodb99183d2015-03-11 16:49:45 +01002427 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002428 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002430
Hanno Becker8ce11a32018-12-19 16:18:52 +00002431 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002432 MPI_VALIDATE_RET( f_rng != NULL );
2433
2434 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2435 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002437
Paul Bakker5121ce52009-01-03 21:22:43 +00002438 /*
2439 * W = |X| - 1
2440 * R = W >> lsb( W )
2441 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2443 s = mbedtls_mpi_lsb( &W );
2444 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2445 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002446
Janos Follathda31fa12018-09-03 14:45:23 +01002447 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 {
2449 /*
2450 * pick a random A, 1 < A < |X| - 1
2451 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002452 count = 0;
2453 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002454 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002455
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002456 j = mbedtls_mpi_bitlen( &A );
2457 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002458 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002459 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002460 }
2461
2462 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002463 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2464 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002465 }
2466
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002467 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2468 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002469
2470 /*
2471 * A = A^R mod |X|
2472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2476 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002477 continue;
2478
2479 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002481 {
2482 /*
2483 * A = A * A mod |X|
2484 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2486 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002489 break;
2490
2491 j++;
2492 }
2493
2494 /*
2495 * not prime if A != |X| - 1 or A == 1
2496 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2498 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002499 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002501 break;
2502 }
2503 }
2504
2505cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002506 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2507 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002509
2510 return( ret );
2511}
2512
2513/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002514 * Pseudo-primality test: small factors, then Miller-Rabin
2515 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002516int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2517 int (*f_rng)(void *, unsigned char *, size_t),
2518 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002519{
2520 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002522 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002523 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002524
2525 XX.s = 1;
2526 XX.n = X->n;
2527 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2530 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2531 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002534 return( 0 );
2535
2536 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2537 {
2538 if( ret == 1 )
2539 return( 0 );
2540
2541 return( ret );
2542 }
2543
Janos Follathda31fa12018-09-03 14:45:23 +01002544 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002545}
2546
Janos Follatha0b67c22018-09-18 14:48:23 +01002547#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002548/*
2549 * Pseudo-primality test, error probability 2^-80
2550 */
2551int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2552 int (*f_rng)(void *, unsigned char *, size_t),
2553 void *p_rng )
2554{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002555 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002556 MPI_VALIDATE_RET( f_rng != NULL );
2557
Janos Follatha0b67c22018-09-18 14:48:23 +01002558 /*
2559 * In the past our key generation aimed for an error rate of at most
2560 * 2^-80. Since this function is deprecated, aim for the same certainty
2561 * here as well.
2562 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002563 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002564}
Janos Follatha0b67c22018-09-18 14:48:23 +01002565#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002566
2567/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002568 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002569 *
Janos Follathf301d232018-08-14 13:34:01 +01002570 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2571 * be either 1024 bits or 1536 bits long, and flags must contain
2572 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002573 */
Janos Follath7c025a92018-08-14 11:08:41 +01002574int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002575 int (*f_rng)(void *, unsigned char *, size_t),
2576 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002577{
Jethro Beekman66689272018-02-14 19:24:10 -08002578#ifdef MBEDTLS_HAVE_INT64
2579// ceil(2^63.5)
2580#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2581#else
2582// ceil(2^31.5)
2583#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2584#endif
2585 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002586 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002587 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 mbedtls_mpi_uint r;
2589 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002590
Hanno Becker8ce11a32018-12-19 16:18:52 +00002591 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002592 MPI_VALIDATE_RET( f_rng != NULL );
2593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2595 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002598
2599 n = BITS_TO_LIMBS( nbits );
2600
Janos Follathda31fa12018-09-03 14:45:23 +01002601 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2602 {
2603 /*
2604 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2605 */
2606 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2607 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2608 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2609 }
2610 else
2611 {
2612 /*
2613 * 2^-100 error probability, number of rounds computed based on HAC,
2614 * fact 4.48
2615 */
2616 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2617 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2618 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2619 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2620 }
2621
Jethro Beekman66689272018-02-14 19:24:10 -08002622 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002623 {
Jethro Beekman66689272018-02-14 19:24:10 -08002624 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2625 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2626 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2627
2628 k = n * biL;
2629 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2630 X->p[0] |= 1;
2631
Janos Follath7c025a92018-08-14 11:08:41 +01002632 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002634 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002636 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002637 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002638 }
Jethro Beekman66689272018-02-14 19:24:10 -08002639 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002640 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002641 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002642 * An necessary condition for Y and X = 2Y + 1 to be prime
2643 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2644 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002645 */
Jethro Beekman66689272018-02-14 19:24:10 -08002646
2647 X->p[0] |= 2;
2648
2649 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2650 if( r == 0 )
2651 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2652 else if( r == 1 )
2653 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2654
2655 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2656 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2657 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2658
2659 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002660 {
Jethro Beekman66689272018-02-14 19:24:10 -08002661 /*
2662 * First, check small factors for X and Y
2663 * before doing Miller-Rabin on any of them
2664 */
2665 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2666 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002667 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002668 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002669 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002670 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002671 goto cleanup;
2672
2673 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2674 goto cleanup;
2675
2676 /*
2677 * Next candidates. We want to preserve Y = (X-1) / 2 and
2678 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2679 * so up Y by 6 and X by 12.
2680 */
2681 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2682 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002683 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002684 }
2685 }
2686
2687cleanup:
2688
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
2691 return( ret );
2692}
2693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002696#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002697
Paul Bakker23986e52011-04-24 08:57:21 +00002698#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002699
2700static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2701{
2702 { 693, 609, 21 },
2703 { 1764, 868, 28 },
2704 { 768454923, 542167814, 1 }
2705};
2706
Paul Bakker5121ce52009-01-03 21:22:43 +00002707/*
2708 * Checkup routine
2709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002710int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002711{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002712 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002713 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002714
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002715 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2716 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002718 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002719 "EFE021C2645FD1DC586E69184AF4A31E" \
2720 "D5F53E93B5F123FA41680867BA110131" \
2721 "944FE7952E2517337780CB0DB80E61AA" \
2722 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002724 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002725 "B2E7EFD37075B9F03FF989C7C5051C20" \
2726 "34D2A323810251127E7BF8625A4F49A5" \
2727 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2728 "5B5C25763222FEFCCFC38B832366C29E" ) );
2729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002731 "0066A198186C18C10B2F5ED9B522752A" \
2732 "9830B69916E535C8F047518A889A43A5" \
2733 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002735 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002737 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002738 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2739 "9E857EA95A03512E2BAE7391688D264A" \
2740 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2741 "8001B72E848A38CAE1C65F78E56ABDEF" \
2742 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2743 "ECF677152EF804370C1A305CAF3B5BF1" \
2744 "30879B56C61DE584A0F53A2447A51E" ) );
2745
2746 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002749 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002750 {
2751 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002753
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002754 ret = 1;
2755 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002756 }
2757
2758 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002761 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002763 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002764 "256567336059E52CAE22925474705F39A94" ) );
2765
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002766 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002767 "6613F26162223DF488E9CD48CC132C7A" \
2768 "0AC93C701B001B092E4E5B9F73BCD27B" \
2769 "9EE50D0657C77F374E903CDFA4C642" ) );
2770
2771 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002772 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2775 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002776 {
2777 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002778 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002779
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002780 ret = 1;
2781 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002782 }
2783
2784 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002787 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002788
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002790 "36E139AEA55215609D2816998ED020BB" \
2791 "BD96C37890F65171D948E9BC7CBAA4D9" \
2792 "325D24D6A3C12710F10A09FA08AB87" ) );
2793
2794 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002797 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002798 {
2799 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002800 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002801
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002802 ret = 1;
2803 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002804 }
2805
2806 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002808
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002809 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002810
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002812 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2813 "C3DBA76456363A10869622EAC2DD84EC" \
2814 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2815
2816 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002818
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002819 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002820 {
2821 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002822 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002823
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002824 ret = 1;
2825 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002826 }
2827
2828 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002829 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002830
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002831 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002832 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002833
Paul Bakker66d5d072014-06-17 16:39:18 +02002834 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002835 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002836 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2837 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002838
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002839 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002841 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002842 {
2843 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002844 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002845
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002846 ret = 1;
2847 goto cleanup;
2848 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002849 }
2850
2851 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002852 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002853
Paul Bakker5121ce52009-01-03 21:22:43 +00002854cleanup:
2855
2856 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002857 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002859 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2860 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002861
2862 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002863 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002864
2865 return( ret );
2866}
2867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002868#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002870#endif /* MBEDTLS_BIGNUM_C */