blob: bdd6af85c4d0052dbbb1565f9d4d39b7ae142c88 [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 Becker9f6d16a2019-01-02 17:15:06 +0000744#if defined(__GNUC__) && defined(__GNUC_PREREQ)
745#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000746#define have_bswap
747#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000748#endif
749
750#if defined(__clang__) && defined(__has_builtin)
751#if __has_builtin(__builtin_bswap32) && \
752 __has_builtin(__builtin_bswap64)
753#define have_bswap
754#endif
755#endif
756
Hanno Beckerf8720072018-11-08 11:53:49 +0000757#if defined(have_bswap)
758 /* The compiler is hopefully able to statically evaluate this! */
759 switch( sizeof(mbedtls_mpi_uint) )
760 {
761 case 4:
762 return( __builtin_bswap32(x) );
763 case 8:
764 return( __builtin_bswap64(x) );
765 }
766#endif
767#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
768#endif /* __BYTE_ORDER__ */
769
770 /* Fall back to C-based reordering if we don't know the byte order
771 * or we couldn't use a compiler-specific builtin. */
772 return( mpi_uint_bigendian_to_host_c( x ) );
773}
774
Hanno Becker2be8a552018-10-25 12:40:09 +0100775static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100776{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100777 mbedtls_mpi_uint *cur_limb_left;
778 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100779 if( limbs == 0 )
780 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100781
782 /*
783 * Traverse limbs and
784 * - adapt byte-order in each limb
785 * - swap the limbs themselves.
786 * For that, simultaneously traverse the limbs from left to right
787 * and from right to left, as long as the left index is not bigger
788 * than the right index (it's not a problem if limbs is odd and the
789 * indices coincide in the last iteration).
790 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100791 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
792 cur_limb_left <= cur_limb_right;
793 cur_limb_left++, cur_limb_right-- )
794 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000795 mbedtls_mpi_uint tmp;
796 /* Note that if cur_limb_left == cur_limb_right,
797 * this code effectively swaps the bytes only once. */
798 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
799 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
800 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100801 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100802}
803
Paul Bakker5121ce52009-01-03 21:22:43 +0000804/*
805 * Import X from unsigned binary data, big endian
806 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000808{
Paul Bakker23986e52011-04-24 08:57:21 +0000809 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100810 size_t const limbs = CHARS_TO_LIMBS( buflen );
811 size_t const overhead = ( limbs * ciL ) - buflen;
812 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000813
Hanno Becker8ce11a32018-12-19 16:18:52 +0000814 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000815 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
816
Hanno Becker073c1992017-10-17 15:17:27 +0100817 /* Ensure that target MPI has exactly the necessary number of limbs */
818 if( X->n != limbs )
819 {
820 mbedtls_mpi_free( X );
821 mbedtls_mpi_init( X );
822 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
823 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200824 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825
Hanno Beckerda1655a2017-10-18 14:21:44 +0100826 Xp = (unsigned char*) X->p;
827 memcpy( Xp + overhead, buf, buflen );
828
Hanno Becker2be8a552018-10-25 12:40:09 +0100829 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker5121ce52009-01-03 21:22:43 +0000830
831cleanup:
832
833 return( ret );
834}
835
836/*
837 * Export X into unsigned binary data, big endian
838 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100839int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
840 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000841{
Hanno Becker73d7d792018-12-11 10:35:51 +0000842 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100843 size_t bytes_to_copy;
844 unsigned char *p;
845 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000846
Hanno Becker73d7d792018-12-11 10:35:51 +0000847 MPI_VALIDATE_RET( X != NULL );
848 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
849
850 stored_bytes = X->n * ciL;
851
Gilles Peskine11cdb052018-11-20 16:47:47 +0100852 if( stored_bytes < buflen )
853 {
854 /* There is enough space in the output buffer. Write initial
855 * null bytes and record the position at which to start
856 * writing the significant bytes. In this case, the execution
857 * trace of this function does not depend on the value of the
858 * number. */
859 bytes_to_copy = stored_bytes;
860 p = buf + buflen - stored_bytes;
861 memset( buf, 0, buflen - stored_bytes );
862 }
863 else
864 {
865 /* The output buffer is smaller than the allocated size of X.
866 * However X may fit if its leading bytes are zero. */
867 bytes_to_copy = buflen;
868 p = buf;
869 for( i = bytes_to_copy; i < stored_bytes; i++ )
870 {
871 if( GET_BYTE( X, i ) != 0 )
872 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
873 }
874 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000875
Gilles Peskine11cdb052018-11-20 16:47:47 +0100876 for( i = 0; i < bytes_to_copy; i++ )
877 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000878
879 return( 0 );
880}
881
882/*
883 * Left-shift: X <<= count
884 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000886{
Paul Bakker23986e52011-04-24 08:57:21 +0000887 int ret;
888 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200889 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000890 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000891
892 v0 = count / (biL );
893 t1 = count & (biL - 1);
894
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200895 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000896
Paul Bakkerf9688572011-05-05 10:00:45 +0000897 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000899
900 ret = 0;
901
902 /*
903 * shift by count / limb_size
904 */
905 if( v0 > 0 )
906 {
Paul Bakker23986e52011-04-24 08:57:21 +0000907 for( i = X->n; i > v0; i-- )
908 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
Paul Bakker23986e52011-04-24 08:57:21 +0000910 for( ; i > 0; i-- )
911 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000912 }
913
914 /*
915 * shift by count % limb_size
916 */
917 if( t1 > 0 )
918 {
919 for( i = v0; i < X->n; i++ )
920 {
921 r1 = X->p[i] >> (biL - t1);
922 X->p[i] <<= t1;
923 X->p[i] |= r0;
924 r0 = r1;
925 }
926 }
927
928cleanup:
929
930 return( ret );
931}
932
933/*
934 * Right-shift: X >>= count
935 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000937{
Paul Bakker23986e52011-04-24 08:57:21 +0000938 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000940 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000941
942 v0 = count / biL;
943 v1 = count & (biL - 1);
944
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100945 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100947
Paul Bakker5121ce52009-01-03 21:22:43 +0000948 /*
949 * shift by count / limb_size
950 */
951 if( v0 > 0 )
952 {
953 for( i = 0; i < X->n - v0; i++ )
954 X->p[i] = X->p[i + v0];
955
956 for( ; i < X->n; i++ )
957 X->p[i] = 0;
958 }
959
960 /*
961 * shift by count % limb_size
962 */
963 if( v1 > 0 )
964 {
Paul Bakker23986e52011-04-24 08:57:21 +0000965 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000966 {
Paul Bakker23986e52011-04-24 08:57:21 +0000967 r1 = X->p[i - 1] << (biL - v1);
968 X->p[i - 1] >>= v1;
969 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 r0 = r1;
971 }
972 }
973
974 return( 0 );
975}
976
977/*
978 * Compare unsigned values
979 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200980int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000981{
Paul Bakker23986e52011-04-24 08:57:21 +0000982 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000983 MPI_VALIDATE_RET( X != NULL );
984 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000985
Paul Bakker23986e52011-04-24 08:57:21 +0000986 for( i = X->n; i > 0; i-- )
987 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000988 break;
989
Paul Bakker23986e52011-04-24 08:57:21 +0000990 for( j = Y->n; j > 0; j-- )
991 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000992 break;
993
Paul Bakker23986e52011-04-24 08:57:21 +0000994 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000995 return( 0 );
996
997 if( i > j ) return( 1 );
998 if( j > i ) return( -1 );
999
Paul Bakker23986e52011-04-24 08:57:21 +00001000 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 {
Paul Bakker23986e52011-04-24 08:57:21 +00001002 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1003 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001004 }
1005
1006 return( 0 );
1007}
1008
1009/*
1010 * Compare signed values
1011 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001012int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001013{
Paul Bakker23986e52011-04-24 08:57:21 +00001014 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001015 MPI_VALIDATE_RET( X != NULL );
1016 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001017
Paul Bakker23986e52011-04-24 08:57:21 +00001018 for( i = X->n; i > 0; i-- )
1019 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001020 break;
1021
Paul Bakker23986e52011-04-24 08:57:21 +00001022 for( j = Y->n; j > 0; j-- )
1023 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001024 break;
1025
Paul Bakker23986e52011-04-24 08:57:21 +00001026 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 return( 0 );
1028
1029 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001030 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001031
1032 if( X->s > 0 && Y->s < 0 ) return( 1 );
1033 if( Y->s > 0 && X->s < 0 ) return( -1 );
1034
Paul Bakker23986e52011-04-24 08:57:21 +00001035 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001036 {
Paul Bakker23986e52011-04-24 08:57:21 +00001037 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1038 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 }
1040
1041 return( 0 );
1042}
1043
1044/*
1045 * Compare signed values
1046 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001048{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 mbedtls_mpi Y;
1050 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001051 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001052
1053 *p = ( z < 0 ) ? -z : z;
1054 Y.s = ( z < 0 ) ? -1 : 1;
1055 Y.n = 1;
1056 Y.p = p;
1057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001058 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001059}
1060
1061/*
1062 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1063 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001065{
Paul Bakker23986e52011-04-24 08:57:21 +00001066 int ret;
1067 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001068 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001069 MPI_VALIDATE_RET( X != NULL );
1070 MPI_VALIDATE_RET( A != NULL );
1071 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001072
1073 if( X == B )
1074 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001076 }
1077
1078 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001080
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001081 /*
1082 * X should always be positive as a result of unsigned additions.
1083 */
1084 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001085
Paul Bakker23986e52011-04-24 08:57:21 +00001086 for( j = B->n; j > 0; j-- )
1087 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 break;
1089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001091
1092 o = B->p; p = X->p; c = 0;
1093
Janos Follath6c922682015-10-30 17:43:11 +01001094 /*
1095 * tmp is used because it might happen that p == o
1096 */
Paul Bakker23986e52011-04-24 08:57:21 +00001097 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 {
Janos Follath6c922682015-10-30 17:43:11 +01001099 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001100 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001101 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001102 }
1103
1104 while( c != 0 )
1105 {
1106 if( i >= X->n )
1107 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001108 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001109 p = X->p + i;
1110 }
1111
Paul Bakker2d319fd2012-09-16 21:34:26 +00001112 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001113 }
1114
1115cleanup:
1116
1117 return( ret );
1118}
1119
1120/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001122 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001124{
Paul Bakker23986e52011-04-24 08:57:21 +00001125 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001126 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001127
1128 for( i = c = 0; i < n; i++, s++, d++ )
1129 {
1130 z = ( *d < c ); *d -= c;
1131 c = ( *d < *s ) + z; *d -= *s;
1132 }
1133
1134 while( c != 0 )
1135 {
1136 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001137 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001138 }
1139}
1140
1141/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001142 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001144int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001146 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001147 int ret;
1148 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001149 MPI_VALIDATE_RET( X != NULL );
1150 MPI_VALIDATE_RET( A != NULL );
1151 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001153 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1154 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001156 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001157
1158 if( X == B )
1159 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 B = &TB;
1162 }
1163
1164 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001165 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
Paul Bakker1ef7a532009-06-20 10:50:55 +00001167 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001168 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001169 */
1170 X->s = 1;
1171
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 ret = 0;
1173
Paul Bakker23986e52011-04-24 08:57:21 +00001174 for( n = B->n; n > 0; n-- )
1175 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001176 break;
1177
Paul Bakker23986e52011-04-24 08:57:21 +00001178 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001179
1180cleanup:
1181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
1184 return( ret );
1185}
1186
1187/*
1188 * Signed addition: X = A + B
1189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001191{
Hanno Becker73d7d792018-12-11 10:35:51 +00001192 int ret, s;
1193 MPI_VALIDATE_RET( X != NULL );
1194 MPI_VALIDATE_RET( A != NULL );
1195 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
Hanno Becker73d7d792018-12-11 10:35:51 +00001197 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001198 if( A->s * B->s < 0 )
1199 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001200 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001201 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 X->s = s;
1204 }
1205 else
1206 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001208 X->s = -s;
1209 }
1210 }
1211 else
1212 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001214 X->s = s;
1215 }
1216
1217cleanup:
1218
1219 return( ret );
1220}
1221
1222/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001223 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001224 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001225int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001226{
Hanno Becker73d7d792018-12-11 10:35:51 +00001227 int ret, s;
1228 MPI_VALIDATE_RET( X != NULL );
1229 MPI_VALIDATE_RET( A != NULL );
1230 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231
Hanno Becker73d7d792018-12-11 10:35:51 +00001232 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001233 if( A->s * B->s > 0 )
1234 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001236 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001237 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 X->s = s;
1239 }
1240 else
1241 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001243 X->s = -s;
1244 }
1245 }
1246 else
1247 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001249 X->s = s;
1250 }
1251
1252cleanup:
1253
1254 return( ret );
1255}
1256
1257/*
1258 * Signed addition: X = A + b
1259 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001261{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 mbedtls_mpi _B;
1263 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001264 MPI_VALIDATE_RET( X != NULL );
1265 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
1267 p[0] = ( b < 0 ) ? -b : b;
1268 _B.s = ( b < 0 ) ? -1 : 1;
1269 _B.n = 1;
1270 _B.p = p;
1271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001272 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001273}
1274
1275/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001276 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001279{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 mbedtls_mpi _B;
1281 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001282 MPI_VALIDATE_RET( X != NULL );
1283 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001284
1285 p[0] = ( b < 0 ) ? -b : b;
1286 _B.s = ( b < 0 ) ? -1 : 1;
1287 _B.n = 1;
1288 _B.p = p;
1289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001291}
1292
1293/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001295 */
1296static
1297#if defined(__APPLE__) && defined(__arm__)
1298/*
1299 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1300 * appears to need this to prevent bad ARM code generation at -O3.
1301 */
1302__attribute__ ((noinline))
1303#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001304void 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 +00001305{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001307
1308#if defined(MULADDC_HUIT)
1309 for( ; i >= 8; i -= 8 )
1310 {
1311 MULADDC_INIT
1312 MULADDC_HUIT
1313 MULADDC_STOP
1314 }
1315
1316 for( ; i > 0; i-- )
1317 {
1318 MULADDC_INIT
1319 MULADDC_CORE
1320 MULADDC_STOP
1321 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001322#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001323 for( ; i >= 16; i -= 16 )
1324 {
1325 MULADDC_INIT
1326 MULADDC_CORE MULADDC_CORE
1327 MULADDC_CORE MULADDC_CORE
1328 MULADDC_CORE MULADDC_CORE
1329 MULADDC_CORE MULADDC_CORE
1330
1331 MULADDC_CORE MULADDC_CORE
1332 MULADDC_CORE MULADDC_CORE
1333 MULADDC_CORE MULADDC_CORE
1334 MULADDC_CORE MULADDC_CORE
1335 MULADDC_STOP
1336 }
1337
1338 for( ; i >= 8; i -= 8 )
1339 {
1340 MULADDC_INIT
1341 MULADDC_CORE MULADDC_CORE
1342 MULADDC_CORE MULADDC_CORE
1343
1344 MULADDC_CORE MULADDC_CORE
1345 MULADDC_CORE MULADDC_CORE
1346 MULADDC_STOP
1347 }
1348
1349 for( ; i > 0; i-- )
1350 {
1351 MULADDC_INIT
1352 MULADDC_CORE
1353 MULADDC_STOP
1354 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001355#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001356
1357 t++;
1358
1359 do {
1360 *d += c; c = ( *d < c ); d++;
1361 }
1362 while( c != 0 );
1363}
1364
1365/*
1366 * Baseline multiplication: X = A * B (HAC 14.12)
1367 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001369{
Paul Bakker23986e52011-04-24 08:57:21 +00001370 int ret;
1371 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001373 MPI_VALIDATE_RET( X != NULL );
1374 MPI_VALIDATE_RET( A != NULL );
1375 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1380 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001381
Paul Bakker23986e52011-04-24 08:57:21 +00001382 for( i = A->n; i > 0; i-- )
1383 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 break;
1385
Paul Bakker23986e52011-04-24 08:57:21 +00001386 for( j = B->n; j > 0; j-- )
1387 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001388 break;
1389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1391 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001392
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001393 for( ; j > 0; j-- )
1394 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
1396 X->s = A->s * B->s;
1397
1398cleanup:
1399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001401
1402 return( ret );
1403}
1404
1405/*
1406 * Baseline multiplication: X = A * b
1407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001409{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410 mbedtls_mpi _B;
1411 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001412 MPI_VALIDATE_RET( X != NULL );
1413 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001414
1415 _B.s = 1;
1416 _B.n = 1;
1417 _B.p = p;
1418 p[0] = b;
1419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001421}
1422
1423/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001424 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1425 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001426 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001427static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1428 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001429{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001430#if defined(MBEDTLS_HAVE_UDBL)
1431 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001432#else
Simon Butcher9803d072016-01-03 00:24:34 +00001433 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1434 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001435 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1436 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001437 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001438#endif
1439
Simon Butcher15b15d12015-11-26 19:35:03 +00001440 /*
1441 * Check for overflow
1442 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001443 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001444 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001445 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001446
Simon Butcherf5ba0452015-12-27 23:01:55 +00001447 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001448 }
1449
1450#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001451 dividend = (mbedtls_t_udbl) u1 << biL;
1452 dividend |= (mbedtls_t_udbl) u0;
1453 quotient = dividend / d;
1454 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1455 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1456
1457 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001458 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001459
1460 return (mbedtls_mpi_uint) quotient;
1461#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001462
1463 /*
1464 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1465 * Vol. 2 - Seminumerical Algorithms, Knuth
1466 */
1467
1468 /*
1469 * Normalize the divisor, d, and dividend, u0, u1
1470 */
1471 s = mbedtls_clz( d );
1472 d = d << s;
1473
1474 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001475 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001476 u0 = u0 << s;
1477
1478 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001479 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001480
1481 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001482 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001483
1484 /*
1485 * Find the first quotient and remainder
1486 */
1487 q1 = u1 / d1;
1488 r0 = u1 - d1 * q1;
1489
1490 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1491 {
1492 q1 -= 1;
1493 r0 += d1;
1494
1495 if ( r0 >= radix ) break;
1496 }
1497
Simon Butcherf5ba0452015-12-27 23:01:55 +00001498 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001499 q0 = rAX / d1;
1500 r0 = rAX - q0 * d1;
1501
1502 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1503 {
1504 q0 -= 1;
1505 r0 += d1;
1506
1507 if ( r0 >= radix ) break;
1508 }
1509
1510 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001511 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001512
1513 quotient = q1 * radix + q0;
1514
1515 return quotient;
1516#endif
1517}
1518
1519/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001522int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1523 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001524{
Paul Bakker23986e52011-04-24 08:57:21 +00001525 int ret;
1526 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001527 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001528 MPI_VALIDATE_RET( A != NULL );
1529 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1532 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1535 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001538 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1540 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001541 return( 0 );
1542 }
1543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1545 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001546 X.s = Y.s = 1;
1547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1549 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1550 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1551 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001552
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001553 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001554 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001555 {
1556 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001557 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1558 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001559 }
1560 else k = 0;
1561
1562 n = X.n - 1;
1563 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001564 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001567 {
1568 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001570 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001572
1573 for( i = n; i > t ; i-- )
1574 {
1575 if( X.p[i] >= Y.p[t] )
1576 Z.p[i - t - 1] = ~0;
1577 else
1578 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001579 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1580 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001581 }
1582
1583 Z.p[i - t - 1]++;
1584 do
1585 {
1586 Z.p[i - t - 1]--;
1587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001589 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001590 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001594 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1595 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001596 T2.p[2] = X.p[i];
1597 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001600 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1601 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1602 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001604 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001605 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1607 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1608 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001609 Z.p[i - t - 1]--;
1610 }
1611 }
1612
1613 if( Q != NULL )
1614 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001616 Q->s = A->s * B->s;
1617 }
1618
1619 if( R != NULL )
1620 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001622 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001625 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001626 R->s = 1;
1627 }
1628
1629cleanup:
1630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1632 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633
1634 return( ret );
1635}
1636
1637/*
1638 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001639 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001640int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1641 const mbedtls_mpi *A,
1642 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001643{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 mbedtls_mpi _B;
1645 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001646 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001647
1648 p[0] = ( b < 0 ) ? -b : b;
1649 _B.s = ( b < 0 ) ? -1 : 1;
1650 _B.n = 1;
1651 _B.p = p;
1652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654}
1655
1656/*
1657 * Modulo: R = A mod B
1658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001660{
1661 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001662 MPI_VALIDATE_RET( R != NULL );
1663 MPI_VALIDATE_RET( A != NULL );
1664 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1667 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001676
1677cleanup:
1678
1679 return( ret );
1680}
1681
1682/*
1683 * Modulo: r = A mod b
1684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001686{
Paul Bakker23986e52011-04-24 08:57:21 +00001687 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001689 MPI_VALIDATE_RET( r != NULL );
1690 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001691
1692 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
1695 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
1698 /*
1699 * handle trivial cases
1700 */
1701 if( b == 1 )
1702 {
1703 *r = 0;
1704 return( 0 );
1705 }
1706
1707 if( b == 2 )
1708 {
1709 *r = A->p[0] & 1;
1710 return( 0 );
1711 }
1712
1713 /*
1714 * general case
1715 */
Paul Bakker23986e52011-04-24 08:57:21 +00001716 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001717 {
Paul Bakker23986e52011-04-24 08:57:21 +00001718 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001719 y = ( y << biH ) | ( x >> biH );
1720 z = y / b;
1721 y -= z * b;
1722
1723 x <<= biH;
1724 y = ( y << biH ) | ( x >> biH );
1725 z = y / b;
1726 y -= z * b;
1727 }
1728
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001729 /*
1730 * If A is negative, then the current y represents a negative value.
1731 * Flipping it to the positive side.
1732 */
1733 if( A->s < 0 && y != 0 )
1734 y = b - y;
1735
Paul Bakker5121ce52009-01-03 21:22:43 +00001736 *r = y;
1737
1738 return( 0 );
1739}
1740
1741/*
1742 * Fast Montgomery initialization (thanks to Tom St Denis)
1743 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001744static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001745{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001746 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001747 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
1749 x = m0;
1750 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001751
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001752 for( i = biL; i >= 8; i /= 2 )
1753 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001754
1755 *mm = ~x + 1;
1756}
1757
1758/*
1759 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1760 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001761static 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 +02001762 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001763{
Paul Bakker23986e52011-04-24 08:57:21 +00001764 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001766
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001767 if( T->n < N->n + 1 || T->p == NULL )
1768 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1769
Paul Bakker5121ce52009-01-03 21:22:43 +00001770 memset( T->p, 0, T->n * ciL );
1771
1772 d = T->p;
1773 n = N->n;
1774 m = ( B->n < n ) ? B->n : n;
1775
1776 for( i = 0; i < n; i++ )
1777 {
1778 /*
1779 * T = (T + u0*B + u1*N) / 2^biL
1780 */
1781 u0 = A->p[i];
1782 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1783
1784 mpi_mul_hlp( m, B->p, d, u0 );
1785 mpi_mul_hlp( n, N->p, d, u1 );
1786
1787 *d++ = u0; d[n + 1] = 0;
1788 }
1789
Paul Bakker66d5d072014-06-17 16:39:18 +02001790 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001793 mpi_sub_hlp( n, N->p, A->p );
1794 else
1795 /* prevent timing attacks */
1796 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001797
1798 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001799}
1800
1801/*
1802 * Montgomery reduction: A = A * R^-1 mod N
1803 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001804static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1805 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001806{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 mbedtls_mpi_uint z = 1;
1808 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001809
Paul Bakker8ddb6452013-02-27 14:56:33 +01001810 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001811 U.p = &z;
1812
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001813 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001814}
1815
1816/*
1817 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1818 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001819int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1820 const mbedtls_mpi *E, const mbedtls_mpi *N,
1821 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001822{
Paul Bakker23986e52011-04-24 08:57:21 +00001823 int ret;
1824 size_t wbits, wsize, one = 1;
1825 size_t i, j, nblimbs;
1826 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 mbedtls_mpi_uint ei, mm, state;
1828 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001829 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001830
Hanno Becker73d7d792018-12-11 10:35:51 +00001831 MPI_VALIDATE_RET( X != NULL );
1832 MPI_VALIDATE_RET( A != NULL );
1833 MPI_VALIDATE_RET( E != NULL );
1834 MPI_VALIDATE_RET( N != NULL );
1835
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001836 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001838
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1840 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001841
1842 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 * Init temps and window size
1844 */
1845 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1847 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848 memset( W, 0, sizeof( W ) );
1849
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001850 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
1852 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1853 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1854
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001855 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1856 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001857
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1860 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001862
1863 /*
Paul Bakker50546922012-05-19 08:40:49 +00001864 * Compensate for negative A (and correct at the end)
1865 */
1866 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001867 if( neg )
1868 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001870 Apos.s = 1;
1871 A = &Apos;
1872 }
1873
1874 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001875 * If 1st call, pre-compute R^2 mod N
1876 */
1877 if( _RR == NULL || _RR->p == NULL )
1878 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1881 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
1883 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 }
1886 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
1889 /*
1890 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1893 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001894 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001897 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001898
1899 /*
1900 * X = R^2 * R^-1 mod N = R mod N
1901 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001903 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904
1905 if( wsize > 1 )
1906 {
1907 /*
1908 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1909 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001910 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1913 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
1915 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001916 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001917
Paul Bakker5121ce52009-01-03 21:22:43 +00001918 /*
1919 * W[i] = W[i - 1] * W[1]
1920 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001921 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001922 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1924 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001925
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001926 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001927 }
1928 }
1929
1930 nblimbs = E->n;
1931 bufsize = 0;
1932 nbits = 0;
1933 wbits = 0;
1934 state = 0;
1935
1936 while( 1 )
1937 {
1938 if( bufsize == 0 )
1939 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001940 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001941 break;
1942
Paul Bakker0d7702c2013-10-29 16:18:35 +01001943 nblimbs--;
1944
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 }
1947
1948 bufsize--;
1949
1950 ei = (E->p[nblimbs] >> bufsize) & 1;
1951
1952 /*
1953 * skip leading 0s
1954 */
1955 if( ei == 0 && state == 0 )
1956 continue;
1957
1958 if( ei == 0 && state == 1 )
1959 {
1960 /*
1961 * out of window, square X
1962 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001963 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001964 continue;
1965 }
1966
1967 /*
1968 * add ei to current window
1969 */
1970 state = 2;
1971
1972 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001973 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974
1975 if( nbits == wsize )
1976 {
1977 /*
1978 * X = X^wsize R^-1 mod N
1979 */
1980 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001981 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
1983 /*
1984 * X = X * W[wbits] R^-1 mod N
1985 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001986 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
1988 state--;
1989 nbits = 0;
1990 wbits = 0;
1991 }
1992 }
1993
1994 /*
1995 * process the remaining bits
1996 */
1997 for( i = 0; i < nbits; i++ )
1998 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001999 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
2001 wbits <<= 1;
2002
Paul Bakker66d5d072014-06-17 16:39:18 +02002003 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002004 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002005 }
2006
2007 /*
2008 * X = A^E * R * R^-1 mod N = A^E mod N
2009 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002010 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002011
Hanno Beckera4af1c42017-04-18 09:07:45 +01002012 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002013 {
2014 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002016 }
2017
Paul Bakker5121ce52009-01-03 21:22:43 +00002018cleanup:
2019
Paul Bakker66d5d072014-06-17 16:39:18 +02002020 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002024
Paul Bakker75a28602014-03-31 12:08:17 +02002025 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
2028 return( ret );
2029}
2030
Paul Bakker5121ce52009-01-03 21:22:43 +00002031/*
2032 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002035{
Paul Bakker23986e52011-04-24 08:57:21 +00002036 int ret;
2037 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
Hanno Becker73d7d792018-12-11 10:35:51 +00002040 MPI_VALIDATE_RET( G != NULL );
2041 MPI_VALIDATE_RET( A != NULL );
2042 MPI_VALIDATE_RET( B != NULL );
2043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2047 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 lz = mbedtls_mpi_lsb( &TA );
2050 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002051
Paul Bakker66d5d072014-06-17 16:39:18 +02002052 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002053 lz = lzt;
2054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2056 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002057
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 TA.s = TB.s = 1;
2059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002061 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2063 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002066 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2068 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069 }
2070 else
2071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2073 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002074 }
2075 }
2076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2078 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079
2080cleanup:
2081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002083
2084 return( ret );
2085}
2086
Paul Bakker33dc46b2014-04-30 16:11:39 +02002087/*
2088 * Fill X with size bytes of random.
2089 *
2090 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002091 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002092 * deterministic, eg for tests).
2093 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002095 int (*f_rng)(void *, unsigned char *, size_t),
2096 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002097{
Paul Bakker23986e52011-04-24 08:57:21 +00002098 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002099 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002100 size_t const overhead = ( limbs * ciL ) - size;
2101 unsigned char *Xp;
2102
Hanno Becker8ce11a32018-12-19 16:18:52 +00002103 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002104 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002105
Hanno Beckerda1655a2017-10-18 14:21:44 +01002106 /* Ensure that target MPI has exactly the necessary number of limbs */
2107 if( X->n != limbs )
2108 {
2109 mbedtls_mpi_free( X );
2110 mbedtls_mpi_init( X );
2111 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2112 }
2113 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002114
Hanno Beckerda1655a2017-10-18 14:21:44 +01002115 Xp = (unsigned char*) X->p;
2116 f_rng( p_rng, Xp + overhead, size );
2117
Hanno Becker2be8a552018-10-25 12:40:09 +01002118 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002119
2120cleanup:
2121 return( ret );
2122}
2123
Paul Bakker5121ce52009-01-03 21:22:43 +00002124/*
2125 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002128{
2129 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002131 MPI_VALIDATE_RET( X != NULL );
2132 MPI_VALIDATE_RET( A != NULL );
2133 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002134
Hanno Becker4bcb4912017-04-18 15:49:39 +01002135 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002136 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2139 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2140 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002142 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002144 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002145 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002147 goto cleanup;
2148 }
2149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2151 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2152 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2153 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2156 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2157 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2158 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
2160 do
2161 {
2162 while( ( TU.p[0] & 1 ) == 0 )
2163 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002164 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002165
2166 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2167 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2169 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 }
2171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2173 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002174 }
2175
2176 while( ( TV.p[0] & 1 ) == 0 )
2177 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
2180 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2181 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2183 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184 }
2185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2187 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002188 }
2189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002191 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2193 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2194 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002195 }
2196 else
2197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2200 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002201 }
2202 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2206 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2209 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
2213cleanup:
2214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2216 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2217 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002218
2219 return( ret );
2220}
2221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002222#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002223
Paul Bakker5121ce52009-01-03 21:22:43 +00002224static const int small_prime[] =
2225{
2226 3, 5, 7, 11, 13, 17, 19, 23,
2227 29, 31, 37, 41, 43, 47, 53, 59,
2228 61, 67, 71, 73, 79, 83, 89, 97,
2229 101, 103, 107, 109, 113, 127, 131, 137,
2230 139, 149, 151, 157, 163, 167, 173, 179,
2231 181, 191, 193, 197, 199, 211, 223, 227,
2232 229, 233, 239, 241, 251, 257, 263, 269,
2233 271, 277, 281, 283, 293, 307, 311, 313,
2234 317, 331, 337, 347, 349, 353, 359, 367,
2235 373, 379, 383, 389, 397, 401, 409, 419,
2236 421, 431, 433, 439, 443, 449, 457, 461,
2237 463, 467, 479, 487, 491, 499, 503, 509,
2238 521, 523, 541, 547, 557, 563, 569, 571,
2239 577, 587, 593, 599, 601, 607, 613, 617,
2240 619, 631, 641, 643, 647, 653, 659, 661,
2241 673, 677, 683, 691, 701, 709, 719, 727,
2242 733, 739, 743, 751, 757, 761, 769, 773,
2243 787, 797, 809, 811, 821, 823, 827, 829,
2244 839, 853, 857, 859, 863, 877, 881, 883,
2245 887, 907, 911, 919, 929, 937, 941, 947,
2246 953, 967, 971, 977, 983, 991, 997, -103
2247};
2248
2249/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002250 * Small divisors test (X must be positive)
2251 *
2252 * Return values:
2253 * 0: no small factor (possible prime, more tests needed)
2254 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002255 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002256 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002259{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002260 int ret = 0;
2261 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002266
2267 for( i = 0; small_prime[i] > 0; i++ )
2268 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002270 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 }
2277
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002278cleanup:
2279 return( ret );
2280}
2281
2282/*
2283 * Miller-Rabin pseudo-primality test (HAC 4.24)
2284 */
Janos Follathda31fa12018-09-03 14:45:23 +01002285static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002286 int (*f_rng)(void *, unsigned char *, size_t),
2287 void *p_rng )
2288{
Pascal Junodb99183d2015-03-11 16:49:45 +01002289 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002290 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002292
Hanno Becker8ce11a32018-12-19 16:18:52 +00002293 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002294 MPI_VALIDATE_RET( f_rng != NULL );
2295
2296 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2297 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002299
Paul Bakker5121ce52009-01-03 21:22:43 +00002300 /*
2301 * W = |X| - 1
2302 * R = W >> lsb( W )
2303 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2305 s = mbedtls_mpi_lsb( &W );
2306 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2307 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002309 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002310
Janos Follathda31fa12018-09-03 14:45:23 +01002311 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002312 {
2313 /*
2314 * pick a random A, 1 < A < |X| - 1
2315 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002316 count = 0;
2317 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002318 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002319
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002320 j = mbedtls_mpi_bitlen( &A );
2321 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002322 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002323 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002324 }
2325
2326 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002327 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002328 }
2329
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002330 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2331 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332
2333 /*
2334 * A = A^R mod |X|
2335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2339 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002340 continue;
2341
2342 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002344 {
2345 /*
2346 * A = A * A mod |X|
2347 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2349 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002352 break;
2353
2354 j++;
2355 }
2356
2357 /*
2358 * not prime if A != |X| - 1 or A == 1
2359 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2361 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002362 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002364 break;
2365 }
2366 }
2367
2368cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002369 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2370 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002371 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002372
2373 return( ret );
2374}
2375
2376/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002377 * Pseudo-primality test: small factors, then Miller-Rabin
2378 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002379int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2380 int (*f_rng)(void *, unsigned char *, size_t),
2381 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002382{
2383 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002385 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002386 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002387
2388 XX.s = 1;
2389 XX.n = X->n;
2390 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2393 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2394 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002397 return( 0 );
2398
2399 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2400 {
2401 if( ret == 1 )
2402 return( 0 );
2403
2404 return( ret );
2405 }
2406
Janos Follathda31fa12018-09-03 14:45:23 +01002407 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002408}
2409
Janos Follatha0b67c22018-09-18 14:48:23 +01002410#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002411/*
2412 * Pseudo-primality test, error probability 2^-80
2413 */
2414int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2415 int (*f_rng)(void *, unsigned char *, size_t),
2416 void *p_rng )
2417{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002418 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002419 MPI_VALIDATE_RET( f_rng != NULL );
2420
Janos Follatha0b67c22018-09-18 14:48:23 +01002421 /*
2422 * In the past our key generation aimed for an error rate of at most
2423 * 2^-80. Since this function is deprecated, aim for the same certainty
2424 * here as well.
2425 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002426 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002427}
Janos Follatha0b67c22018-09-18 14:48:23 +01002428#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002429
2430/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002431 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002432 *
Janos Follathf301d232018-08-14 13:34:01 +01002433 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2434 * be either 1024 bits or 1536 bits long, and flags must contain
2435 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002436 */
Janos Follath7c025a92018-08-14 11:08:41 +01002437int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002438 int (*f_rng)(void *, unsigned char *, size_t),
2439 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002440{
Jethro Beekman66689272018-02-14 19:24:10 -08002441#ifdef MBEDTLS_HAVE_INT64
2442// ceil(2^63.5)
2443#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2444#else
2445// ceil(2^31.5)
2446#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2447#endif
2448 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002449 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002450 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 mbedtls_mpi_uint r;
2452 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002453
Hanno Becker8ce11a32018-12-19 16:18:52 +00002454 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002455 MPI_VALIDATE_RET( f_rng != NULL );
2456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2458 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002460 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002461
2462 n = BITS_TO_LIMBS( nbits );
2463
Janos Follathda31fa12018-09-03 14:45:23 +01002464 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2465 {
2466 /*
2467 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2468 */
2469 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2470 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2471 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2472 }
2473 else
2474 {
2475 /*
2476 * 2^-100 error probability, number of rounds computed based on HAC,
2477 * fact 4.48
2478 */
2479 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2480 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2481 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2482 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2483 }
2484
Jethro Beekman66689272018-02-14 19:24:10 -08002485 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002486 {
Jethro Beekman66689272018-02-14 19:24:10 -08002487 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2488 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2489 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2490
2491 k = n * biL;
2492 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2493 X->p[0] |= 1;
2494
Janos Follath7c025a92018-08-14 11:08:41 +01002495 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002496 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002497 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002500 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002501 }
Jethro Beekman66689272018-02-14 19:24:10 -08002502 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002503 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002504 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002505 * An necessary condition for Y and X = 2Y + 1 to be prime
2506 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2507 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002508 */
Jethro Beekman66689272018-02-14 19:24:10 -08002509
2510 X->p[0] |= 2;
2511
2512 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2513 if( r == 0 )
2514 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2515 else if( r == 1 )
2516 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2517
2518 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2519 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2520 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2521
2522 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002523 {
Jethro Beekman66689272018-02-14 19:24:10 -08002524 /*
2525 * First, check small factors for X and Y
2526 * before doing Miller-Rabin on any of them
2527 */
2528 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2529 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002530 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002531 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002532 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002533 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002534 goto cleanup;
2535
2536 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2537 goto cleanup;
2538
2539 /*
2540 * Next candidates. We want to preserve Y = (X-1) / 2 and
2541 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2542 * so up Y by 6 and X by 12.
2543 */
2544 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2545 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002546 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002547 }
2548 }
2549
2550cleanup:
2551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
2554 return( ret );
2555}
2556
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002557#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002560
Paul Bakker23986e52011-04-24 08:57:21 +00002561#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002562
2563static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2564{
2565 { 693, 609, 21 },
2566 { 1764, 868, 28 },
2567 { 768454923, 542167814, 1 }
2568};
2569
Paul Bakker5121ce52009-01-03 21:22:43 +00002570/*
2571 * Checkup routine
2572 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002573int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002574{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002575 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2579 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002582 "EFE021C2645FD1DC586E69184AF4A31E" \
2583 "D5F53E93B5F123FA41680867BA110131" \
2584 "944FE7952E2517337780CB0DB80E61AA" \
2585 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002588 "B2E7EFD37075B9F03FF989C7C5051C20" \
2589 "34D2A323810251127E7BF8625A4F49A5" \
2590 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2591 "5B5C25763222FEFCCFC38B832366C29E" ) );
2592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002594 "0066A198186C18C10B2F5ED9B522752A" \
2595 "9830B69916E535C8F047518A889A43A5" \
2596 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002601 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2602 "9E857EA95A03512E2BAE7391688D264A" \
2603 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2604 "8001B72E848A38CAE1C65F78E56ABDEF" \
2605 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2606 "ECF677152EF804370C1A305CAF3B5BF1" \
2607 "30879B56C61DE584A0F53A2447A51E" ) );
2608
2609 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002612 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002613 {
2614 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002616
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002617 ret = 1;
2618 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002619 }
2620
2621 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002623
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002627 "256567336059E52CAE22925474705F39A94" ) );
2628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002630 "6613F26162223DF488E9CD48CC132C7A" \
2631 "0AC93C701B001B092E4E5B9F73BCD27B" \
2632 "9EE50D0657C77F374E903CDFA4C642" ) );
2633
2634 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002636
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002637 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2638 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002639 {
2640 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002641 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002642
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002643 ret = 1;
2644 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002645 }
2646
2647 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002648 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002649
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002650 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002651
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002652 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002653 "36E139AEA55215609D2816998ED020BB" \
2654 "BD96C37890F65171D948E9BC7CBAA4D9" \
2655 "325D24D6A3C12710F10A09FA08AB87" ) );
2656
2657 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002658 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002661 {
2662 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002663 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002664
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002665 ret = 1;
2666 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002667 }
2668
2669 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002670 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002672 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002674 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002675 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2676 "C3DBA76456363A10869622EAC2DD84EC" \
2677 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2678
2679 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002680 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002683 {
2684 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002685 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002686
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002687 ret = 1;
2688 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002689 }
2690
2691 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002692 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002693
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002694 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002696
Paul Bakker66d5d072014-06-17 16:39:18 +02002697 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002698 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002699 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2700 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002705 {
2706 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002707 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002708
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002709 ret = 1;
2710 goto cleanup;
2711 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002712 }
2713
2714 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002715 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002716
Paul Bakker5121ce52009-01-03 21:22:43 +00002717cleanup:
2718
2719 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002720 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002722 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2723 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002724
2725 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002726 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002727
2728 return( ret );
2729}
2730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002733#endif /* MBEDTLS_BIGNUM_C */