blob: 503ec537d8b51625808fcabde98beed81aed7fdf [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/*
530 * Helper to write the digits high-order first
531 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000533{
534 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536
537 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
541 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
544 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000545
546 if( r < 10 )
547 *(*p)++ = (char)( r + 0x30 );
548 else
549 *(*p)++ = (char)( r + 0x37 );
550
551cleanup:
552
553 return( ret );
554}
555
556/*
557 * Export into an ASCII string
558 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100559int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
560 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000561{
Paul Bakker23986e52011-04-24 08:57:21 +0000562 int ret = 0;
563 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000566 MPI_VALIDATE_RET( X != NULL );
567 MPI_VALIDATE_RET( olen != NULL );
568 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
570 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000571 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000572
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200573 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 if( radix >= 4 ) n >>= 1;
575 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000576 /*
577 * Round up the buffer length to an even value to ensure that there is
578 * enough room for hexadecimal values that can be represented in an odd
579 * number of digits.
580 */
581 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100583 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100585 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 }
588
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100589 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
592 if( X->s == -1 )
593 *p++ = '-';
594
595 if( radix == 16 )
596 {
Paul Bakker23986e52011-04-24 08:57:21 +0000597 int c;
598 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Paul Bakker23986e52011-04-24 08:57:21 +0000600 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 {
Paul Bakker23986e52011-04-24 08:57:21 +0000602 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 {
Paul Bakker23986e52011-04-24 08:57:21 +0000604 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
Paul Bakker6c343d72014-07-10 14:36:19 +0200606 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000607 continue;
608
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000609 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000610 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 k = 1;
612 }
613 }
614 }
615 else
616 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000618
619 if( T.s == -1 )
620 T.s = 1;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 }
624
625 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100626 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
628cleanup:
629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 return( ret );
633}
634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000636/*
637 * Read X from an opened file
638 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000640{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000642 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000644 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000645 * Buffer should have space for (short) label and decimal formatted MPI,
646 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000647 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
Hanno Becker73d7d792018-12-11 10:35:51 +0000650 MPI_VALIDATE_RET( X != NULL );
651 MPI_VALIDATE_RET( fin != NULL );
652
653 if( radix < 2 || radix > 16 )
654 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
655
Paul Bakker5121ce52009-01-03 21:22:43 +0000656 memset( s, 0, sizeof( s ) );
657 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
660 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000661 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000663
Hanno Beckerb2034b72017-04-26 11:46:46 +0100664 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
665 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
667 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100668 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 if( mpi_get_digit( &d, radix, *p ) != 0 )
670 break;
671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673}
674
675/*
676 * Write X into an opened file (or stdout if fout == NULL)
677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000679{
Paul Bakker23986e52011-04-24 08:57:21 +0000680 int ret;
681 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000682 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000683 * Buffer should have space for (short) label and decimal formatted MPI,
684 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000685 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000687 MPI_VALIDATE_RET( X != NULL );
688
689 if( radix < 2 || radix > 16 )
690 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100692 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100694 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
696 if( p == NULL ) p = "";
697
698 plen = strlen( p );
699 slen = strlen( s );
700 s[slen++] = '\r';
701 s[slen++] = '\n';
702
703 if( fout != NULL )
704 {
705 if( fwrite( p, 1, plen, fout ) != plen ||
706 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000708 }
709 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
712cleanup:
713
714 return( ret );
715}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000717
Hanno Beckerda1655a2017-10-18 14:21:44 +0100718
719/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
720 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000721
722static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
723{
724 uint8_t i;
725 mbedtls_mpi_uint tmp = 0;
726 /* This works regardless of the endianness. */
727 for( i = 0; i < ciL; i++, x >>= 8 )
728 tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
729 return( tmp );
730}
731
732static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
733{
734#if defined(__BYTE_ORDER__)
735
736/* Nothing to do on bigendian systems. */
737#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
738 return( x );
739#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
740
741#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
742
743/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker5d91c0b2019-01-02 11:24:30 +0000744#if( defined(__GNUC__) && defined(__GNUC_PREREQ) && __GNUC_PREREQ(4,3) )
Hanno Beckerf8720072018-11-08 11:53:49 +0000745#define have_bswap
746#elif defined(__clang__) && \
747 defined(__has_builtin) && \
748 __has_builtin(__builtin_bswap32) && \
749 __has_builtin(__builtin_bswap64)
750#define have_bswap
751#endif
752#if defined(have_bswap)
753 /* The compiler is hopefully able to statically evaluate this! */
754 switch( sizeof(mbedtls_mpi_uint) )
755 {
756 case 4:
757 return( __builtin_bswap32(x) );
758 case 8:
759 return( __builtin_bswap64(x) );
760 }
761#endif
762#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
763#endif /* __BYTE_ORDER__ */
764
765 /* Fall back to C-based reordering if we don't know the byte order
766 * or we couldn't use a compiler-specific builtin. */
767 return( mpi_uint_bigendian_to_host_c( x ) );
768}
769
Hanno Becker2be8a552018-10-25 12:40:09 +0100770static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100771{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100772 mbedtls_mpi_uint *cur_limb_left;
773 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100774 if( limbs == 0 )
775 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100776
777 /*
778 * Traverse limbs and
779 * - adapt byte-order in each limb
780 * - swap the limbs themselves.
781 * For that, simultaneously traverse the limbs from left to right
782 * and from right to left, as long as the left index is not bigger
783 * than the right index (it's not a problem if limbs is odd and the
784 * indices coincide in the last iteration).
785 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100786 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
787 cur_limb_left <= cur_limb_right;
788 cur_limb_left++, cur_limb_right-- )
789 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000790 mbedtls_mpi_uint tmp;
791 /* Note that if cur_limb_left == cur_limb_right,
792 * this code effectively swaps the bytes only once. */
793 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
794 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
795 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100796 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100797}
798
Paul Bakker5121ce52009-01-03 21:22:43 +0000799/*
800 * Import X from unsigned binary data, big endian
801 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000803{
Paul Bakker23986e52011-04-24 08:57:21 +0000804 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100805 size_t const limbs = CHARS_TO_LIMBS( buflen );
806 size_t const overhead = ( limbs * ciL ) - buflen;
807 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000808
Hanno Becker8ce11a32018-12-19 16:18:52 +0000809 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000810 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
811
Hanno Becker073c1992017-10-17 15:17:27 +0100812 /* Ensure that target MPI has exactly the necessary number of limbs */
813 if( X->n != limbs )
814 {
815 mbedtls_mpi_free( X );
816 mbedtls_mpi_init( X );
817 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
818 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000820
Hanno Beckerda1655a2017-10-18 14:21:44 +0100821 Xp = (unsigned char*) X->p;
822 memcpy( Xp + overhead, buf, buflen );
823
Hanno Becker2be8a552018-10-25 12:40:09 +0100824 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825
826cleanup:
827
828 return( ret );
829}
830
831/*
832 * Export X into unsigned binary data, big endian
833 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100834int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
835 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000836{
Hanno Becker73d7d792018-12-11 10:35:51 +0000837 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100838 size_t bytes_to_copy;
839 unsigned char *p;
840 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000841
Hanno Becker73d7d792018-12-11 10:35:51 +0000842 MPI_VALIDATE_RET( X != NULL );
843 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
844
845 stored_bytes = X->n * ciL;
846
Gilles Peskine11cdb052018-11-20 16:47:47 +0100847 if( stored_bytes < buflen )
848 {
849 /* There is enough space in the output buffer. Write initial
850 * null bytes and record the position at which to start
851 * writing the significant bytes. In this case, the execution
852 * trace of this function does not depend on the value of the
853 * number. */
854 bytes_to_copy = stored_bytes;
855 p = buf + buflen - stored_bytes;
856 memset( buf, 0, buflen - stored_bytes );
857 }
858 else
859 {
860 /* The output buffer is smaller than the allocated size of X.
861 * However X may fit if its leading bytes are zero. */
862 bytes_to_copy = buflen;
863 p = buf;
864 for( i = bytes_to_copy; i < stored_bytes; i++ )
865 {
866 if( GET_BYTE( X, i ) != 0 )
867 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
868 }
869 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
Gilles Peskine11cdb052018-11-20 16:47:47 +0100871 for( i = 0; i < bytes_to_copy; i++ )
872 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000873
874 return( 0 );
875}
876
877/*
878 * Left-shift: X <<= count
879 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000881{
Paul Bakker23986e52011-04-24 08:57:21 +0000882 int ret;
883 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200884 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000885 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000886
887 v0 = count / (biL );
888 t1 = count & (biL - 1);
889
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200890 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000891
Paul Bakkerf9688572011-05-05 10:00:45 +0000892 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000894
895 ret = 0;
896
897 /*
898 * shift by count / limb_size
899 */
900 if( v0 > 0 )
901 {
Paul Bakker23986e52011-04-24 08:57:21 +0000902 for( i = X->n; i > v0; i-- )
903 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000904
Paul Bakker23986e52011-04-24 08:57:21 +0000905 for( ; i > 0; i-- )
906 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000907 }
908
909 /*
910 * shift by count % limb_size
911 */
912 if( t1 > 0 )
913 {
914 for( i = v0; i < X->n; i++ )
915 {
916 r1 = X->p[i] >> (biL - t1);
917 X->p[i] <<= t1;
918 X->p[i] |= r0;
919 r0 = r1;
920 }
921 }
922
923cleanup:
924
925 return( ret );
926}
927
928/*
929 * Right-shift: X >>= count
930 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000932{
Paul Bakker23986e52011-04-24 08:57:21 +0000933 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200934 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000935 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000936
937 v0 = count / biL;
938 v1 = count & (biL - 1);
939
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100940 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100942
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 /*
944 * shift by count / limb_size
945 */
946 if( v0 > 0 )
947 {
948 for( i = 0; i < X->n - v0; i++ )
949 X->p[i] = X->p[i + v0];
950
951 for( ; i < X->n; i++ )
952 X->p[i] = 0;
953 }
954
955 /*
956 * shift by count % limb_size
957 */
958 if( v1 > 0 )
959 {
Paul Bakker23986e52011-04-24 08:57:21 +0000960 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000961 {
Paul Bakker23986e52011-04-24 08:57:21 +0000962 r1 = X->p[i - 1] << (biL - v1);
963 X->p[i - 1] >>= v1;
964 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000965 r0 = r1;
966 }
967 }
968
969 return( 0 );
970}
971
972/*
973 * Compare unsigned values
974 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000976{
Paul Bakker23986e52011-04-24 08:57:21 +0000977 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000978 MPI_VALIDATE_RET( X != NULL );
979 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000980
Paul Bakker23986e52011-04-24 08:57:21 +0000981 for( i = X->n; i > 0; i-- )
982 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000983 break;
984
Paul Bakker23986e52011-04-24 08:57:21 +0000985 for( j = Y->n; j > 0; j-- )
986 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000987 break;
988
Paul Bakker23986e52011-04-24 08:57:21 +0000989 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 return( 0 );
991
992 if( i > j ) return( 1 );
993 if( j > i ) return( -1 );
994
Paul Bakker23986e52011-04-24 08:57:21 +0000995 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000996 {
Paul Bakker23986e52011-04-24 08:57:21 +0000997 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
998 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000999 }
1000
1001 return( 0 );
1002}
1003
1004/*
1005 * Compare signed values
1006 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001008{
Paul Bakker23986e52011-04-24 08:57:21 +00001009 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001010 MPI_VALIDATE_RET( X != NULL );
1011 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001012
Paul Bakker23986e52011-04-24 08:57:21 +00001013 for( i = X->n; i > 0; i-- )
1014 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001015 break;
1016
Paul Bakker23986e52011-04-24 08:57:21 +00001017 for( j = Y->n; j > 0; j-- )
1018 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001019 break;
1020
Paul Bakker23986e52011-04-24 08:57:21 +00001021 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 return( 0 );
1023
1024 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001025 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001026
1027 if( X->s > 0 && Y->s < 0 ) return( 1 );
1028 if( Y->s > 0 && X->s < 0 ) return( -1 );
1029
Paul Bakker23986e52011-04-24 08:57:21 +00001030 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 {
Paul Bakker23986e52011-04-24 08:57:21 +00001032 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1033 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034 }
1035
1036 return( 0 );
1037}
1038
1039/*
1040 * Compare signed values
1041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001043{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 mbedtls_mpi Y;
1045 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001046 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047
1048 *p = ( z < 0 ) ? -z : z;
1049 Y.s = ( z < 0 ) ? -1 : 1;
1050 Y.n = 1;
1051 Y.p = p;
1052
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001054}
1055
1056/*
1057 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1058 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001059int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001060{
Paul Bakker23986e52011-04-24 08:57:21 +00001061 int ret;
1062 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001063 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001064 MPI_VALIDATE_RET( X != NULL );
1065 MPI_VALIDATE_RET( A != NULL );
1066 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001067
1068 if( X == B )
1069 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001071 }
1072
1073 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001075
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001076 /*
1077 * X should always be positive as a result of unsigned additions.
1078 */
1079 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001080
Paul Bakker23986e52011-04-24 08:57:21 +00001081 for( j = B->n; j > 0; j-- )
1082 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001083 break;
1084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001086
1087 o = B->p; p = X->p; c = 0;
1088
Janos Follath6c922682015-10-30 17:43:11 +01001089 /*
1090 * tmp is used because it might happen that p == o
1091 */
Paul Bakker23986e52011-04-24 08:57:21 +00001092 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 {
Janos Follath6c922682015-10-30 17:43:11 +01001094 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001096 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001097 }
1098
1099 while( c != 0 )
1100 {
1101 if( i >= X->n )
1102 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001104 p = X->p + i;
1105 }
1106
Paul Bakker2d319fd2012-09-16 21:34:26 +00001107 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001108 }
1109
1110cleanup:
1111
1112 return( ret );
1113}
1114
1115/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001117 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001118static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001119{
Paul Bakker23986e52011-04-24 08:57:21 +00001120 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001122
1123 for( i = c = 0; i < n; i++, s++, d++ )
1124 {
1125 z = ( *d < c ); *d -= c;
1126 c = ( *d < *s ) + z; *d -= *s;
1127 }
1128
1129 while( c != 0 )
1130 {
1131 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001132 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 }
1134}
1135
1136/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001137 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001138 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001139int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001140{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001142 int ret;
1143 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001144 MPI_VALIDATE_RET( X != NULL );
1145 MPI_VALIDATE_RET( A != NULL );
1146 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001148 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1149 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
1153 if( X == B )
1154 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001155 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001156 B = &TB;
1157 }
1158
1159 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161
Paul Bakker1ef7a532009-06-20 10:50:55 +00001162 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001163 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001164 */
1165 X->s = 1;
1166
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 ret = 0;
1168
Paul Bakker23986e52011-04-24 08:57:21 +00001169 for( n = B->n; n > 0; n-- )
1170 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001171 break;
1172
Paul Bakker23986e52011-04-24 08:57:21 +00001173 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
1175cleanup:
1176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001178
1179 return( ret );
1180}
1181
1182/*
1183 * Signed addition: X = A + B
1184 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186{
Hanno Becker73d7d792018-12-11 10:35:51 +00001187 int ret, s;
1188 MPI_VALIDATE_RET( X != NULL );
1189 MPI_VALIDATE_RET( A != NULL );
1190 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001191
Hanno Becker73d7d792018-12-11 10:35:51 +00001192 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 if( A->s * B->s < 0 )
1194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001196 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198 X->s = s;
1199 }
1200 else
1201 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 X->s = -s;
1204 }
1205 }
1206 else
1207 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001209 X->s = s;
1210 }
1211
1212cleanup:
1213
1214 return( ret );
1215}
1216
1217/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001218 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001221{
Hanno Becker73d7d792018-12-11 10:35:51 +00001222 int ret, s;
1223 MPI_VALIDATE_RET( X != NULL );
1224 MPI_VALIDATE_RET( A != NULL );
1225 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001226
Hanno Becker73d7d792018-12-11 10:35:51 +00001227 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 if( A->s * B->s > 0 )
1229 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001233 X->s = s;
1234 }
1235 else
1236 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001237 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 X->s = -s;
1239 }
1240 }
1241 else
1242 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001243 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001244 X->s = s;
1245 }
1246
1247cleanup:
1248
1249 return( ret );
1250}
1251
1252/*
1253 * Signed addition: X = A + b
1254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001256{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 mbedtls_mpi _B;
1258 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001259 MPI_VALIDATE_RET( X != NULL );
1260 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
1262 p[0] = ( b < 0 ) ? -b : b;
1263 _B.s = ( b < 0 ) ? -1 : 1;
1264 _B.n = 1;
1265 _B.p = p;
1266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001268}
1269
1270/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001271 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001272 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001274{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 mbedtls_mpi _B;
1276 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001277 MPI_VALIDATE_RET( X != NULL );
1278 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001279
1280 p[0] = ( b < 0 ) ? -b : b;
1281 _B.s = ( b < 0 ) ? -1 : 1;
1282 _B.n = 1;
1283 _B.p = p;
1284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001286}
1287
1288/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001290 */
1291static
1292#if defined(__APPLE__) && defined(__arm__)
1293/*
1294 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1295 * appears to need this to prevent bad ARM code generation at -O3.
1296 */
1297__attribute__ ((noinline))
1298#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299void 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 +00001300{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001302
1303#if defined(MULADDC_HUIT)
1304 for( ; i >= 8; i -= 8 )
1305 {
1306 MULADDC_INIT
1307 MULADDC_HUIT
1308 MULADDC_STOP
1309 }
1310
1311 for( ; i > 0; i-- )
1312 {
1313 MULADDC_INIT
1314 MULADDC_CORE
1315 MULADDC_STOP
1316 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001317#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001318 for( ; i >= 16; i -= 16 )
1319 {
1320 MULADDC_INIT
1321 MULADDC_CORE MULADDC_CORE
1322 MULADDC_CORE MULADDC_CORE
1323 MULADDC_CORE MULADDC_CORE
1324 MULADDC_CORE MULADDC_CORE
1325
1326 MULADDC_CORE MULADDC_CORE
1327 MULADDC_CORE MULADDC_CORE
1328 MULADDC_CORE MULADDC_CORE
1329 MULADDC_CORE MULADDC_CORE
1330 MULADDC_STOP
1331 }
1332
1333 for( ; i >= 8; i -= 8 )
1334 {
1335 MULADDC_INIT
1336 MULADDC_CORE MULADDC_CORE
1337 MULADDC_CORE MULADDC_CORE
1338
1339 MULADDC_CORE MULADDC_CORE
1340 MULADDC_CORE MULADDC_CORE
1341 MULADDC_STOP
1342 }
1343
1344 for( ; i > 0; i-- )
1345 {
1346 MULADDC_INIT
1347 MULADDC_CORE
1348 MULADDC_STOP
1349 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001350#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001351
1352 t++;
1353
1354 do {
1355 *d += c; c = ( *d < c ); d++;
1356 }
1357 while( c != 0 );
1358}
1359
1360/*
1361 * Baseline multiplication: X = A * B (HAC 14.12)
1362 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001364{
Paul Bakker23986e52011-04-24 08:57:21 +00001365 int ret;
1366 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001368 MPI_VALIDATE_RET( X != NULL );
1369 MPI_VALIDATE_RET( A != NULL );
1370 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1375 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
Paul Bakker23986e52011-04-24 08:57:21 +00001377 for( i = A->n; i > 0; i-- )
1378 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 break;
1380
Paul Bakker23986e52011-04-24 08:57:21 +00001381 for( j = B->n; j > 0; j-- )
1382 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001383 break;
1384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1386 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001387
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001388 for( ; j > 0; j-- )
1389 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001390
1391 X->s = A->s * B->s;
1392
1393cleanup:
1394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
1397 return( ret );
1398}
1399
1400/*
1401 * Baseline multiplication: X = A * b
1402 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001404{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405 mbedtls_mpi _B;
1406 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001407 MPI_VALIDATE_RET( X != NULL );
1408 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409
1410 _B.s = 1;
1411 _B.n = 1;
1412 _B.p = p;
1413 p[0] = b;
1414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001416}
1417
1418/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001419 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1420 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001421 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001422static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1423 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001424{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001425#if defined(MBEDTLS_HAVE_UDBL)
1426 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001427#else
Simon Butcher9803d072016-01-03 00:24:34 +00001428 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1429 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001430 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1431 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001432 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001433#endif
1434
Simon Butcher15b15d12015-11-26 19:35:03 +00001435 /*
1436 * Check for overflow
1437 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001438 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001439 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001440 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001441
Simon Butcherf5ba0452015-12-27 23:01:55 +00001442 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001443 }
1444
1445#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001446 dividend = (mbedtls_t_udbl) u1 << biL;
1447 dividend |= (mbedtls_t_udbl) u0;
1448 quotient = dividend / d;
1449 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1450 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1451
1452 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001453 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001454
1455 return (mbedtls_mpi_uint) quotient;
1456#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001457
1458 /*
1459 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1460 * Vol. 2 - Seminumerical Algorithms, Knuth
1461 */
1462
1463 /*
1464 * Normalize the divisor, d, and dividend, u0, u1
1465 */
1466 s = mbedtls_clz( d );
1467 d = d << s;
1468
1469 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001470 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001471 u0 = u0 << s;
1472
1473 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001474 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001475
1476 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001477 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001478
1479 /*
1480 * Find the first quotient and remainder
1481 */
1482 q1 = u1 / d1;
1483 r0 = u1 - d1 * q1;
1484
1485 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1486 {
1487 q1 -= 1;
1488 r0 += d1;
1489
1490 if ( r0 >= radix ) break;
1491 }
1492
Simon Butcherf5ba0452015-12-27 23:01:55 +00001493 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001494 q0 = rAX / d1;
1495 r0 = rAX - q0 * d1;
1496
1497 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1498 {
1499 q0 -= 1;
1500 r0 += d1;
1501
1502 if ( r0 >= radix ) break;
1503 }
1504
1505 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001506 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001507
1508 quotient = q1 * radix + q0;
1509
1510 return quotient;
1511#endif
1512}
1513
1514/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001516 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001517int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1518 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001519{
Paul Bakker23986e52011-04-24 08:57:21 +00001520 int ret;
1521 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001523 MPI_VALIDATE_RET( A != NULL );
1524 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001526 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1527 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001529 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1530 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001532 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001533 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1535 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001536 return( 0 );
1537 }
1538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1540 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001541 X.s = Y.s = 1;
1542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1544 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1545 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1546 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001548 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001549 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 {
1551 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1553 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001554 }
1555 else k = 0;
1556
1557 n = X.n - 1;
1558 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001559 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001561 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001562 {
1563 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001564 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001565 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001567
1568 for( i = n; i > t ; i-- )
1569 {
1570 if( X.p[i] >= Y.p[t] )
1571 Z.p[i - t - 1] = ~0;
1572 else
1573 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001574 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1575 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 }
1577
1578 Z.p[i - t - 1]++;
1579 do
1580 {
1581 Z.p[i - t - 1]--;
1582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001584 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001589 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1590 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001591 T2.p[2] = X.p[i];
1592 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001595 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1596 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1597 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001600 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1602 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1603 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604 Z.p[i - t - 1]--;
1605 }
1606 }
1607
1608 if( Q != NULL )
1609 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001611 Q->s = A->s * B->s;
1612 }
1613
1614 if( R != NULL )
1615 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001617 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001621 R->s = 1;
1622 }
1623
1624cleanup:
1625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1627 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001628
1629 return( ret );
1630}
1631
1632/*
1633 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001634 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001635int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1636 const mbedtls_mpi *A,
1637 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001638{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 mbedtls_mpi _B;
1640 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001641 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001642
1643 p[0] = ( b < 0 ) ? -b : b;
1644 _B.s = ( b < 0 ) ? -1 : 1;
1645 _B.n = 1;
1646 _B.p = p;
1647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001649}
1650
1651/*
1652 * Modulo: R = A mod B
1653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001655{
1656 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001657 MPI_VALIDATE_RET( R != NULL );
1658 MPI_VALIDATE_RET( A != NULL );
1659 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1662 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1667 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1670 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001671
1672cleanup:
1673
1674 return( ret );
1675}
1676
1677/*
1678 * Modulo: r = A mod b
1679 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001681{
Paul Bakker23986e52011-04-24 08:57:21 +00001682 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001684 MPI_VALIDATE_RET( r != NULL );
1685 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
1687 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
1690 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
1693 /*
1694 * handle trivial cases
1695 */
1696 if( b == 1 )
1697 {
1698 *r = 0;
1699 return( 0 );
1700 }
1701
1702 if( b == 2 )
1703 {
1704 *r = A->p[0] & 1;
1705 return( 0 );
1706 }
1707
1708 /*
1709 * general case
1710 */
Paul Bakker23986e52011-04-24 08:57:21 +00001711 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 {
Paul Bakker23986e52011-04-24 08:57:21 +00001713 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 y = ( y << biH ) | ( x >> biH );
1715 z = y / b;
1716 y -= z * b;
1717
1718 x <<= biH;
1719 y = ( y << biH ) | ( x >> biH );
1720 z = y / b;
1721 y -= z * b;
1722 }
1723
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001724 /*
1725 * If A is negative, then the current y represents a negative value.
1726 * Flipping it to the positive side.
1727 */
1728 if( A->s < 0 && y != 0 )
1729 y = b - y;
1730
Paul Bakker5121ce52009-01-03 21:22:43 +00001731 *r = y;
1732
1733 return( 0 );
1734}
1735
1736/*
1737 * Fast Montgomery initialization (thanks to Tom St Denis)
1738 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001740{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001742 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001743
1744 x = m0;
1745 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001746
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001747 for( i = biL; i >= 8; i /= 2 )
1748 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001749
1750 *mm = ~x + 1;
1751}
1752
1753/*
1754 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1755 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001756static 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 +02001757 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001758{
Paul Bakker23986e52011-04-24 08:57:21 +00001759 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001761
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001762 if( T->n < N->n + 1 || T->p == NULL )
1763 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1764
Paul Bakker5121ce52009-01-03 21:22:43 +00001765 memset( T->p, 0, T->n * ciL );
1766
1767 d = T->p;
1768 n = N->n;
1769 m = ( B->n < n ) ? B->n : n;
1770
1771 for( i = 0; i < n; i++ )
1772 {
1773 /*
1774 * T = (T + u0*B + u1*N) / 2^biL
1775 */
1776 u0 = A->p[i];
1777 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1778
1779 mpi_mul_hlp( m, B->p, d, u0 );
1780 mpi_mul_hlp( n, N->p, d, u1 );
1781
1782 *d++ = u0; d[n + 1] = 0;
1783 }
1784
Paul Bakker66d5d072014-06-17 16:39:18 +02001785 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001788 mpi_sub_hlp( n, N->p, A->p );
1789 else
1790 /* prevent timing attacks */
1791 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001792
1793 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001794}
1795
1796/*
1797 * Montgomery reduction: A = A * R^-1 mod N
1798 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001799static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1800 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001801{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 mbedtls_mpi_uint z = 1;
1803 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Paul Bakker8ddb6452013-02-27 14:56:33 +01001805 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001806 U.p = &z;
1807
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001808 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001809}
1810
1811/*
1812 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1813 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001814int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1815 const mbedtls_mpi *E, const mbedtls_mpi *N,
1816 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001817{
Paul Bakker23986e52011-04-24 08:57:21 +00001818 int ret;
1819 size_t wbits, wsize, one = 1;
1820 size_t i, j, nblimbs;
1821 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 mbedtls_mpi_uint ei, mm, state;
1823 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001824 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
Hanno Becker73d7d792018-12-11 10:35:51 +00001826 MPI_VALIDATE_RET( X != NULL );
1827 MPI_VALIDATE_RET( A != NULL );
1828 MPI_VALIDATE_RET( E != NULL );
1829 MPI_VALIDATE_RET( N != NULL );
1830
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001831 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1835 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001836
1837 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 * Init temps and window size
1839 */
1840 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1842 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 memset( W, 0, sizeof( W ) );
1844
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001845 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
1847 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1848 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1849
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001850 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1851 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001852
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1856 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857
1858 /*
Paul Bakker50546922012-05-19 08:40:49 +00001859 * Compensate for negative A (and correct at the end)
1860 */
1861 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001862 if( neg )
1863 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001865 Apos.s = 1;
1866 A = &Apos;
1867 }
1868
1869 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001870 * If 1st call, pre-compute R^2 mod N
1871 */
1872 if( _RR == NULL || _RR->p == NULL )
1873 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1875 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1876 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001877
1878 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 }
1881 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883
1884 /*
1885 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1886 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1888 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001889 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001891
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001892 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
1894 /*
1895 * X = R^2 * R^-1 mod N = R mod N
1896 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001898 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
1900 if( wsize > 1 )
1901 {
1902 /*
1903 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1904 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001905 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1908 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001909
1910 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001911 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001912
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 /*
1914 * W[i] = W[i - 1] * W[1]
1915 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001916 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001918 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1919 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001921 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001922 }
1923 }
1924
1925 nblimbs = E->n;
1926 bufsize = 0;
1927 nbits = 0;
1928 wbits = 0;
1929 state = 0;
1930
1931 while( 1 )
1932 {
1933 if( bufsize == 0 )
1934 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001935 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001936 break;
1937
Paul Bakker0d7702c2013-10-29 16:18:35 +01001938 nblimbs--;
1939
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001940 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001941 }
1942
1943 bufsize--;
1944
1945 ei = (E->p[nblimbs] >> bufsize) & 1;
1946
1947 /*
1948 * skip leading 0s
1949 */
1950 if( ei == 0 && state == 0 )
1951 continue;
1952
1953 if( ei == 0 && state == 1 )
1954 {
1955 /*
1956 * out of window, square X
1957 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001958 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959 continue;
1960 }
1961
1962 /*
1963 * add ei to current window
1964 */
1965 state = 2;
1966
1967 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001968 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 if( nbits == wsize )
1971 {
1972 /*
1973 * X = X^wsize R^-1 mod N
1974 */
1975 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001976 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001977
1978 /*
1979 * X = X * W[wbits] R^-1 mod N
1980 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001981 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
1983 state--;
1984 nbits = 0;
1985 wbits = 0;
1986 }
1987 }
1988
1989 /*
1990 * process the remaining bits
1991 */
1992 for( i = 0; i < nbits; i++ )
1993 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001994 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
1996 wbits <<= 1;
1997
Paul Bakker66d5d072014-06-17 16:39:18 +02001998 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001999 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000 }
2001
2002 /*
2003 * X = A^E * R * R^-1 mod N = A^E mod N
2004 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002005 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Hanno Beckera4af1c42017-04-18 09:07:45 +01002007 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002008 {
2009 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002011 }
2012
Paul Bakker5121ce52009-01-03 21:22:43 +00002013cleanup:
2014
Paul Bakker66d5d072014-06-17 16:39:18 +02002015 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002019
Paul Bakker75a28602014-03-31 12:08:17 +02002020 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
2023 return( ret );
2024}
2025
Paul Bakker5121ce52009-01-03 21:22:43 +00002026/*
2027 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2028 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002030{
Paul Bakker23986e52011-04-24 08:57:21 +00002031 int ret;
2032 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
Hanno Becker73d7d792018-12-11 10:35:51 +00002035 MPI_VALIDATE_RET( G != NULL );
2036 MPI_VALIDATE_RET( A != NULL );
2037 MPI_VALIDATE_RET( B != NULL );
2038
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002040
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2042 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 lz = mbedtls_mpi_lsb( &TA );
2045 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002046
Paul Bakker66d5d072014-06-17 16:39:18 +02002047 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002048 lz = lzt;
2049
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2051 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002052
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 TA.s = TB.s = 1;
2054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002056 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2058 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002061 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2063 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002064 }
2065 else
2066 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2068 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069 }
2070 }
2071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2073 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002074
2075cleanup:
2076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
2079 return( ret );
2080}
2081
Paul Bakker33dc46b2014-04-30 16:11:39 +02002082/*
2083 * Fill X with size bytes of random.
2084 *
2085 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002086 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002087 * deterministic, eg for tests).
2088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002089int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002090 int (*f_rng)(void *, unsigned char *, size_t),
2091 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002092{
Paul Bakker23986e52011-04-24 08:57:21 +00002093 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002094 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002095 size_t const overhead = ( limbs * ciL ) - size;
2096 unsigned char *Xp;
2097
Hanno Becker8ce11a32018-12-19 16:18:52 +00002098 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002099 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002100
Hanno Beckerda1655a2017-10-18 14:21:44 +01002101 /* Ensure that target MPI has exactly the necessary number of limbs */
2102 if( X->n != limbs )
2103 {
2104 mbedtls_mpi_free( X );
2105 mbedtls_mpi_init( X );
2106 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2107 }
2108 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002109
Hanno Beckerda1655a2017-10-18 14:21:44 +01002110 Xp = (unsigned char*) X->p;
2111 f_rng( p_rng, Xp + overhead, size );
2112
Hanno Becker2be8a552018-10-25 12:40:09 +01002113 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002114
2115cleanup:
2116 return( ret );
2117}
2118
Paul Bakker5121ce52009-01-03 21:22:43 +00002119/*
2120 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2121 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002123{
2124 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002126 MPI_VALIDATE_RET( X != NULL );
2127 MPI_VALIDATE_RET( A != NULL );
2128 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002129
Hanno Becker4bcb4912017-04-18 15:49:39 +01002130 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002131 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2134 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2135 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002136
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002137 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002140 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002142 goto cleanup;
2143 }
2144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2146 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2147 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2148 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2151 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2152 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2153 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002154
2155 do
2156 {
2157 while( ( TU.p[0] & 1 ) == 0 )
2158 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
2161 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2162 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2164 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 }
2166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2168 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002169 }
2170
2171 while( ( TV.p[0] & 1 ) == 0 )
2172 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002174
2175 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2178 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179 }
2180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2182 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183 }
2184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002186 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2188 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2189 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190 }
2191 else
2192 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2194 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2195 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002196 }
2197 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2201 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2204 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207
2208cleanup:
2209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2211 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2212 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002213
2214 return( ret );
2215}
2216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002218
Paul Bakker5121ce52009-01-03 21:22:43 +00002219static const int small_prime[] =
2220{
2221 3, 5, 7, 11, 13, 17, 19, 23,
2222 29, 31, 37, 41, 43, 47, 53, 59,
2223 61, 67, 71, 73, 79, 83, 89, 97,
2224 101, 103, 107, 109, 113, 127, 131, 137,
2225 139, 149, 151, 157, 163, 167, 173, 179,
2226 181, 191, 193, 197, 199, 211, 223, 227,
2227 229, 233, 239, 241, 251, 257, 263, 269,
2228 271, 277, 281, 283, 293, 307, 311, 313,
2229 317, 331, 337, 347, 349, 353, 359, 367,
2230 373, 379, 383, 389, 397, 401, 409, 419,
2231 421, 431, 433, 439, 443, 449, 457, 461,
2232 463, 467, 479, 487, 491, 499, 503, 509,
2233 521, 523, 541, 547, 557, 563, 569, 571,
2234 577, 587, 593, 599, 601, 607, 613, 617,
2235 619, 631, 641, 643, 647, 653, 659, 661,
2236 673, 677, 683, 691, 701, 709, 719, 727,
2237 733, 739, 743, 751, 757, 761, 769, 773,
2238 787, 797, 809, 811, 821, 823, 827, 829,
2239 839, 853, 857, 859, 863, 877, 881, 883,
2240 887, 907, 911, 919, 929, 937, 941, 947,
2241 953, 967, 971, 977, 983, 991, 997, -103
2242};
2243
2244/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002245 * Small divisors test (X must be positive)
2246 *
2247 * Return values:
2248 * 0: no small factor (possible prime, more tests needed)
2249 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002251 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002254{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002255 int ret = 0;
2256 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
Paul Bakker5121ce52009-01-03 21:22:43 +00002259 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002261
2262 for( i = 0; small_prime[i] > 0; i++ )
2263 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002265 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
2269 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002271 }
2272
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002273cleanup:
2274 return( ret );
2275}
2276
2277/*
2278 * Miller-Rabin pseudo-primality test (HAC 4.24)
2279 */
Janos Follathda31fa12018-09-03 14:45:23 +01002280static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002281 int (*f_rng)(void *, unsigned char *, size_t),
2282 void *p_rng )
2283{
Pascal Junodb99183d2015-03-11 16:49:45 +01002284 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002285 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002287
Hanno Becker8ce11a32018-12-19 16:18:52 +00002288 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002289 MPI_VALIDATE_RET( f_rng != NULL );
2290
2291 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2292 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002294
Paul Bakker5121ce52009-01-03 21:22:43 +00002295 /*
2296 * W = |X| - 1
2297 * R = W >> lsb( W )
2298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2300 s = mbedtls_mpi_lsb( &W );
2301 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2302 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002304 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002305
Janos Follathda31fa12018-09-03 14:45:23 +01002306 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002307 {
2308 /*
2309 * pick a random A, 1 < A < |X| - 1
2310 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002311 count = 0;
2312 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002313 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002314
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002315 j = mbedtls_mpi_bitlen( &A );
2316 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002317 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002318 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002319 }
2320
2321 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002322 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002323 }
2324
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002325 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2326 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327
2328 /*
2329 * A = A^R mod |X|
2330 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2334 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002335 continue;
2336
2337 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002339 {
2340 /*
2341 * A = A * A mod |X|
2342 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2344 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002347 break;
2348
2349 j++;
2350 }
2351
2352 /*
2353 * not prime if A != |X| - 1 or A == 1
2354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2356 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002359 break;
2360 }
2361 }
2362
2363cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002364 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2365 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
2368 return( ret );
2369}
2370
2371/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002372 * Pseudo-primality test: small factors, then Miller-Rabin
2373 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002374int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2375 int (*f_rng)(void *, unsigned char *, size_t),
2376 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002377{
2378 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002380 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002381 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002382
2383 XX.s = 1;
2384 XX.n = X->n;
2385 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2388 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2389 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002392 return( 0 );
2393
2394 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2395 {
2396 if( ret == 1 )
2397 return( 0 );
2398
2399 return( ret );
2400 }
2401
Janos Follathda31fa12018-09-03 14:45:23 +01002402 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002403}
2404
Janos Follatha0b67c22018-09-18 14:48:23 +01002405#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002406/*
2407 * Pseudo-primality test, error probability 2^-80
2408 */
2409int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2410 int (*f_rng)(void *, unsigned char *, size_t),
2411 void *p_rng )
2412{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002413 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002414 MPI_VALIDATE_RET( f_rng != NULL );
2415
Janos Follatha0b67c22018-09-18 14:48:23 +01002416 /*
2417 * In the past our key generation aimed for an error rate of at most
2418 * 2^-80. Since this function is deprecated, aim for the same certainty
2419 * here as well.
2420 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002421 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002422}
Janos Follatha0b67c22018-09-18 14:48:23 +01002423#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002424
2425/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002426 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002427 *
Janos Follathf301d232018-08-14 13:34:01 +01002428 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2429 * be either 1024 bits or 1536 bits long, and flags must contain
2430 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002431 */
Janos Follath7c025a92018-08-14 11:08:41 +01002432int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002433 int (*f_rng)(void *, unsigned char *, size_t),
2434 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002435{
Jethro Beekman66689272018-02-14 19:24:10 -08002436#ifdef MBEDTLS_HAVE_INT64
2437// ceil(2^63.5)
2438#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2439#else
2440// ceil(2^31.5)
2441#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2442#endif
2443 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002444 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002445 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446 mbedtls_mpi_uint r;
2447 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002448
Hanno Becker8ce11a32018-12-19 16:18:52 +00002449 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002450 MPI_VALIDATE_RET( f_rng != NULL );
2451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2453 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002456
2457 n = BITS_TO_LIMBS( nbits );
2458
Janos Follathda31fa12018-09-03 14:45:23 +01002459 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2460 {
2461 /*
2462 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2463 */
2464 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2465 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2466 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2467 }
2468 else
2469 {
2470 /*
2471 * 2^-100 error probability, number of rounds computed based on HAC,
2472 * fact 4.48
2473 */
2474 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2475 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2476 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2477 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2478 }
2479
Jethro Beekman66689272018-02-14 19:24:10 -08002480 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002481 {
Jethro Beekman66689272018-02-14 19:24:10 -08002482 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2483 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2484 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2485
2486 k = n * biL;
2487 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2488 X->p[0] |= 1;
2489
Janos Follath7c025a92018-08-14 11:08:41 +01002490 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002491 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002492 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002495 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002496 }
Jethro Beekman66689272018-02-14 19:24:10 -08002497 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002498 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002499 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002500 * An necessary condition for Y and X = 2Y + 1 to be prime
2501 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2502 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002503 */
Jethro Beekman66689272018-02-14 19:24:10 -08002504
2505 X->p[0] |= 2;
2506
2507 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2508 if( r == 0 )
2509 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2510 else if( r == 1 )
2511 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2512
2513 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2514 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2515 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2516
2517 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002518 {
Jethro Beekman66689272018-02-14 19:24:10 -08002519 /*
2520 * First, check small factors for X and Y
2521 * before doing Miller-Rabin on any of them
2522 */
2523 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2524 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002525 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002526 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002527 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002528 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002529 goto cleanup;
2530
2531 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2532 goto cleanup;
2533
2534 /*
2535 * Next candidates. We want to preserve Y = (X-1) / 2 and
2536 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2537 * so up Y by 6 and X by 12.
2538 */
2539 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2540 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002541 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002542 }
2543 }
2544
2545cleanup:
2546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002548
2549 return( ret );
2550}
2551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002555
Paul Bakker23986e52011-04-24 08:57:21 +00002556#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002557
2558static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2559{
2560 { 693, 609, 21 },
2561 { 1764, 868, 28 },
2562 { 768454923, 542167814, 1 }
2563};
2564
Paul Bakker5121ce52009-01-03 21:22:43 +00002565/*
2566 * Checkup routine
2567 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002568int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002569{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002570 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002571 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002573 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2574 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002577 "EFE021C2645FD1DC586E69184AF4A31E" \
2578 "D5F53E93B5F123FA41680867BA110131" \
2579 "944FE7952E2517337780CB0DB80E61AA" \
2580 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002583 "B2E7EFD37075B9F03FF989C7C5051C20" \
2584 "34D2A323810251127E7BF8625A4F49A5" \
2585 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2586 "5B5C25763222FEFCCFC38B832366C29E" ) );
2587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002589 "0066A198186C18C10B2F5ED9B522752A" \
2590 "9830B69916E535C8F047518A889A43A5" \
2591 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2597 "9E857EA95A03512E2BAE7391688D264A" \
2598 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2599 "8001B72E848A38CAE1C65F78E56ABDEF" \
2600 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2601 "ECF677152EF804370C1A305CAF3B5BF1" \
2602 "30879B56C61DE584A0F53A2447A51E" ) );
2603
2604 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002607 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002608 {
2609 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002611
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002612 ret = 1;
2613 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002614 }
2615
2616 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002621 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002622 "256567336059E52CAE22925474705F39A94" ) );
2623
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002625 "6613F26162223DF488E9CD48CC132C7A" \
2626 "0AC93C701B001B092E4E5B9F73BCD27B" \
2627 "9EE50D0657C77F374E903CDFA4C642" ) );
2628
2629 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2633 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002634 {
2635 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002636 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002637
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002638 ret = 1;
2639 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002640 }
2641
2642 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002645 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002648 "36E139AEA55215609D2816998ED020BB" \
2649 "BD96C37890F65171D948E9BC7CBAA4D9" \
2650 "325D24D6A3C12710F10A09FA08AB87" ) );
2651
2652 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002653 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002655 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002656 {
2657 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002658 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002659
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002660 ret = 1;
2661 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002662 }
2663
2664 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002666
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002670 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2671 "C3DBA76456363A10869622EAC2DD84EC" \
2672 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2673
2674 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002675 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002678 {
2679 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002680 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002681
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002682 ret = 1;
2683 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002684 }
2685
2686 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002688
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002689 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002691
Paul Bakker66d5d072014-06-17 16:39:18 +02002692 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002693 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2695 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002698
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002699 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002700 {
2701 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002703
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002704 ret = 1;
2705 goto cleanup;
2706 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002707 }
2708
2709 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002710 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002711
Paul Bakker5121ce52009-01-03 21:22:43 +00002712cleanup:
2713
2714 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002715 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002717 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2718 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002719
2720 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002721 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002722
2723 return( ret );
2724}
2725
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002726#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002728#endif /* MBEDTLS_BIGNUM_C */