blob: 65696470d47d1d08a2b0d7ced96cdb501f83aa11 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
Ron Eldora16fa292018-11-20 14:07:01 +0200530 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000531 */
Ron Eldora16fa292018-11-20 14:07:01 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix,
533 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534{
535 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200537 size_t length = 0;
538 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Ron Eldora16fa292018-11-20 14:07:01 +0200540 do
541 {
542 if( length >= buflen )
543 {
544 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
545 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
Ron Eldora16fa292018-11-20 14:07:01 +0200547 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
548 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
549 /*
550 * Write the residue in the current position, as an ASCII character.
551 */
552 if( r < 0xA )
553 *(--p_end) = (char)( '0' + r );
554 else
555 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Ron Eldora16fa292018-11-20 14:07:01 +0200557 length++;
558 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Ron Eldora16fa292018-11-20 14:07:01 +0200560 memmove( *p, p_end, length );
561 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563cleanup:
564
565 return( ret );
566}
567
568/*
569 * Export into an ASCII string
570 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
572 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573{
Paul Bakker23986e52011-04-24 08:57:21 +0000574 int ret = 0;
575 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000578 MPI_VALIDATE_RET( X != NULL );
579 MPI_VALIDATE_RET( olen != NULL );
580 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
582 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000583 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Hanno Becker23cfea02019-02-04 09:45:07 +0000585 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
586 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
587 * `n`. If radix > 4, this might be a strict
588 * overapproximation of the number of
589 * radix-adic digits needed to present `n`. */
590 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
591 * present `n`. */
592
Janos Follath80470622019-03-06 13:43:02 +0000593 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000594 n += 1; /* Compensate for the divisions above, which round down `n`
595 * in case it's not even. */
596 n += 1; /* Potential '-'-sign. */
597 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
598 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100600 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100602 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 }
605
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100606 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
609 if( X->s == -1 )
Hanno Beckerc983c812019-02-01 16:41:30 +0000610 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000612 buflen--;
613 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 if( radix == 16 )
616 {
Paul Bakker23986e52011-04-24 08:57:21 +0000617 int c;
618 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
Paul Bakker23986e52011-04-24 08:57:21 +0000620 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 {
Paul Bakker23986e52011-04-24 08:57:21 +0000622 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 {
Paul Bakker23986e52011-04-24 08:57:21 +0000624 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
Paul Bakker6c343d72014-07-10 14:36:19 +0200626 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000627 continue;
628
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000629 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000630 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000631 k = 1;
632 }
633 }
634 }
635 else
636 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000638
639 if( T.s == -1 )
640 T.s = 1;
641
Ron Eldora16fa292018-11-20 14:07:01 +0200642 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 }
644
645 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100646 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
648cleanup:
649
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
652 return( ret );
653}
654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000656/*
657 * Read X from an opened file
658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000660{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000662 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000664 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000665 * Buffer should have space for (short) label and decimal formatted MPI,
666 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
Hanno Becker73d7d792018-12-11 10:35:51 +0000670 MPI_VALIDATE_RET( X != NULL );
671 MPI_VALIDATE_RET( fin != NULL );
672
673 if( radix < 2 || radix > 16 )
674 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
675
Paul Bakker5121ce52009-01-03 21:22:43 +0000676 memset( s, 0, sizeof( s ) );
677 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
680 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000681 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000683
Hanno Beckerb2034b72017-04-26 11:46:46 +0100684 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
685 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100688 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 if( mpi_get_digit( &d, radix, *p ) != 0 )
690 break;
691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693}
694
695/*
696 * Write X into an opened file (or stdout if fout == NULL)
697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000699{
Paul Bakker23986e52011-04-24 08:57:21 +0000700 int ret;
701 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000702 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000703 * Buffer should have space for (short) label and decimal formatted MPI,
704 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000705 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000707 MPI_VALIDATE_RET( X != NULL );
708
709 if( radix < 2 || radix > 16 )
710 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100712 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100714 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 if( p == NULL ) p = "";
717
718 plen = strlen( p );
719 slen = strlen( s );
720 s[slen++] = '\r';
721 s[slen++] = '\n';
722
723 if( fout != NULL )
724 {
725 if( fwrite( p, 1, plen, fout ) != plen ||
726 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000728 }
729 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000731
732cleanup:
733
734 return( ret );
735}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
Hanno Beckerda1655a2017-10-18 14:21:44 +0100738
739/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
740 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000741
742static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
743{
744 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100745 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000746 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100747
748 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
749 {
750 tmp <<= CHAR_BIT;
751 tmp |= (mbedtls_mpi_uint) *x_ptr;
752 }
753
Hanno Beckerf8720072018-11-08 11:53:49 +0000754 return( tmp );
755}
756
757static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
758{
759#if defined(__BYTE_ORDER__)
760
761/* Nothing to do on bigendian systems. */
762#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
763 return( x );
764#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
765
766#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
767
768/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000769#if defined(__GNUC__) && defined(__GNUC_PREREQ)
770#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000771#define have_bswap
772#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000773#endif
774
775#if defined(__clang__) && defined(__has_builtin)
776#if __has_builtin(__builtin_bswap32) && \
777 __has_builtin(__builtin_bswap64)
778#define have_bswap
779#endif
780#endif
781
Hanno Beckerf8720072018-11-08 11:53:49 +0000782#if defined(have_bswap)
783 /* The compiler is hopefully able to statically evaluate this! */
784 switch( sizeof(mbedtls_mpi_uint) )
785 {
786 case 4:
787 return( __builtin_bswap32(x) );
788 case 8:
789 return( __builtin_bswap64(x) );
790 }
791#endif
792#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
793#endif /* __BYTE_ORDER__ */
794
795 /* Fall back to C-based reordering if we don't know the byte order
796 * or we couldn't use a compiler-specific builtin. */
797 return( mpi_uint_bigendian_to_host_c( x ) );
798}
799
Hanno Becker2be8a552018-10-25 12:40:09 +0100800static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100801{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100802 mbedtls_mpi_uint *cur_limb_left;
803 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100804 if( limbs == 0 )
805 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100806
807 /*
808 * Traverse limbs and
809 * - adapt byte-order in each limb
810 * - swap the limbs themselves.
811 * For that, simultaneously traverse the limbs from left to right
812 * and from right to left, as long as the left index is not bigger
813 * than the right index (it's not a problem if limbs is odd and the
814 * indices coincide in the last iteration).
815 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100816 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
817 cur_limb_left <= cur_limb_right;
818 cur_limb_left++, cur_limb_right-- )
819 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000820 mbedtls_mpi_uint tmp;
821 /* Note that if cur_limb_left == cur_limb_right,
822 * this code effectively swaps the bytes only once. */
823 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
824 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
825 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100826 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100827}
828
Paul Bakker5121ce52009-01-03 21:22:43 +0000829/*
Janos Follatha778a942019-02-13 10:28:28 +0000830 * Import X from unsigned binary data, little endian
831 */
832int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
833 const unsigned char *buf, size_t buflen )
834{
835 int ret;
836 size_t i;
837 size_t const limbs = CHARS_TO_LIMBS( buflen );
838
839 /* Ensure that target MPI has exactly the necessary number of limbs */
840 if( X->n != limbs )
841 {
842 mbedtls_mpi_free( X );
843 mbedtls_mpi_init( X );
844 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
845 }
846
847 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
848
849 for( i = 0; i < buflen; i++ )
850 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
851
852cleanup:
853
Janos Follath171a7ef2019-02-15 16:17:45 +0000854 /*
855 * This function is also used to import keys. However, wiping the buffers
856 * upon failure is not necessary because failure only can happen before any
857 * input is copied.
858 */
Janos Follatha778a942019-02-13 10:28:28 +0000859 return( ret );
860}
861
862/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000863 * Import X from unsigned binary data, big endian
864 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200865int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000866{
Paul Bakker23986e52011-04-24 08:57:21 +0000867 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100868 size_t const limbs = CHARS_TO_LIMBS( buflen );
869 size_t const overhead = ( limbs * ciL ) - buflen;
870 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000871
Hanno Becker8ce11a32018-12-19 16:18:52 +0000872 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000873 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
874
Hanno Becker073c1992017-10-17 15:17:27 +0100875 /* Ensure that target MPI has exactly the necessary number of limbs */
876 if( X->n != limbs )
877 {
878 mbedtls_mpi_free( X );
879 mbedtls_mpi_init( X );
880 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
881 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000883
Hanno Becker0e810b92019-01-03 17:13:11 +0000884 /* Avoid calling `memcpy` with NULL source argument,
885 * even if buflen is 0. */
886 if( buf != NULL )
887 {
888 Xp = (unsigned char*) X->p;
889 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100890
Hanno Becker0e810b92019-01-03 17:13:11 +0000891 mpi_bigendian_to_host( X->p, limbs );
892 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000893
894cleanup:
895
Janos Follath171a7ef2019-02-15 16:17:45 +0000896 /*
897 * This function is also used to import keys. However, wiping the buffers
898 * upon failure is not necessary because failure only can happen before any
899 * input is copied.
900 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000901 return( ret );
902}
903
904/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000905 * Export X into unsigned binary data, little endian
906 */
907int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
908 unsigned char *buf, size_t buflen )
909{
910 size_t stored_bytes = X->n * ciL;
911 size_t bytes_to_copy;
912 size_t i;
913
914 if( stored_bytes < buflen )
915 {
916 bytes_to_copy = stored_bytes;
917 }
918 else
919 {
920 bytes_to_copy = buflen;
921
922 /* The output buffer is smaller than the allocated size of X.
923 * However X may fit if its leading bytes are zero. */
924 for( i = bytes_to_copy; i < stored_bytes; i++ )
925 {
926 if( GET_BYTE( X, i ) != 0 )
927 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
928 }
929 }
930
931 for( i = 0; i < bytes_to_copy; i++ )
932 buf[i] = GET_BYTE( X, i );
933
934 if( stored_bytes < buflen )
935 {
936 /* Write trailing 0 bytes */
937 memset( buf + stored_bytes, 0, buflen - stored_bytes );
938 }
939
940 return( 0 );
941}
942
943/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000944 * Export X into unsigned binary data, big endian
945 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100946int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
947 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000948{
Hanno Becker73d7d792018-12-11 10:35:51 +0000949 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100950 size_t bytes_to_copy;
951 unsigned char *p;
952 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000953
Hanno Becker73d7d792018-12-11 10:35:51 +0000954 MPI_VALIDATE_RET( X != NULL );
955 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
956
957 stored_bytes = X->n * ciL;
958
Gilles Peskine11cdb052018-11-20 16:47:47 +0100959 if( stored_bytes < buflen )
960 {
961 /* There is enough space in the output buffer. Write initial
962 * null bytes and record the position at which to start
963 * writing the significant bytes. In this case, the execution
964 * trace of this function does not depend on the value of the
965 * number. */
966 bytes_to_copy = stored_bytes;
967 p = buf + buflen - stored_bytes;
968 memset( buf, 0, buflen - stored_bytes );
969 }
970 else
971 {
972 /* The output buffer is smaller than the allocated size of X.
973 * However X may fit if its leading bytes are zero. */
974 bytes_to_copy = buflen;
975 p = buf;
976 for( i = bytes_to_copy; i < stored_bytes; i++ )
977 {
978 if( GET_BYTE( X, i ) != 0 )
979 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
980 }
981 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000982
Gilles Peskine11cdb052018-11-20 16:47:47 +0100983 for( i = 0; i < bytes_to_copy; i++ )
984 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000985
986 return( 0 );
987}
988
989/*
990 * Left-shift: X <<= count
991 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000993{
Paul Bakker23986e52011-04-24 08:57:21 +0000994 int ret;
995 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200996 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000997 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000998
999 v0 = count / (biL );
1000 t1 = count & (biL - 1);
1001
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001002 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +00001003
Paul Bakkerf9688572011-05-05 10:00:45 +00001004 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001005 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001006
1007 ret = 0;
1008
1009 /*
1010 * shift by count / limb_size
1011 */
1012 if( v0 > 0 )
1013 {
Paul Bakker23986e52011-04-24 08:57:21 +00001014 for( i = X->n; i > v0; i-- )
1015 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001016
Paul Bakker23986e52011-04-24 08:57:21 +00001017 for( ; i > 0; i-- )
1018 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001019 }
1020
1021 /*
1022 * shift by count % limb_size
1023 */
1024 if( t1 > 0 )
1025 {
1026 for( i = v0; i < X->n; i++ )
1027 {
1028 r1 = X->p[i] >> (biL - t1);
1029 X->p[i] <<= t1;
1030 X->p[i] |= r0;
1031 r0 = r1;
1032 }
1033 }
1034
1035cleanup:
1036
1037 return( ret );
1038}
1039
1040/*
1041 * Right-shift: X >>= count
1042 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001043int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001044{
Paul Bakker23986e52011-04-24 08:57:21 +00001045 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001047 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001048
1049 v0 = count / biL;
1050 v1 = count & (biL - 1);
1051
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001052 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001054
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 /*
1056 * shift by count / limb_size
1057 */
1058 if( v0 > 0 )
1059 {
1060 for( i = 0; i < X->n - v0; i++ )
1061 X->p[i] = X->p[i + v0];
1062
1063 for( ; i < X->n; i++ )
1064 X->p[i] = 0;
1065 }
1066
1067 /*
1068 * shift by count % limb_size
1069 */
1070 if( v1 > 0 )
1071 {
Paul Bakker23986e52011-04-24 08:57:21 +00001072 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 {
Paul Bakker23986e52011-04-24 08:57:21 +00001074 r1 = X->p[i - 1] << (biL - v1);
1075 X->p[i - 1] >>= v1;
1076 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001077 r0 = r1;
1078 }
1079 }
1080
1081 return( 0 );
1082}
1083
1084/*
1085 * Compare unsigned values
1086 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001088{
Paul Bakker23986e52011-04-24 08:57:21 +00001089 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001090 MPI_VALIDATE_RET( X != NULL );
1091 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001092
Paul Bakker23986e52011-04-24 08:57:21 +00001093 for( i = X->n; i > 0; i-- )
1094 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 break;
1096
Paul Bakker23986e52011-04-24 08:57:21 +00001097 for( j = Y->n; j > 0; j-- )
1098 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001099 break;
1100
Paul Bakker23986e52011-04-24 08:57:21 +00001101 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001102 return( 0 );
1103
1104 if( i > j ) return( 1 );
1105 if( j > i ) return( -1 );
1106
Paul Bakker23986e52011-04-24 08:57:21 +00001107 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001108 {
Paul Bakker23986e52011-04-24 08:57:21 +00001109 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1110 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001111 }
1112
1113 return( 0 );
1114}
1115
1116/*
1117 * Compare signed values
1118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001120{
Paul Bakker23986e52011-04-24 08:57:21 +00001121 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001122 MPI_VALIDATE_RET( X != NULL );
1123 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001124
Paul Bakker23986e52011-04-24 08:57:21 +00001125 for( i = X->n; i > 0; i-- )
1126 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001127 break;
1128
Paul Bakker23986e52011-04-24 08:57:21 +00001129 for( j = Y->n; j > 0; j-- )
1130 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001131 break;
1132
Paul Bakker23986e52011-04-24 08:57:21 +00001133 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001134 return( 0 );
1135
1136 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001137 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001138
1139 if( X->s > 0 && Y->s < 0 ) return( 1 );
1140 if( Y->s > 0 && X->s < 0 ) return( -1 );
1141
Paul Bakker23986e52011-04-24 08:57:21 +00001142 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 {
Paul Bakker23986e52011-04-24 08:57:21 +00001144 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1145 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001146 }
1147
1148 return( 0 );
1149}
1150
Janos Follath0e5532d2019-10-11 14:21:53 +01001151static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1152 const mbedtls_mpi_uint y )
Janos Follathee6abce2019-09-05 14:47:19 +01001153{
1154 mbedtls_mpi_uint ret;
1155 mbedtls_mpi_uint cond;
1156
1157 /*
1158 * Check if the most significant bits (MSB) of the operands are different.
1159 */
1160 cond = ( x ^ y );
1161 /*
1162 * If the MSB are the same then the difference x-y will be negative (and
1163 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1164 */
1165 ret = ( x - y ) & ~cond;
1166 /*
1167 * If the MSB are different, then the operand with the MSB of 1 is the
1168 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1169 * the MSB of y is 0.)
1170 */
1171 ret |= y & cond;
1172
1173
1174 ret = ret >> ( sizeof( mbedtls_mpi_uint ) * 8 - 1 );
1175
1176 return ret;
1177}
1178
1179/*
1180 * Compare signed values in constant time
1181 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001182int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1183 unsigned *ret )
Janos Follathee6abce2019-09-05 14:47:19 +01001184{
1185 size_t i;
Janos Follathb2590792019-09-23 09:19:14 +01001186 unsigned int cond, done, sign_X, sign_Y;
Janos Follathee6abce2019-09-05 14:47:19 +01001187
1188 MPI_VALIDATE_RET( X != NULL );
1189 MPI_VALIDATE_RET( Y != NULL );
1190 MPI_VALIDATE_RET( ret != NULL );
1191
1192 if( X->n != Y->n )
1193 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1194
1195 /*
Janos Follath0e5532d2019-10-11 14:21:53 +01001196 * Get sign bits of the signs.
Janos Follathee6abce2019-09-05 14:47:19 +01001197 */
Janos Follathb2590792019-09-23 09:19:14 +01001198 sign_X = X->s;
Janos Follath0e5532d2019-10-11 14:21:53 +01001199 sign_X = sign_X >> ( sizeof( unsigned int ) * 8 - 1 );
Janos Follathb2590792019-09-23 09:19:14 +01001200 sign_Y = Y->s;
Janos Follath0e5532d2019-10-11 14:21:53 +01001201 sign_Y = sign_Y >> ( sizeof( unsigned int ) * 8 - 1 );
1202
1203 /*
1204 * If the signs are different, then the positive operand is the bigger.
1205 * That is if X is negative (sign bit 1), then X < Y is true and it is false
1206 * if X is positive (sign bit 0).
1207 */
1208 cond = ( sign_X ^ sign_Y );
1209 *ret = cond & sign_X;
1210
1211 /*
1212 * This is a constant time function, we might have the result, but we still
1213 * need to go through the loop. Record if we have the result already.
1214 */
Janos Follathee6abce2019-09-05 14:47:19 +01001215 done = cond;
1216
1217 for( i = X->n; i > 0; i-- )
1218 {
1219 /*
Janos Follath0e5532d2019-10-11 14:21:53 +01001220 * If Y->p[i - 1] < X->p[i - 1] and both X and Y are negative, then
1221 * X < Y.
1222 *
1223 * Again even if we can make a decision, we just mark the result and
1224 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001225 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001226 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ) & sign_X;
1227 *ret |= cond & ( 1 - done );
Janos Follath1fc97592019-10-11 10:43:40 +01001228 done |= cond & ( 1 - done );
Janos Follathee6abce2019-09-05 14:47:19 +01001229
1230 /*
Janos Follath0e5532d2019-10-11 14:21:53 +01001231 * If X->p[i - 1] < Y->p[i - 1] and both X and Y are positive, then
1232 * X < Y.
1233 *
1234 * Again even if we can make a decision, we just mark the result and
1235 * the fact that we are done and continue looping.
Janos Follathee6abce2019-09-05 14:47:19 +01001236 */
Janos Follath0e5532d2019-10-11 14:21:53 +01001237 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ) & ( 1 - sign_X );
1238 *ret |= cond & ( 1 - done );
Janos Follath1fc97592019-10-11 10:43:40 +01001239 done |= cond & ( 1 - done );
Janos Follathee6abce2019-09-05 14:47:19 +01001240 }
1241
1242 return( 0 );
1243}
1244
Paul Bakker5121ce52009-01-03 21:22:43 +00001245/*
1246 * Compare signed values
1247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001249{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 mbedtls_mpi Y;
1251 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001252 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001253
1254 *p = ( z < 0 ) ? -z : z;
1255 Y.s = ( z < 0 ) ? -1 : 1;
1256 Y.n = 1;
1257 Y.p = p;
1258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001260}
1261
1262/*
1263 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001266{
Paul Bakker23986e52011-04-24 08:57:21 +00001267 int ret;
1268 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001269 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001270 MPI_VALIDATE_RET( X != NULL );
1271 MPI_VALIDATE_RET( A != NULL );
1272 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001273
1274 if( X == B )
1275 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001276 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001277 }
1278
1279 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001281
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001282 /*
1283 * X should always be positive as a result of unsigned additions.
1284 */
1285 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001286
Paul Bakker23986e52011-04-24 08:57:21 +00001287 for( j = B->n; j > 0; j-- )
1288 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001289 break;
1290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001292
1293 o = B->p; p = X->p; c = 0;
1294
Janos Follath6c922682015-10-30 17:43:11 +01001295 /*
1296 * tmp is used because it might happen that p == o
1297 */
Paul Bakker23986e52011-04-24 08:57:21 +00001298 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001299 {
Janos Follath6c922682015-10-30 17:43:11 +01001300 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001301 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001302 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001303 }
1304
1305 while( c != 0 )
1306 {
1307 if( i >= X->n )
1308 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001309 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001310 p = X->p + i;
1311 }
1312
Paul Bakker2d319fd2012-09-16 21:34:26 +00001313 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001314 }
1315
1316cleanup:
1317
1318 return( ret );
1319}
1320
1321/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001323 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001325{
Paul Bakker23986e52011-04-24 08:57:21 +00001326 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001328
1329 for( i = c = 0; i < n; i++, s++, d++ )
1330 {
1331 z = ( *d < c ); *d -= c;
1332 c = ( *d < *s ) + z; *d -= *s;
1333 }
1334
1335 while( c != 0 )
1336 {
1337 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001338 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 }
1340}
1341
1342/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001343 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001344 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001346{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001348 int ret;
1349 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001350 MPI_VALIDATE_RET( X != NULL );
1351 MPI_VALIDATE_RET( A != NULL );
1352 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1355 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001358
1359 if( X == B )
1360 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 B = &TB;
1363 }
1364
1365 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367
Paul Bakker1ef7a532009-06-20 10:50:55 +00001368 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001369 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001370 */
1371 X->s = 1;
1372
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 ret = 0;
1374
Paul Bakker23986e52011-04-24 08:57:21 +00001375 for( n = B->n; n > 0; n-- )
1376 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001377 break;
1378
Paul Bakker23986e52011-04-24 08:57:21 +00001379 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380
1381cleanup:
1382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001384
1385 return( ret );
1386}
1387
1388/*
1389 * Signed addition: X = A + B
1390 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001392{
Hanno Becker73d7d792018-12-11 10:35:51 +00001393 int ret, s;
1394 MPI_VALIDATE_RET( X != NULL );
1395 MPI_VALIDATE_RET( A != NULL );
1396 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001397
Hanno Becker73d7d792018-12-11 10:35:51 +00001398 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001399 if( A->s * B->s < 0 )
1400 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404 X->s = s;
1405 }
1406 else
1407 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409 X->s = -s;
1410 }
1411 }
1412 else
1413 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415 X->s = s;
1416 }
1417
1418cleanup:
1419
1420 return( ret );
1421}
1422
1423/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001424 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001427{
Hanno Becker73d7d792018-12-11 10:35:51 +00001428 int ret, s;
1429 MPI_VALIDATE_RET( X != NULL );
1430 MPI_VALIDATE_RET( A != NULL );
1431 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001432
Hanno Becker73d7d792018-12-11 10:35:51 +00001433 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 if( A->s * B->s > 0 )
1435 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001437 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001439 X->s = s;
1440 }
1441 else
1442 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001444 X->s = -s;
1445 }
1446 }
1447 else
1448 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001450 X->s = s;
1451 }
1452
1453cleanup:
1454
1455 return( ret );
1456}
1457
1458/*
1459 * Signed addition: X = A + b
1460 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001462{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001463 mbedtls_mpi _B;
1464 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001465 MPI_VALIDATE_RET( X != NULL );
1466 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001467
1468 p[0] = ( b < 0 ) ? -b : b;
1469 _B.s = ( b < 0 ) ? -1 : 1;
1470 _B.n = 1;
1471 _B.p = p;
1472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001474}
1475
1476/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001477 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001478 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001479int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001480{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 mbedtls_mpi _B;
1482 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001483 MPI_VALIDATE_RET( X != NULL );
1484 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001485
1486 p[0] = ( b < 0 ) ? -b : b;
1487 _B.s = ( b < 0 ) ? -1 : 1;
1488 _B.n = 1;
1489 _B.p = p;
1490
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001492}
1493
1494/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001495 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001496 */
1497static
1498#if defined(__APPLE__) && defined(__arm__)
1499/*
1500 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1501 * appears to need this to prevent bad ARM code generation at -O3.
1502 */
1503__attribute__ ((noinline))
1504#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001505void 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 +00001506{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
1509#if defined(MULADDC_HUIT)
1510 for( ; i >= 8; i -= 8 )
1511 {
1512 MULADDC_INIT
1513 MULADDC_HUIT
1514 MULADDC_STOP
1515 }
1516
1517 for( ; i > 0; i-- )
1518 {
1519 MULADDC_INIT
1520 MULADDC_CORE
1521 MULADDC_STOP
1522 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001523#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001524 for( ; i >= 16; i -= 16 )
1525 {
1526 MULADDC_INIT
1527 MULADDC_CORE MULADDC_CORE
1528 MULADDC_CORE MULADDC_CORE
1529 MULADDC_CORE MULADDC_CORE
1530 MULADDC_CORE MULADDC_CORE
1531
1532 MULADDC_CORE MULADDC_CORE
1533 MULADDC_CORE MULADDC_CORE
1534 MULADDC_CORE MULADDC_CORE
1535 MULADDC_CORE MULADDC_CORE
1536 MULADDC_STOP
1537 }
1538
1539 for( ; i >= 8; i -= 8 )
1540 {
1541 MULADDC_INIT
1542 MULADDC_CORE MULADDC_CORE
1543 MULADDC_CORE MULADDC_CORE
1544
1545 MULADDC_CORE MULADDC_CORE
1546 MULADDC_CORE MULADDC_CORE
1547 MULADDC_STOP
1548 }
1549
1550 for( ; i > 0; i-- )
1551 {
1552 MULADDC_INIT
1553 MULADDC_CORE
1554 MULADDC_STOP
1555 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001556#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001557
1558 t++;
1559
1560 do {
1561 *d += c; c = ( *d < c ); d++;
1562 }
1563 while( c != 0 );
1564}
1565
1566/*
1567 * Baseline multiplication: X = A * B (HAC 14.12)
1568 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001570{
Paul Bakker23986e52011-04-24 08:57:21 +00001571 int ret;
1572 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001574 MPI_VALIDATE_RET( X != NULL );
1575 MPI_VALIDATE_RET( A != NULL );
1576 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001580 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1581 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
Paul Bakker23986e52011-04-24 08:57:21 +00001583 for( i = A->n; i > 0; i-- )
1584 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 break;
1586
Paul Bakker23986e52011-04-24 08:57:21 +00001587 for( j = B->n; j > 0; j-- )
1588 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 break;
1590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1592 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001593
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001594 for( ; j > 0; j-- )
1595 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001596
1597 X->s = A->s * B->s;
1598
1599cleanup:
1600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001602
1603 return( ret );
1604}
1605
1606/*
1607 * Baseline multiplication: X = A * b
1608 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001610{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 mbedtls_mpi _B;
1612 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001613 MPI_VALIDATE_RET( X != NULL );
1614 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001615
1616 _B.s = 1;
1617 _B.n = 1;
1618 _B.p = p;
1619 p[0] = b;
1620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001622}
1623
1624/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001625 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1626 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001627 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001628static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1629 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001630{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001631#if defined(MBEDTLS_HAVE_UDBL)
1632 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001633#else
Simon Butcher9803d072016-01-03 00:24:34 +00001634 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1635 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001636 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1637 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001638 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001639#endif
1640
Simon Butcher15b15d12015-11-26 19:35:03 +00001641 /*
1642 * Check for overflow
1643 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001644 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001645 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001646 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001647
Simon Butcherf5ba0452015-12-27 23:01:55 +00001648 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001649 }
1650
1651#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001652 dividend = (mbedtls_t_udbl) u1 << biL;
1653 dividend |= (mbedtls_t_udbl) u0;
1654 quotient = dividend / d;
1655 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1656 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1657
1658 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001659 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001660
1661 return (mbedtls_mpi_uint) quotient;
1662#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001663
1664 /*
1665 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1666 * Vol. 2 - Seminumerical Algorithms, Knuth
1667 */
1668
1669 /*
1670 * Normalize the divisor, d, and dividend, u0, u1
1671 */
1672 s = mbedtls_clz( d );
1673 d = d << s;
1674
1675 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001676 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001677 u0 = u0 << s;
1678
1679 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001680 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001681
1682 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001683 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001684
1685 /*
1686 * Find the first quotient and remainder
1687 */
1688 q1 = u1 / d1;
1689 r0 = u1 - d1 * q1;
1690
1691 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1692 {
1693 q1 -= 1;
1694 r0 += d1;
1695
1696 if ( r0 >= radix ) break;
1697 }
1698
Simon Butcherf5ba0452015-12-27 23:01:55 +00001699 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001700 q0 = rAX / d1;
1701 r0 = rAX - q0 * d1;
1702
1703 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1704 {
1705 q0 -= 1;
1706 r0 += d1;
1707
1708 if ( r0 >= radix ) break;
1709 }
1710
1711 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001712 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001713
1714 quotient = q1 * radix + q0;
1715
1716 return quotient;
1717#endif
1718}
1719
1720/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001723int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1724 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001725{
Paul Bakker23986e52011-04-24 08:57:21 +00001726 int ret;
1727 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001729 MPI_VALIDATE_RET( A != NULL );
1730 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1733 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001735 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1736 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001740 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1741 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001742 return( 0 );
1743 }
1744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1746 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001747 X.s = Y.s = 1;
1748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1750 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1751 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1752 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001754 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001755 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 {
1757 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1759 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 }
1761 else k = 0;
1762
1763 n = X.n - 1;
1764 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001766
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001767 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001768 {
1769 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001770 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001771 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001772 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001773
1774 for( i = n; i > t ; i-- )
1775 {
1776 if( X.p[i] >= Y.p[t] )
1777 Z.p[i - t - 1] = ~0;
1778 else
1779 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001780 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1781 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001782 }
1783
1784 Z.p[i - t - 1]++;
1785 do
1786 {
1787 Z.p[i - t - 1]--;
1788
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001790 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001791 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001795 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1796 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001797 T2.p[2] = X.p[i];
1798 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001800
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1802 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1803 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001806 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1808 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1809 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001810 Z.p[i - t - 1]--;
1811 }
1812 }
1813
1814 if( Q != NULL )
1815 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817 Q->s = A->s * B->s;
1818 }
1819
1820 if( R != NULL )
1821 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001823 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001827 R->s = 1;
1828 }
1829
1830cleanup:
1831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1833 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001834
1835 return( ret );
1836}
1837
1838/*
1839 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001840 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001841int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1842 const mbedtls_mpi *A,
1843 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001844{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 mbedtls_mpi _B;
1846 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001847 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
1849 p[0] = ( b < 0 ) ? -b : b;
1850 _B.s = ( b < 0 ) ? -1 : 1;
1851 _B.n = 1;
1852 _B.p = p;
1853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855}
1856
1857/*
1858 * Modulo: R = A mod B
1859 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001861{
1862 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001863 MPI_VALIDATE_RET( R != NULL );
1864 MPI_VALIDATE_RET( A != NULL );
1865 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001866
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1868 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001872 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1873 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001874
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1876 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001877
1878cleanup:
1879
1880 return( ret );
1881}
1882
1883/*
1884 * Modulo: r = A mod b
1885 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001887{
Paul Bakker23986e52011-04-24 08:57:21 +00001888 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001890 MPI_VALIDATE_RET( r != NULL );
1891 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
1893 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001895
1896 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
1899 /*
1900 * handle trivial cases
1901 */
1902 if( b == 1 )
1903 {
1904 *r = 0;
1905 return( 0 );
1906 }
1907
1908 if( b == 2 )
1909 {
1910 *r = A->p[0] & 1;
1911 return( 0 );
1912 }
1913
1914 /*
1915 * general case
1916 */
Paul Bakker23986e52011-04-24 08:57:21 +00001917 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001918 {
Paul Bakker23986e52011-04-24 08:57:21 +00001919 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001920 y = ( y << biH ) | ( x >> biH );
1921 z = y / b;
1922 y -= z * b;
1923
1924 x <<= biH;
1925 y = ( y << biH ) | ( x >> biH );
1926 z = y / b;
1927 y -= z * b;
1928 }
1929
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001930 /*
1931 * If A is negative, then the current y represents a negative value.
1932 * Flipping it to the positive side.
1933 */
1934 if( A->s < 0 && y != 0 )
1935 y = b - y;
1936
Paul Bakker5121ce52009-01-03 21:22:43 +00001937 *r = y;
1938
1939 return( 0 );
1940}
1941
1942/*
1943 * Fast Montgomery initialization (thanks to Tom St Denis)
1944 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001946{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001948 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
1950 x = m0;
1951 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001952
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001953 for( i = biL; i >= 8; i /= 2 )
1954 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001955
1956 *mm = ~x + 1;
1957}
1958
1959/*
1960 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1961 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001962static 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 +02001963 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001964{
Paul Bakker23986e52011-04-24 08:57:21 +00001965 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001968 if( T->n < N->n + 1 || T->p == NULL )
1969 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1970
Paul Bakker5121ce52009-01-03 21:22:43 +00001971 memset( T->p, 0, T->n * ciL );
1972
1973 d = T->p;
1974 n = N->n;
1975 m = ( B->n < n ) ? B->n : n;
1976
1977 for( i = 0; i < n; i++ )
1978 {
1979 /*
1980 * T = (T + u0*B + u1*N) / 2^biL
1981 */
1982 u0 = A->p[i];
1983 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1984
1985 mpi_mul_hlp( m, B->p, d, u0 );
1986 mpi_mul_hlp( n, N->p, d, u1 );
1987
1988 *d++ = u0; d[n + 1] = 0;
1989 }
1990
Paul Bakker66d5d072014-06-17 16:39:18 +02001991 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001994 mpi_sub_hlp( n, N->p, A->p );
1995 else
1996 /* prevent timing attacks */
1997 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001998
1999 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000}
2001
2002/*
2003 * Montgomery reduction: A = A * R^-1 mod N
2004 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002005static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2006 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00002007{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008 mbedtls_mpi_uint z = 1;
2009 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002010
Paul Bakker8ddb6452013-02-27 14:56:33 +01002011 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002012 U.p = &z;
2013
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002014 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002015}
2016
2017/*
2018 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2019 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002020int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
2021 const mbedtls_mpi *E, const mbedtls_mpi *N,
2022 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00002023{
Paul Bakker23986e52011-04-24 08:57:21 +00002024 int ret;
2025 size_t wbits, wsize, one = 1;
2026 size_t i, j, nblimbs;
2027 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 mbedtls_mpi_uint ei, mm, state;
2029 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002030 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
Hanno Becker73d7d792018-12-11 10:35:51 +00002032 MPI_VALIDATE_RET( X != NULL );
2033 MPI_VALIDATE_RET( A != NULL );
2034 MPI_VALIDATE_RET( E != NULL );
2035 MPI_VALIDATE_RET( N != NULL );
2036
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01002037 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2041 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002042
2043 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002044 * Init temps and window size
2045 */
2046 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
2048 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 memset( W, 0, sizeof( W ) );
2050
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002051 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
2053 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2054 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
2055
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002056#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2058 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002059#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002060
Paul Bakker5121ce52009-01-03 21:22:43 +00002061 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2063 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
2064 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002065
2066 /*
Paul Bakker50546922012-05-19 08:40:49 +00002067 * Compensate for negative A (and correct at the end)
2068 */
2069 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002070 if( neg )
2071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002073 Apos.s = 1;
2074 A = &Apos;
2075 }
2076
2077 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002078 * If 1st call, pre-compute R^2 mod N
2079 */
2080 if( _RR == NULL || _RR->p == NULL )
2081 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2083 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2084 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002085
2086 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002088 }
2089 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002090 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002091
2092 /*
2093 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2094 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2096 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002097 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002098 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002100 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
2102 /*
2103 * X = R^2 * R^-1 mod N = R mod N
2104 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002106 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
2108 if( wsize > 1 )
2109 {
2110 /*
2111 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2112 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002113 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2116 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002117
2118 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002119 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002120
Paul Bakker5121ce52009-01-03 21:22:43 +00002121 /*
2122 * W[i] = W[i - 1] * W[1]
2123 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002124 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002125 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2127 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002129 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002130 }
2131 }
2132
2133 nblimbs = E->n;
2134 bufsize = 0;
2135 nbits = 0;
2136 wbits = 0;
2137 state = 0;
2138
2139 while( 1 )
2140 {
2141 if( bufsize == 0 )
2142 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002143 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002144 break;
2145
Paul Bakker0d7702c2013-10-29 16:18:35 +01002146 nblimbs--;
2147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002149 }
2150
2151 bufsize--;
2152
2153 ei = (E->p[nblimbs] >> bufsize) & 1;
2154
2155 /*
2156 * skip leading 0s
2157 */
2158 if( ei == 0 && state == 0 )
2159 continue;
2160
2161 if( ei == 0 && state == 1 )
2162 {
2163 /*
2164 * out of window, square X
2165 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002166 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002167 continue;
2168 }
2169
2170 /*
2171 * add ei to current window
2172 */
2173 state = 2;
2174
2175 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002176 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
2178 if( nbits == wsize )
2179 {
2180 /*
2181 * X = X^wsize R^-1 mod N
2182 */
2183 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002184 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
2186 /*
2187 * X = X * W[wbits] R^-1 mod N
2188 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002189 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
2191 state--;
2192 nbits = 0;
2193 wbits = 0;
2194 }
2195 }
2196
2197 /*
2198 * process the remaining bits
2199 */
2200 for( i = 0; i < nbits; i++ )
2201 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002202 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002203
2204 wbits <<= 1;
2205
Paul Bakker66d5d072014-06-17 16:39:18 +02002206 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002207 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002208 }
2209
2210 /*
2211 * X = A^E * R * R^-1 mod N = A^E mod N
2212 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002213 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214
Hanno Beckera4af1c42017-04-18 09:07:45 +01002215 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002216 {
2217 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002219 }
2220
Paul Bakker5121ce52009-01-03 21:22:43 +00002221cleanup:
2222
Paul Bakker66d5d072014-06-17 16:39:18 +02002223 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002227
Paul Bakker75a28602014-03-31 12:08:17 +02002228 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002230
2231 return( ret );
2232}
2233
Paul Bakker5121ce52009-01-03 21:22:43 +00002234/*
2235 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2236 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002238{
Paul Bakker23986e52011-04-24 08:57:21 +00002239 int ret;
2240 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002241 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
Hanno Becker73d7d792018-12-11 10:35:51 +00002243 MPI_VALIDATE_RET( G != NULL );
2244 MPI_VALIDATE_RET( A != NULL );
2245 MPI_VALIDATE_RET( B != NULL );
2246
Alexander Ke8ad49f2019-08-16 16:16:07 +03002247 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2250 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 lz = mbedtls_mpi_lsb( &TA );
2253 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002254
Paul Bakker66d5d072014-06-17 16:39:18 +02002255 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002256 lz = lzt;
2257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2259 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002260
Paul Bakker5121ce52009-01-03 21:22:43 +00002261 TA.s = TB.s = 1;
2262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2266 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2271 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002272 }
2273 else
2274 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2276 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002277 }
2278 }
2279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2281 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
2283cleanup:
2284
Alexander Ke8ad49f2019-08-16 16:16:07 +03002285 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002286
2287 return( ret );
2288}
2289
Paul Bakker33dc46b2014-04-30 16:11:39 +02002290/*
2291 * Fill X with size bytes of random.
2292 *
2293 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002294 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002295 * deterministic, eg for tests).
2296 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002298 int (*f_rng)(void *, unsigned char *, size_t),
2299 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002300{
Paul Bakker23986e52011-04-24 08:57:21 +00002301 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002302 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002303 size_t const overhead = ( limbs * ciL ) - size;
2304 unsigned char *Xp;
2305
Hanno Becker8ce11a32018-12-19 16:18:52 +00002306 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002307 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002308
Hanno Beckerda1655a2017-10-18 14:21:44 +01002309 /* Ensure that target MPI has exactly the necessary number of limbs */
2310 if( X->n != limbs )
2311 {
2312 mbedtls_mpi_free( X );
2313 mbedtls_mpi_init( X );
2314 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2315 }
2316 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002317
Hanno Beckerda1655a2017-10-18 14:21:44 +01002318 Xp = (unsigned char*) X->p;
2319 f_rng( p_rng, Xp + overhead, size );
2320
Hanno Becker2be8a552018-10-25 12:40:09 +01002321 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002322
2323cleanup:
2324 return( ret );
2325}
2326
Paul Bakker5121ce52009-01-03 21:22:43 +00002327/*
2328 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2329 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002331{
2332 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002334 MPI_VALIDATE_RET( X != NULL );
2335 MPI_VALIDATE_RET( A != NULL );
2336 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Hanno Becker4bcb4912017-04-18 15:49:39 +01002338 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2342 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2343 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002348 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002350 goto cleanup;
2351 }
2352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2354 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2355 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2356 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2359 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2360 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2361 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002362
2363 do
2364 {
2365 while( ( TU.p[0] & 1 ) == 0 )
2366 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002368
2369 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2370 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2372 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002373 }
2374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2376 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377 }
2378
2379 while( ( TV.p[0] & 1 ) == 0 )
2380 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
2383 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2384 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2386 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002387 }
2388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2390 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002391 }
2392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2396 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2397 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 }
2399 else
2400 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2402 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2403 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404 }
2405 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2409 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2412 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002415
2416cleanup:
2417
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2419 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2420 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002421
2422 return( ret );
2423}
2424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002426
Paul Bakker5121ce52009-01-03 21:22:43 +00002427static const int small_prime[] =
2428{
2429 3, 5, 7, 11, 13, 17, 19, 23,
2430 29, 31, 37, 41, 43, 47, 53, 59,
2431 61, 67, 71, 73, 79, 83, 89, 97,
2432 101, 103, 107, 109, 113, 127, 131, 137,
2433 139, 149, 151, 157, 163, 167, 173, 179,
2434 181, 191, 193, 197, 199, 211, 223, 227,
2435 229, 233, 239, 241, 251, 257, 263, 269,
2436 271, 277, 281, 283, 293, 307, 311, 313,
2437 317, 331, 337, 347, 349, 353, 359, 367,
2438 373, 379, 383, 389, 397, 401, 409, 419,
2439 421, 431, 433, 439, 443, 449, 457, 461,
2440 463, 467, 479, 487, 491, 499, 503, 509,
2441 521, 523, 541, 547, 557, 563, 569, 571,
2442 577, 587, 593, 599, 601, 607, 613, 617,
2443 619, 631, 641, 643, 647, 653, 659, 661,
2444 673, 677, 683, 691, 701, 709, 719, 727,
2445 733, 739, 743, 751, 757, 761, 769, 773,
2446 787, 797, 809, 811, 821, 823, 827, 829,
2447 839, 853, 857, 859, 863, 877, 881, 883,
2448 887, 907, 911, 919, 929, 937, 941, 947,
2449 953, 967, 971, 977, 983, 991, 997, -103
2450};
2451
2452/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002453 * Small divisors test (X must be positive)
2454 *
2455 * Return values:
2456 * 0: no small factor (possible prime, more tests needed)
2457 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002459 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002460 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002462{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002463 int ret = 0;
2464 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002465 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002466
Paul Bakker5121ce52009-01-03 21:22:43 +00002467 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002469
2470 for( i = 0; small_prime[i] > 0; i++ )
2471 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002473 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002476
2477 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002479 }
2480
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002481cleanup:
2482 return( ret );
2483}
2484
2485/*
2486 * Miller-Rabin pseudo-primality test (HAC 4.24)
2487 */
Janos Follathda31fa12018-09-03 14:45:23 +01002488static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002489 int (*f_rng)(void *, unsigned char *, size_t),
2490 void *p_rng )
2491{
Pascal Junodb99183d2015-03-11 16:49:45 +01002492 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002493 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002495
Hanno Becker8ce11a32018-12-19 16:18:52 +00002496 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002497 MPI_VALIDATE_RET( f_rng != NULL );
2498
2499 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2500 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002502
Paul Bakker5121ce52009-01-03 21:22:43 +00002503 /*
2504 * W = |X| - 1
2505 * R = W >> lsb( W )
2506 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2508 s = mbedtls_mpi_lsb( &W );
2509 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2510 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002511
Janos Follathda31fa12018-09-03 14:45:23 +01002512 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002513 {
2514 /*
2515 * pick a random A, 1 < A < |X| - 1
2516 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002517 count = 0;
2518 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002519 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002520
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002521 j = mbedtls_mpi_bitlen( &A );
2522 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002523 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002524 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002525 }
2526
2527 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002528 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2529 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002530 }
2531
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002532 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2533 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002534
2535 /*
2536 * A = A^R mod |X|
2537 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2541 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002542 continue;
2543
2544 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002546 {
2547 /*
2548 * A = A * A mod |X|
2549 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2551 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002553 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002554 break;
2555
2556 j++;
2557 }
2558
2559 /*
2560 * not prime if A != |X| - 1 or A == 1
2561 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2563 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002564 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002566 break;
2567 }
2568 }
2569
2570cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002571 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2572 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002573 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002574
2575 return( ret );
2576}
2577
2578/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002579 * Pseudo-primality test: small factors, then Miller-Rabin
2580 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002581int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2582 int (*f_rng)(void *, unsigned char *, size_t),
2583 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002584{
2585 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002586 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002587 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002588 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002589
2590 XX.s = 1;
2591 XX.n = X->n;
2592 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2595 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2596 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002599 return( 0 );
2600
2601 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2602 {
2603 if( ret == 1 )
2604 return( 0 );
2605
2606 return( ret );
2607 }
2608
Janos Follathda31fa12018-09-03 14:45:23 +01002609 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002610}
2611
Janos Follatha0b67c22018-09-18 14:48:23 +01002612#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002613/*
2614 * Pseudo-primality test, error probability 2^-80
2615 */
2616int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2617 int (*f_rng)(void *, unsigned char *, size_t),
2618 void *p_rng )
2619{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002620 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002621 MPI_VALIDATE_RET( f_rng != NULL );
2622
Janos Follatha0b67c22018-09-18 14:48:23 +01002623 /*
2624 * In the past our key generation aimed for an error rate of at most
2625 * 2^-80. Since this function is deprecated, aim for the same certainty
2626 * here as well.
2627 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002628 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002629}
Janos Follatha0b67c22018-09-18 14:48:23 +01002630#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002631
2632/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002634 *
Janos Follathf301d232018-08-14 13:34:01 +01002635 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2636 * be either 1024 bits or 1536 bits long, and flags must contain
2637 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002638 */
Janos Follath7c025a92018-08-14 11:08:41 +01002639int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002640 int (*f_rng)(void *, unsigned char *, size_t),
2641 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002642{
Jethro Beekman66689272018-02-14 19:24:10 -08002643#ifdef MBEDTLS_HAVE_INT64
2644// ceil(2^63.5)
2645#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2646#else
2647// ceil(2^31.5)
2648#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2649#endif
2650 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002651 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002652 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002653 mbedtls_mpi_uint r;
2654 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Hanno Becker8ce11a32018-12-19 16:18:52 +00002656 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002657 MPI_VALIDATE_RET( f_rng != NULL );
2658
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002659 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2660 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002662 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002663
2664 n = BITS_TO_LIMBS( nbits );
2665
Janos Follathda31fa12018-09-03 14:45:23 +01002666 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2667 {
2668 /*
2669 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2670 */
2671 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2672 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2673 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2674 }
2675 else
2676 {
2677 /*
2678 * 2^-100 error probability, number of rounds computed based on HAC,
2679 * fact 4.48
2680 */
2681 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2682 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2683 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2684 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2685 }
2686
Jethro Beekman66689272018-02-14 19:24:10 -08002687 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002688 {
Jethro Beekman66689272018-02-14 19:24:10 -08002689 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2690 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2691 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2692
2693 k = n * biL;
2694 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2695 X->p[0] |= 1;
2696
Janos Follath7c025a92018-08-14 11:08:41 +01002697 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002698 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002699 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002702 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002703 }
Jethro Beekman66689272018-02-14 19:24:10 -08002704 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002705 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002706 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002707 * An necessary condition for Y and X = 2Y + 1 to be prime
2708 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2709 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002710 */
Jethro Beekman66689272018-02-14 19:24:10 -08002711
2712 X->p[0] |= 2;
2713
2714 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2715 if( r == 0 )
2716 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2717 else if( r == 1 )
2718 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2719
2720 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2721 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2722 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2723
2724 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002725 {
Jethro Beekman66689272018-02-14 19:24:10 -08002726 /*
2727 * First, check small factors for X and Y
2728 * before doing Miller-Rabin on any of them
2729 */
2730 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2731 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002732 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002733 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002734 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002735 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002736 goto cleanup;
2737
2738 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2739 goto cleanup;
2740
2741 /*
2742 * Next candidates. We want to preserve Y = (X-1) / 2 and
2743 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2744 * so up Y by 6 and X by 12.
2745 */
2746 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2747 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002748 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002749 }
2750 }
2751
2752cleanup:
2753
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002755
2756 return( ret );
2757}
2758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002761#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002762
Paul Bakker23986e52011-04-24 08:57:21 +00002763#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002764
2765static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2766{
2767 { 693, 609, 21 },
2768 { 1764, 868, 28 },
2769 { 768454923, 542167814, 1 }
2770};
2771
Paul Bakker5121ce52009-01-03 21:22:43 +00002772/*
2773 * Checkup routine
2774 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002775int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002776{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002777 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002778 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002779
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2781 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002782
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002784 "EFE021C2645FD1DC586E69184AF4A31E" \
2785 "D5F53E93B5F123FA41680867BA110131" \
2786 "944FE7952E2517337780CB0DB80E61AA" \
2787 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2788
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002790 "B2E7EFD37075B9F03FF989C7C5051C20" \
2791 "34D2A323810251127E7BF8625A4F49A5" \
2792 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2793 "5B5C25763222FEFCCFC38B832366C29E" ) );
2794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002796 "0066A198186C18C10B2F5ED9B522752A" \
2797 "9830B69916E535C8F047518A889A43A5" \
2798 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002800 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002802 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002803 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2804 "9E857EA95A03512E2BAE7391688D264A" \
2805 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2806 "8001B72E848A38CAE1C65F78E56ABDEF" \
2807 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2808 "ECF677152EF804370C1A305CAF3B5BF1" \
2809 "30879B56C61DE584A0F53A2447A51E" ) );
2810
2811 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002812 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002814 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002815 {
2816 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002818
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002819 ret = 1;
2820 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002821 }
2822
2823 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002824 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002825
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002826 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002828 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002829 "256567336059E52CAE22925474705F39A94" ) );
2830
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002831 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002832 "6613F26162223DF488E9CD48CC132C7A" \
2833 "0AC93C701B001B092E4E5B9F73BCD27B" \
2834 "9EE50D0657C77F374E903CDFA4C642" ) );
2835
2836 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002837 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002838
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002839 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2840 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002841 {
2842 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002843 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002844
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002845 ret = 1;
2846 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002847 }
2848
2849 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002850 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002852 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002854 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002855 "36E139AEA55215609D2816998ED020BB" \
2856 "BD96C37890F65171D948E9BC7CBAA4D9" \
2857 "325D24D6A3C12710F10A09FA08AB87" ) );
2858
2859 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002860 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002862 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002863 {
2864 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002865 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002866
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002867 ret = 1;
2868 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002869 }
2870
2871 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002872 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002874 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002876 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002877 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2878 "C3DBA76456363A10869622EAC2DD84EC" \
2879 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2880
2881 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002882 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002883
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002884 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002885 {
2886 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002887 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002888
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002889 ret = 1;
2890 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002891 }
2892
2893 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002894 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002895
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002896 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002897 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002898
Paul Bakker66d5d072014-06-17 16:39:18 +02002899 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002900 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002901 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2902 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002903
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002904 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002905
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002906 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002907 {
2908 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002909 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002910
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002911 ret = 1;
2912 goto cleanup;
2913 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002914 }
2915
2916 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002917 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002918
Paul Bakker5121ce52009-01-03 21:22:43 +00002919cleanup:
2920
2921 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002922 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002924 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2925 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002926
2927 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002928 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002929
2930 return( ret );
2931}
2932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002933#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002934
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002935#endif /* MBEDTLS_BIGNUM_C */