blob: 47e4529befe2da2a780d9bfeff050e18176ff376 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
Ron Eldora16fa292018-11-20 14:07:01 +0200530 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000531 */
Ron Eldora16fa292018-11-20 14:07:01 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix,
533 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534{
535 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200537 size_t length = 0;
538 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Ron Eldora16fa292018-11-20 14:07:01 +0200540 do
541 {
542 if( length >= buflen )
543 {
544 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
545 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
Ron Eldora16fa292018-11-20 14:07:01 +0200547 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
548 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
549 /*
550 * Write the residue in the current position, as an ASCII character.
551 */
552 if( r < 0xA )
553 *(--p_end) = (char)( '0' + r );
554 else
555 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Ron Eldora16fa292018-11-20 14:07:01 +0200557 length++;
558 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Ron Eldora16fa292018-11-20 14:07:01 +0200560 memmove( *p, p_end, length );
561 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563cleanup:
564
565 return( ret );
566}
567
568/*
569 * Export into an ASCII string
570 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
572 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573{
Paul Bakker23986e52011-04-24 08:57:21 +0000574 int ret = 0;
575 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000578 MPI_VALIDATE_RET( X != NULL );
579 MPI_VALIDATE_RET( olen != NULL );
580 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
582 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000583 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200585 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000586 if( radix >= 4 ) n >>= 1;
587 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000588 /*
589 * Round up the buffer length to an even value to ensure that there is
590 * enough room for hexadecimal values that can be represented in an odd
591 * number of digits.
592 */
593 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100595 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000596 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100597 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 }
600
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100601 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603
604 if( X->s == -1 )
605 *p++ = '-';
606
607 if( radix == 16 )
608 {
Paul Bakker23986e52011-04-24 08:57:21 +0000609 int c;
610 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
Paul Bakker23986e52011-04-24 08:57:21 +0000612 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 {
Paul Bakker23986e52011-04-24 08:57:21 +0000614 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 {
Paul Bakker23986e52011-04-24 08:57:21 +0000616 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
Paul Bakker6c343d72014-07-10 14:36:19 +0200618 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 continue;
620
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000621 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000622 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 k = 1;
624 }
625 }
626 }
627 else
628 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000630
631 if( T.s == -1 )
632 T.s = 1;
633
Ron Eldora16fa292018-11-20 14:07:01 +0200634 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635 }
636
637 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100638 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640cleanup:
641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
644 return( ret );
645}
646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000648/*
649 * Read X from an opened file
650 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000652{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000654 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000655 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000656 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000657 * Buffer should have space for (short) label and decimal formatted MPI,
658 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000659 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Hanno Becker73d7d792018-12-11 10:35:51 +0000662 MPI_VALIDATE_RET( X != NULL );
663 MPI_VALIDATE_RET( fin != NULL );
664
665 if( radix < 2 || radix > 16 )
666 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
667
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 memset( s, 0, sizeof( s ) );
669 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000673 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000675
Hanno Beckerb2034b72017-04-26 11:46:46 +0100676 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
677 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
679 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100680 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 if( mpi_get_digit( &d, radix, *p ) != 0 )
682 break;
683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000685}
686
687/*
688 * Write X into an opened file (or stdout if fout == NULL)
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Paul Bakker23986e52011-04-24 08:57:21 +0000692 int ret;
693 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000694 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000695 * Buffer should have space for (short) label and decimal formatted MPI,
696 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000699 MPI_VALIDATE_RET( X != NULL );
700
701 if( radix < 2 || radix > 16 )
702 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100704 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100706 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708 if( p == NULL ) p = "";
709
710 plen = strlen( p );
711 slen = strlen( s );
712 s[slen++] = '\r';
713 s[slen++] = '\n';
714
715 if( fout != NULL )
716 {
717 if( fwrite( p, 1, plen, fout ) != plen ||
718 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000720 }
721 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724cleanup:
725
726 return( ret );
727}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Hanno Beckerda1655a2017-10-18 14:21:44 +0100730
731/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
732 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000733
734static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
735{
736 uint8_t i;
737 mbedtls_mpi_uint tmp = 0;
738 /* This works regardless of the endianness. */
739 for( i = 0; i < ciL; i++, x >>= 8 )
740 tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
741 return( tmp );
742}
743
744static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
745{
746#if defined(__BYTE_ORDER__)
747
748/* Nothing to do on bigendian systems. */
749#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
750 return( x );
751#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
752
753#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
754
755/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000756#if defined(__GNUC__) && defined(__GNUC_PREREQ)
757#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000758#define have_bswap
759#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000760#endif
761
762#if defined(__clang__) && defined(__has_builtin)
763#if __has_builtin(__builtin_bswap32) && \
764 __has_builtin(__builtin_bswap64)
765#define have_bswap
766#endif
767#endif
768
Hanno Beckerf8720072018-11-08 11:53:49 +0000769#if defined(have_bswap)
770 /* The compiler is hopefully able to statically evaluate this! */
771 switch( sizeof(mbedtls_mpi_uint) )
772 {
773 case 4:
774 return( __builtin_bswap32(x) );
775 case 8:
776 return( __builtin_bswap64(x) );
777 }
778#endif
779#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
780#endif /* __BYTE_ORDER__ */
781
782 /* Fall back to C-based reordering if we don't know the byte order
783 * or we couldn't use a compiler-specific builtin. */
784 return( mpi_uint_bigendian_to_host_c( x ) );
785}
786
Hanno Becker2be8a552018-10-25 12:40:09 +0100787static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100788{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100789 mbedtls_mpi_uint *cur_limb_left;
790 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100791 if( limbs == 0 )
792 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100793
794 /*
795 * Traverse limbs and
796 * - adapt byte-order in each limb
797 * - swap the limbs themselves.
798 * For that, simultaneously traverse the limbs from left to right
799 * and from right to left, as long as the left index is not bigger
800 * than the right index (it's not a problem if limbs is odd and the
801 * indices coincide in the last iteration).
802 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100803 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
804 cur_limb_left <= cur_limb_right;
805 cur_limb_left++, cur_limb_right-- )
806 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000807 mbedtls_mpi_uint tmp;
808 /* Note that if cur_limb_left == cur_limb_right,
809 * this code effectively swaps the bytes only once. */
810 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
811 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
812 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100813 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100814}
815
Paul Bakker5121ce52009-01-03 21:22:43 +0000816/*
817 * Import X from unsigned binary data, big endian
818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000820{
Paul Bakker23986e52011-04-24 08:57:21 +0000821 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100822 size_t const limbs = CHARS_TO_LIMBS( buflen );
823 size_t const overhead = ( limbs * ciL ) - buflen;
824 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000825
Hanno Becker8ce11a32018-12-19 16:18:52 +0000826 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000827 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
828
Hanno Becker073c1992017-10-17 15:17:27 +0100829 /* Ensure that target MPI has exactly the necessary number of limbs */
830 if( X->n != limbs )
831 {
832 mbedtls_mpi_free( X );
833 mbedtls_mpi_init( X );
834 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
835 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200836 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000837
Hanno Becker0e810b92019-01-03 17:13:11 +0000838 /* Avoid calling `memcpy` with NULL source argument,
839 * even if buflen is 0. */
840 if( buf != NULL )
841 {
842 Xp = (unsigned char*) X->p;
843 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100844
Hanno Becker0e810b92019-01-03 17:13:11 +0000845 mpi_bigendian_to_host( X->p, limbs );
846 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000847
848cleanup:
849
850 return( ret );
851}
852
853/*
854 * Export X into unsigned binary data, big endian
855 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100856int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
857 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000858{
Hanno Becker73d7d792018-12-11 10:35:51 +0000859 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100860 size_t bytes_to_copy;
861 unsigned char *p;
862 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000863
Hanno Becker73d7d792018-12-11 10:35:51 +0000864 MPI_VALIDATE_RET( X != NULL );
865 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
866
867 stored_bytes = X->n * ciL;
868
Gilles Peskine11cdb052018-11-20 16:47:47 +0100869 if( stored_bytes < buflen )
870 {
871 /* There is enough space in the output buffer. Write initial
872 * null bytes and record the position at which to start
873 * writing the significant bytes. In this case, the execution
874 * trace of this function does not depend on the value of the
875 * number. */
876 bytes_to_copy = stored_bytes;
877 p = buf + buflen - stored_bytes;
878 memset( buf, 0, buflen - stored_bytes );
879 }
880 else
881 {
882 /* The output buffer is smaller than the allocated size of X.
883 * However X may fit if its leading bytes are zero. */
884 bytes_to_copy = buflen;
885 p = buf;
886 for( i = bytes_to_copy; i < stored_bytes; i++ )
887 {
888 if( GET_BYTE( X, i ) != 0 )
889 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
890 }
891 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000892
Gilles Peskine11cdb052018-11-20 16:47:47 +0100893 for( i = 0; i < bytes_to_copy; i++ )
894 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000895
896 return( 0 );
897}
898
899/*
900 * Left-shift: X <<= count
901 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000903{
Paul Bakker23986e52011-04-24 08:57:21 +0000904 int ret;
905 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000907 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000908
909 v0 = count / (biL );
910 t1 = count & (biL - 1);
911
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200912 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000913
Paul Bakkerf9688572011-05-05 10:00:45 +0000914 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000916
917 ret = 0;
918
919 /*
920 * shift by count / limb_size
921 */
922 if( v0 > 0 )
923 {
Paul Bakker23986e52011-04-24 08:57:21 +0000924 for( i = X->n; i > v0; i-- )
925 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
Paul Bakker23986e52011-04-24 08:57:21 +0000927 for( ; i > 0; i-- )
928 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000929 }
930
931 /*
932 * shift by count % limb_size
933 */
934 if( t1 > 0 )
935 {
936 for( i = v0; i < X->n; i++ )
937 {
938 r1 = X->p[i] >> (biL - t1);
939 X->p[i] <<= t1;
940 X->p[i] |= r0;
941 r0 = r1;
942 }
943 }
944
945cleanup:
946
947 return( ret );
948}
949
950/*
951 * Right-shift: X >>= count
952 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000954{
Paul Bakker23986e52011-04-24 08:57:21 +0000955 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000957 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000958
959 v0 = count / biL;
960 v1 = count & (biL - 1);
961
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100962 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200963 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100964
Paul Bakker5121ce52009-01-03 21:22:43 +0000965 /*
966 * shift by count / limb_size
967 */
968 if( v0 > 0 )
969 {
970 for( i = 0; i < X->n - v0; i++ )
971 X->p[i] = X->p[i + v0];
972
973 for( ; i < X->n; i++ )
974 X->p[i] = 0;
975 }
976
977 /*
978 * shift by count % limb_size
979 */
980 if( v1 > 0 )
981 {
Paul Bakker23986e52011-04-24 08:57:21 +0000982 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000983 {
Paul Bakker23986e52011-04-24 08:57:21 +0000984 r1 = X->p[i - 1] << (biL - v1);
985 X->p[i - 1] >>= v1;
986 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000987 r0 = r1;
988 }
989 }
990
991 return( 0 );
992}
993
994/*
995 * Compare unsigned values
996 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000998{
Paul Bakker23986e52011-04-24 08:57:21 +0000999 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001000 MPI_VALIDATE_RET( X != NULL );
1001 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001002
Paul Bakker23986e52011-04-24 08:57:21 +00001003 for( i = X->n; i > 0; i-- )
1004 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001005 break;
1006
Paul Bakker23986e52011-04-24 08:57:21 +00001007 for( j = Y->n; j > 0; j-- )
1008 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001009 break;
1010
Paul Bakker23986e52011-04-24 08:57:21 +00001011 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 return( 0 );
1013
1014 if( i > j ) return( 1 );
1015 if( j > i ) return( -1 );
1016
Paul Bakker23986e52011-04-24 08:57:21 +00001017 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 {
Paul Bakker23986e52011-04-24 08:57:21 +00001019 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1020 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 }
1022
1023 return( 0 );
1024}
1025
1026/*
1027 * Compare signed values
1028 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001029int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001030{
Paul Bakker23986e52011-04-24 08:57:21 +00001031 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001032 MPI_VALIDATE_RET( X != NULL );
1033 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034
Paul Bakker23986e52011-04-24 08:57:21 +00001035 for( i = X->n; i > 0; i-- )
1036 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001037 break;
1038
Paul Bakker23986e52011-04-24 08:57:21 +00001039 for( j = Y->n; j > 0; j-- )
1040 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001041 break;
1042
Paul Bakker23986e52011-04-24 08:57:21 +00001043 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001044 return( 0 );
1045
1046 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001047 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001048
1049 if( X->s > 0 && Y->s < 0 ) return( 1 );
1050 if( Y->s > 0 && X->s < 0 ) return( -1 );
1051
Paul Bakker23986e52011-04-24 08:57:21 +00001052 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001053 {
Paul Bakker23986e52011-04-24 08:57:21 +00001054 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1055 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001056 }
1057
1058 return( 0 );
1059}
1060
1061/*
1062 * Compare signed values
1063 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001065{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 mbedtls_mpi Y;
1067 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001068 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069
1070 *p = ( z < 0 ) ? -z : z;
1071 Y.s = ( z < 0 ) ? -1 : 1;
1072 Y.n = 1;
1073 Y.p = p;
1074
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001076}
1077
1078/*
1079 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1080 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082{
Paul Bakker23986e52011-04-24 08:57:21 +00001083 int ret;
1084 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001085 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001086 MPI_VALIDATE_RET( X != NULL );
1087 MPI_VALIDATE_RET( A != NULL );
1088 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001089
1090 if( X == B )
1091 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 }
1094
1095 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001097
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001098 /*
1099 * X should always be positive as a result of unsigned additions.
1100 */
1101 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001102
Paul Bakker23986e52011-04-24 08:57:21 +00001103 for( j = B->n; j > 0; j-- )
1104 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001105 break;
1106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001108
1109 o = B->p; p = X->p; c = 0;
1110
Janos Follath6c922682015-10-30 17:43:11 +01001111 /*
1112 * tmp is used because it might happen that p == o
1113 */
Paul Bakker23986e52011-04-24 08:57:21 +00001114 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001115 {
Janos Follath6c922682015-10-30 17:43:11 +01001116 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001117 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001118 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001119 }
1120
1121 while( c != 0 )
1122 {
1123 if( i >= X->n )
1124 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126 p = X->p + i;
1127 }
1128
Paul Bakker2d319fd2012-09-16 21:34:26 +00001129 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 }
1131
1132cleanup:
1133
1134 return( ret );
1135}
1136
1137/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001138 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001140static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001141{
Paul Bakker23986e52011-04-24 08:57:21 +00001142 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001144
1145 for( i = c = 0; i < n; i++, s++, d++ )
1146 {
1147 z = ( *d < c ); *d -= c;
1148 c = ( *d < *s ) + z; *d -= *s;
1149 }
1150
1151 while( c != 0 )
1152 {
1153 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001154 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001155 }
1156}
1157
1158/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001159 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001160 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001161int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001162{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001163 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001164 int ret;
1165 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001166 MPI_VALIDATE_RET( X != NULL );
1167 MPI_VALIDATE_RET( A != NULL );
1168 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1171 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
1175 if( X == B )
1176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001178 B = &TB;
1179 }
1180
1181 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
Paul Bakker1ef7a532009-06-20 10:50:55 +00001184 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001185 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001186 */
1187 X->s = 1;
1188
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 ret = 0;
1190
Paul Bakker23986e52011-04-24 08:57:21 +00001191 for( n = B->n; n > 0; n-- )
1192 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 break;
1194
Paul Bakker23986e52011-04-24 08:57:21 +00001195 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
1197cleanup:
1198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001199 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
1201 return( ret );
1202}
1203
1204/*
1205 * Signed addition: X = A + B
1206 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001208{
Hanno Becker73d7d792018-12-11 10:35:51 +00001209 int ret, s;
1210 MPI_VALIDATE_RET( X != NULL );
1211 MPI_VALIDATE_RET( A != NULL );
1212 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001213
Hanno Becker73d7d792018-12-11 10:35:51 +00001214 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001215 if( A->s * B->s < 0 )
1216 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001218 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001219 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 X->s = s;
1221 }
1222 else
1223 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001225 X->s = -s;
1226 }
1227 }
1228 else
1229 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 X->s = s;
1232 }
1233
1234cleanup:
1235
1236 return( ret );
1237}
1238
1239/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001240 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001243{
Hanno Becker73d7d792018-12-11 10:35:51 +00001244 int ret, s;
1245 MPI_VALIDATE_RET( X != NULL );
1246 MPI_VALIDATE_RET( A != NULL );
1247 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001248
Hanno Becker73d7d792018-12-11 10:35:51 +00001249 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001250 if( A->s * B->s > 0 )
1251 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001253 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001255 X->s = s;
1256 }
1257 else
1258 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001260 X->s = -s;
1261 }
1262 }
1263 else
1264 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001266 X->s = s;
1267 }
1268
1269cleanup:
1270
1271 return( ret );
1272}
1273
1274/*
1275 * Signed addition: X = A + b
1276 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001278{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001279 mbedtls_mpi _B;
1280 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001281 MPI_VALIDATE_RET( X != NULL );
1282 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001283
1284 p[0] = ( b < 0 ) ? -b : b;
1285 _B.s = ( b < 0 ) ? -1 : 1;
1286 _B.n = 1;
1287 _B.p = p;
1288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001290}
1291
1292/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001293 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001294 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001295int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001296{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001297 mbedtls_mpi _B;
1298 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001299 MPI_VALIDATE_RET( X != NULL );
1300 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001301
1302 p[0] = ( b < 0 ) ? -b : b;
1303 _B.s = ( b < 0 ) ? -1 : 1;
1304 _B.n = 1;
1305 _B.p = p;
1306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001308}
1309
1310/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001312 */
1313static
1314#if defined(__APPLE__) && defined(__arm__)
1315/*
1316 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1317 * appears to need this to prevent bad ARM code generation at -O3.
1318 */
1319__attribute__ ((noinline))
1320#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321void 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 +00001322{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001324
1325#if defined(MULADDC_HUIT)
1326 for( ; i >= 8; i -= 8 )
1327 {
1328 MULADDC_INIT
1329 MULADDC_HUIT
1330 MULADDC_STOP
1331 }
1332
1333 for( ; i > 0; i-- )
1334 {
1335 MULADDC_INIT
1336 MULADDC_CORE
1337 MULADDC_STOP
1338 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001339#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 for( ; i >= 16; i -= 16 )
1341 {
1342 MULADDC_INIT
1343 MULADDC_CORE MULADDC_CORE
1344 MULADDC_CORE MULADDC_CORE
1345 MULADDC_CORE MULADDC_CORE
1346 MULADDC_CORE MULADDC_CORE
1347
1348 MULADDC_CORE MULADDC_CORE
1349 MULADDC_CORE MULADDC_CORE
1350 MULADDC_CORE MULADDC_CORE
1351 MULADDC_CORE MULADDC_CORE
1352 MULADDC_STOP
1353 }
1354
1355 for( ; i >= 8; i -= 8 )
1356 {
1357 MULADDC_INIT
1358 MULADDC_CORE MULADDC_CORE
1359 MULADDC_CORE MULADDC_CORE
1360
1361 MULADDC_CORE MULADDC_CORE
1362 MULADDC_CORE MULADDC_CORE
1363 MULADDC_STOP
1364 }
1365
1366 for( ; i > 0; i-- )
1367 {
1368 MULADDC_INIT
1369 MULADDC_CORE
1370 MULADDC_STOP
1371 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001372#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
1374 t++;
1375
1376 do {
1377 *d += c; c = ( *d < c ); d++;
1378 }
1379 while( c != 0 );
1380}
1381
1382/*
1383 * Baseline multiplication: X = A * B (HAC 14.12)
1384 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001386{
Paul Bakker23986e52011-04-24 08:57:21 +00001387 int ret;
1388 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001390 MPI_VALIDATE_RET( X != NULL );
1391 MPI_VALIDATE_RET( A != NULL );
1392 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1397 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001398
Paul Bakker23986e52011-04-24 08:57:21 +00001399 for( i = A->n; i > 0; i-- )
1400 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 break;
1402
Paul Bakker23986e52011-04-24 08:57:21 +00001403 for( j = B->n; j > 0; j-- )
1404 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001405 break;
1406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1408 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001409
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001410 for( ; j > 0; j-- )
1411 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001412
1413 X->s = A->s * B->s;
1414
1415cleanup:
1416
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001418
1419 return( ret );
1420}
1421
1422/*
1423 * Baseline multiplication: X = A * b
1424 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001425int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001426{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001427 mbedtls_mpi _B;
1428 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001429 MPI_VALIDATE_RET( X != NULL );
1430 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001431
1432 _B.s = 1;
1433 _B.n = 1;
1434 _B.p = p;
1435 p[0] = b;
1436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001438}
1439
1440/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001441 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1442 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001443 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001444static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1445 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001446{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001447#if defined(MBEDTLS_HAVE_UDBL)
1448 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001449#else
Simon Butcher9803d072016-01-03 00:24:34 +00001450 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1451 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001452 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1453 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001454 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001455#endif
1456
Simon Butcher15b15d12015-11-26 19:35:03 +00001457 /*
1458 * Check for overflow
1459 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001460 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001461 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001462 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001463
Simon Butcherf5ba0452015-12-27 23:01:55 +00001464 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001465 }
1466
1467#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001468 dividend = (mbedtls_t_udbl) u1 << biL;
1469 dividend |= (mbedtls_t_udbl) u0;
1470 quotient = dividend / d;
1471 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1472 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1473
1474 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001475 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001476
1477 return (mbedtls_mpi_uint) quotient;
1478#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001479
1480 /*
1481 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1482 * Vol. 2 - Seminumerical Algorithms, Knuth
1483 */
1484
1485 /*
1486 * Normalize the divisor, d, and dividend, u0, u1
1487 */
1488 s = mbedtls_clz( d );
1489 d = d << s;
1490
1491 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001492 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001493 u0 = u0 << s;
1494
1495 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001496 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001497
1498 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001499 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001500
1501 /*
1502 * Find the first quotient and remainder
1503 */
1504 q1 = u1 / d1;
1505 r0 = u1 - d1 * q1;
1506
1507 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1508 {
1509 q1 -= 1;
1510 r0 += d1;
1511
1512 if ( r0 >= radix ) break;
1513 }
1514
Simon Butcherf5ba0452015-12-27 23:01:55 +00001515 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001516 q0 = rAX / d1;
1517 r0 = rAX - q0 * d1;
1518
1519 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1520 {
1521 q0 -= 1;
1522 r0 += d1;
1523
1524 if ( r0 >= radix ) break;
1525 }
1526
1527 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001528 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001529
1530 quotient = q1 * radix + q0;
1531
1532 return quotient;
1533#endif
1534}
1535
1536/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001538 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001539int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1540 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001541{
Paul Bakker23986e52011-04-24 08:57:21 +00001542 int ret;
1543 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001545 MPI_VALIDATE_RET( A != NULL );
1546 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1549 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001551 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1552 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001555 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1557 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001558 return( 0 );
1559 }
1560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001561 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 X.s = Y.s = 1;
1564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1566 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1567 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1568 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001569
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001570 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001571 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001572 {
1573 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1575 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 }
1577 else k = 0;
1578
1579 n = X.n - 1;
1580 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001584 {
1585 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001587 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001589
1590 for( i = n; i > t ; i-- )
1591 {
1592 if( X.p[i] >= Y.p[t] )
1593 Z.p[i - t - 1] = ~0;
1594 else
1595 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001596 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1597 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001598 }
1599
1600 Z.p[i - t - 1]++;
1601 do
1602 {
1603 Z.p[i - t - 1]--;
1604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001606 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001607 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001611 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1612 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001613 T2.p[2] = X.p[i];
1614 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001617 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1618 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1619 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001622 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1624 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1625 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001626 Z.p[i - t - 1]--;
1627 }
1628 }
1629
1630 if( Q != NULL )
1631 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 Q->s = A->s * B->s;
1634 }
1635
1636 if( R != NULL )
1637 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001639 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001643 R->s = 1;
1644 }
1645
1646cleanup:
1647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001648 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1649 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
1651 return( ret );
1652}
1653
1654/*
1655 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001656 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001657int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1658 const mbedtls_mpi *A,
1659 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001660{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 mbedtls_mpi _B;
1662 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001663 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
1665 p[0] = ( b < 0 ) ? -b : b;
1666 _B.s = ( b < 0 ) ? -1 : 1;
1667 _B.n = 1;
1668 _B.p = p;
1669
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001670 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001671}
1672
1673/*
1674 * Modulo: R = A mod B
1675 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001677{
1678 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001679 MPI_VALIDATE_RET( R != NULL );
1680 MPI_VALIDATE_RET( A != NULL );
1681 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001682
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1684 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001685
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1692 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
1694cleanup:
1695
1696 return( ret );
1697}
1698
1699/*
1700 * Modulo: r = A mod b
1701 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001703{
Paul Bakker23986e52011-04-24 08:57:21 +00001704 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001706 MPI_VALIDATE_RET( r != NULL );
1707 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001708
1709 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001710 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001711
1712 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001713 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001714
1715 /*
1716 * handle trivial cases
1717 */
1718 if( b == 1 )
1719 {
1720 *r = 0;
1721 return( 0 );
1722 }
1723
1724 if( b == 2 )
1725 {
1726 *r = A->p[0] & 1;
1727 return( 0 );
1728 }
1729
1730 /*
1731 * general case
1732 */
Paul Bakker23986e52011-04-24 08:57:21 +00001733 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001734 {
Paul Bakker23986e52011-04-24 08:57:21 +00001735 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001736 y = ( y << biH ) | ( x >> biH );
1737 z = y / b;
1738 y -= z * b;
1739
1740 x <<= biH;
1741 y = ( y << biH ) | ( x >> biH );
1742 z = y / b;
1743 y -= z * b;
1744 }
1745
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001746 /*
1747 * If A is negative, then the current y represents a negative value.
1748 * Flipping it to the positive side.
1749 */
1750 if( A->s < 0 && y != 0 )
1751 y = b - y;
1752
Paul Bakker5121ce52009-01-03 21:22:43 +00001753 *r = y;
1754
1755 return( 0 );
1756}
1757
1758/*
1759 * Fast Montgomery initialization (thanks to Tom St Denis)
1760 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001762{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001764 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001765
1766 x = m0;
1767 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001768
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001769 for( i = biL; i >= 8; i /= 2 )
1770 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001771
1772 *mm = ~x + 1;
1773}
1774
1775/*
1776 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1777 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001778static 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 +02001779 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001780{
Paul Bakker23986e52011-04-24 08:57:21 +00001781 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001782 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001783
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001784 if( T->n < N->n + 1 || T->p == NULL )
1785 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1786
Paul Bakker5121ce52009-01-03 21:22:43 +00001787 memset( T->p, 0, T->n * ciL );
1788
1789 d = T->p;
1790 n = N->n;
1791 m = ( B->n < n ) ? B->n : n;
1792
1793 for( i = 0; i < n; i++ )
1794 {
1795 /*
1796 * T = (T + u0*B + u1*N) / 2^biL
1797 */
1798 u0 = A->p[i];
1799 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1800
1801 mpi_mul_hlp( m, B->p, d, u0 );
1802 mpi_mul_hlp( n, N->p, d, u1 );
1803
1804 *d++ = u0; d[n + 1] = 0;
1805 }
1806
Paul Bakker66d5d072014-06-17 16:39:18 +02001807 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001810 mpi_sub_hlp( n, N->p, A->p );
1811 else
1812 /* prevent timing attacks */
1813 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001814
1815 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001816}
1817
1818/*
1819 * Montgomery reduction: A = A * R^-1 mod N
1820 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001821static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1822 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001823{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 mbedtls_mpi_uint z = 1;
1825 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
Paul Bakker8ddb6452013-02-27 14:56:33 +01001827 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001828 U.p = &z;
1829
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001830 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831}
1832
1833/*
1834 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1835 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001836int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1837 const mbedtls_mpi *E, const mbedtls_mpi *N,
1838 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001839{
Paul Bakker23986e52011-04-24 08:57:21 +00001840 int ret;
1841 size_t wbits, wsize, one = 1;
1842 size_t i, j, nblimbs;
1843 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 mbedtls_mpi_uint ei, mm, state;
1845 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001846 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001847
Hanno Becker73d7d792018-12-11 10:35:51 +00001848 MPI_VALIDATE_RET( X != NULL );
1849 MPI_VALIDATE_RET( A != NULL );
1850 MPI_VALIDATE_RET( E != NULL );
1851 MPI_VALIDATE_RET( N != NULL );
1852
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001853 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1857 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001858
1859 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001860 * Init temps and window size
1861 */
1862 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1864 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001865 memset( W, 0, sizeof( W ) );
1866
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001867 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001868
1869 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1870 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1871
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001872#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1874 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001875#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001876
Paul Bakker5121ce52009-01-03 21:22:43 +00001877 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1879 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
1882 /*
Paul Bakker50546922012-05-19 08:40:49 +00001883 * Compensate for negative A (and correct at the end)
1884 */
1885 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001886 if( neg )
1887 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001889 Apos.s = 1;
1890 A = &Apos;
1891 }
1892
1893 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001894 * If 1st call, pre-compute R^2 mod N
1895 */
1896 if( _RR == NULL || _RR->p == NULL )
1897 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1899 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1900 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001901
1902 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001904 }
1905 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001907
1908 /*
1909 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1910 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1912 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001913 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001914 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001916 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917
1918 /*
1919 * X = R^2 * R^-1 mod N = R mod N
1920 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001922 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
1924 if( wsize > 1 )
1925 {
1926 /*
1927 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1928 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001929 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1932 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
1934 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001935 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001936
Paul Bakker5121ce52009-01-03 21:22:43 +00001937 /*
1938 * W[i] = W[i - 1] * W[1]
1939 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001940 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001941 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1943 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001944
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001945 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 }
1947 }
1948
1949 nblimbs = E->n;
1950 bufsize = 0;
1951 nbits = 0;
1952 wbits = 0;
1953 state = 0;
1954
1955 while( 1 )
1956 {
1957 if( bufsize == 0 )
1958 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001959 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001960 break;
1961
Paul Bakker0d7702c2013-10-29 16:18:35 +01001962 nblimbs--;
1963
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001965 }
1966
1967 bufsize--;
1968
1969 ei = (E->p[nblimbs] >> bufsize) & 1;
1970
1971 /*
1972 * skip leading 0s
1973 */
1974 if( ei == 0 && state == 0 )
1975 continue;
1976
1977 if( ei == 0 && state == 1 )
1978 {
1979 /*
1980 * out of window, square X
1981 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001982 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001983 continue;
1984 }
1985
1986 /*
1987 * add ei to current window
1988 */
1989 state = 2;
1990
1991 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001992 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001993
1994 if( nbits == wsize )
1995 {
1996 /*
1997 * X = X^wsize R^-1 mod N
1998 */
1999 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002000 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002001
2002 /*
2003 * X = X * W[wbits] R^-1 mod N
2004 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002005 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
2007 state--;
2008 nbits = 0;
2009 wbits = 0;
2010 }
2011 }
2012
2013 /*
2014 * process the remaining bits
2015 */
2016 for( i = 0; i < nbits; i++ )
2017 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002018 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
2020 wbits <<= 1;
2021
Paul Bakker66d5d072014-06-17 16:39:18 +02002022 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002023 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002024 }
2025
2026 /*
2027 * X = A^E * R * R^-1 mod N = A^E mod N
2028 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002029 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
Hanno Beckera4af1c42017-04-18 09:07:45 +01002031 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002032 {
2033 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002035 }
2036
Paul Bakker5121ce52009-01-03 21:22:43 +00002037cleanup:
2038
Paul Bakker66d5d072014-06-17 16:39:18 +02002039 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002043
Paul Bakker75a28602014-03-31 12:08:17 +02002044 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
2047 return( ret );
2048}
2049
Paul Bakker5121ce52009-01-03 21:22:43 +00002050/*
2051 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2052 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002053int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002054{
Paul Bakker23986e52011-04-24 08:57:21 +00002055 int ret;
2056 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
Hanno Becker73d7d792018-12-11 10:35:51 +00002059 MPI_VALIDATE_RET( G != NULL );
2060 MPI_VALIDATE_RET( A != NULL );
2061 MPI_VALIDATE_RET( B != NULL );
2062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2066 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 lz = mbedtls_mpi_lsb( &TA );
2069 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002070
Paul Bakker66d5d072014-06-17 16:39:18 +02002071 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002072 lz = lzt;
2073
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2075 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002076
Paul Bakker5121ce52009-01-03 21:22:43 +00002077 TA.s = TB.s = 1;
2078
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002080 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2082 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002085 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2087 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002088 }
2089 else
2090 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2092 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002093 }
2094 }
2095
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2097 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002098
2099cleanup:
2100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002101 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002102
2103 return( ret );
2104}
2105
Paul Bakker33dc46b2014-04-30 16:11:39 +02002106/*
2107 * Fill X with size bytes of random.
2108 *
2109 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002110 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002111 * deterministic, eg for tests).
2112 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002114 int (*f_rng)(void *, unsigned char *, size_t),
2115 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002116{
Paul Bakker23986e52011-04-24 08:57:21 +00002117 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002118 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002119 size_t const overhead = ( limbs * ciL ) - size;
2120 unsigned char *Xp;
2121
Hanno Becker8ce11a32018-12-19 16:18:52 +00002122 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002123 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002124
Hanno Beckerda1655a2017-10-18 14:21:44 +01002125 /* Ensure that target MPI has exactly the necessary number of limbs */
2126 if( X->n != limbs )
2127 {
2128 mbedtls_mpi_free( X );
2129 mbedtls_mpi_init( X );
2130 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2131 }
2132 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002133
Hanno Beckerda1655a2017-10-18 14:21:44 +01002134 Xp = (unsigned char*) X->p;
2135 f_rng( p_rng, Xp + overhead, size );
2136
Hanno Becker2be8a552018-10-25 12:40:09 +01002137 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002138
2139cleanup:
2140 return( ret );
2141}
2142
Paul Bakker5121ce52009-01-03 21:22:43 +00002143/*
2144 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002146int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002147{
2148 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002150 MPI_VALIDATE_RET( X != NULL );
2151 MPI_VALIDATE_RET( A != NULL );
2152 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002153
Hanno Becker4bcb4912017-04-18 15:49:39 +01002154 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2158 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2159 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002164 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002166 goto cleanup;
2167 }
2168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2170 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2171 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2172 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2175 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2176 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2177 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
2179 do
2180 {
2181 while( ( TU.p[0] & 1 ) == 0 )
2182 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184
2185 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2186 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2188 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189 }
2190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2192 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002193 }
2194
2195 while( ( TV.p[0] & 1 ) == 0 )
2196 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002198
2199 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2200 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2202 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002203 }
2204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2206 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 }
2208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002210 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2212 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2213 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002214 }
2215 else
2216 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2218 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2219 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220 }
2221 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002222 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2225 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2228 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
2232cleanup:
2233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2235 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2236 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
2238 return( ret );
2239}
2240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002241#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002242
Paul Bakker5121ce52009-01-03 21:22:43 +00002243static const int small_prime[] =
2244{
2245 3, 5, 7, 11, 13, 17, 19, 23,
2246 29, 31, 37, 41, 43, 47, 53, 59,
2247 61, 67, 71, 73, 79, 83, 89, 97,
2248 101, 103, 107, 109, 113, 127, 131, 137,
2249 139, 149, 151, 157, 163, 167, 173, 179,
2250 181, 191, 193, 197, 199, 211, 223, 227,
2251 229, 233, 239, 241, 251, 257, 263, 269,
2252 271, 277, 281, 283, 293, 307, 311, 313,
2253 317, 331, 337, 347, 349, 353, 359, 367,
2254 373, 379, 383, 389, 397, 401, 409, 419,
2255 421, 431, 433, 439, 443, 449, 457, 461,
2256 463, 467, 479, 487, 491, 499, 503, 509,
2257 521, 523, 541, 547, 557, 563, 569, 571,
2258 577, 587, 593, 599, 601, 607, 613, 617,
2259 619, 631, 641, 643, 647, 653, 659, 661,
2260 673, 677, 683, 691, 701, 709, 719, 727,
2261 733, 739, 743, 751, 757, 761, 769, 773,
2262 787, 797, 809, 811, 821, 823, 827, 829,
2263 839, 853, 857, 859, 863, 877, 881, 883,
2264 887, 907, 911, 919, 929, 937, 941, 947,
2265 953, 967, 971, 977, 983, 991, 997, -103
2266};
2267
2268/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002269 * Small divisors test (X must be positive)
2270 *
2271 * Return values:
2272 * 0: no small factor (possible prime, more tests needed)
2273 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002275 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002276 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002278{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002279 int ret = 0;
2280 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002282
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
2286 for( i = 0; small_prime[i] > 0; i++ )
2287 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002289 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
2293 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002295 }
2296
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002297cleanup:
2298 return( ret );
2299}
2300
2301/*
2302 * Miller-Rabin pseudo-primality test (HAC 4.24)
2303 */
Janos Follathda31fa12018-09-03 14:45:23 +01002304static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002305 int (*f_rng)(void *, unsigned char *, size_t),
2306 void *p_rng )
2307{
Pascal Junodb99183d2015-03-11 16:49:45 +01002308 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002309 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002311
Hanno Becker8ce11a32018-12-19 16:18:52 +00002312 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002313 MPI_VALIDATE_RET( f_rng != NULL );
2314
2315 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2316 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002318
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 /*
2320 * W = |X| - 1
2321 * R = W >> lsb( W )
2322 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2324 s = mbedtls_mpi_lsb( &W );
2325 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2326 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002328 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002329
Janos Follathda31fa12018-09-03 14:45:23 +01002330 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 {
2332 /*
2333 * pick a random A, 1 < A < |X| - 1
2334 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002335 count = 0;
2336 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002337 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002338
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002339 j = mbedtls_mpi_bitlen( &A );
2340 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002341 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002342 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002343 }
2344
2345 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002346 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002347 }
2348
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002349 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2350 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
2352 /*
2353 * A = A^R mod |X|
2354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2358 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002359 continue;
2360
2361 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002363 {
2364 /*
2365 * A = A * A mod |X|
2366 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2368 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002371 break;
2372
2373 j++;
2374 }
2375
2376 /*
2377 * not prime if A != |X| - 1 or A == 1
2378 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2380 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002383 break;
2384 }
2385 }
2386
2387cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002388 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2389 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002391
2392 return( ret );
2393}
2394
2395/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002396 * Pseudo-primality test: small factors, then Miller-Rabin
2397 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002398int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2399 int (*f_rng)(void *, unsigned char *, size_t),
2400 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002401{
2402 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002404 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002405 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002406
2407 XX.s = 1;
2408 XX.n = X->n;
2409 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2412 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2413 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002415 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002416 return( 0 );
2417
2418 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2419 {
2420 if( ret == 1 )
2421 return( 0 );
2422
2423 return( ret );
2424 }
2425
Janos Follathda31fa12018-09-03 14:45:23 +01002426 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002427}
2428
Janos Follatha0b67c22018-09-18 14:48:23 +01002429#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002430/*
2431 * Pseudo-primality test, error probability 2^-80
2432 */
2433int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2434 int (*f_rng)(void *, unsigned char *, size_t),
2435 void *p_rng )
2436{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002437 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002438 MPI_VALIDATE_RET( f_rng != NULL );
2439
Janos Follatha0b67c22018-09-18 14:48:23 +01002440 /*
2441 * In the past our key generation aimed for an error rate of at most
2442 * 2^-80. Since this function is deprecated, aim for the same certainty
2443 * here as well.
2444 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002445 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002446}
Janos Follatha0b67c22018-09-18 14:48:23 +01002447#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002448
2449/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002450 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002451 *
Janos Follathf301d232018-08-14 13:34:01 +01002452 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2453 * be either 1024 bits or 1536 bits long, and flags must contain
2454 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002455 */
Janos Follath7c025a92018-08-14 11:08:41 +01002456int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002457 int (*f_rng)(void *, unsigned char *, size_t),
2458 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002459{
Jethro Beekman66689272018-02-14 19:24:10 -08002460#ifdef MBEDTLS_HAVE_INT64
2461// ceil(2^63.5)
2462#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2463#else
2464// ceil(2^31.5)
2465#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2466#endif
2467 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002468 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002469 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470 mbedtls_mpi_uint r;
2471 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002472
Hanno Becker8ce11a32018-12-19 16:18:52 +00002473 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002474 MPI_VALIDATE_RET( f_rng != NULL );
2475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002476 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002479 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002480
2481 n = BITS_TO_LIMBS( nbits );
2482
Janos Follathda31fa12018-09-03 14:45:23 +01002483 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2484 {
2485 /*
2486 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2487 */
2488 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2489 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2490 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2491 }
2492 else
2493 {
2494 /*
2495 * 2^-100 error probability, number of rounds computed based on HAC,
2496 * fact 4.48
2497 */
2498 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2499 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2500 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2501 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2502 }
2503
Jethro Beekman66689272018-02-14 19:24:10 -08002504 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002505 {
Jethro Beekman66689272018-02-14 19:24:10 -08002506 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2507 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2508 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2509
2510 k = n * biL;
2511 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2512 X->p[0] |= 1;
2513
Janos Follath7c025a92018-08-14 11:08:41 +01002514 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002516 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002518 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002519 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002520 }
Jethro Beekman66689272018-02-14 19:24:10 -08002521 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002522 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002523 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002524 * An necessary condition for Y and X = 2Y + 1 to be prime
2525 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2526 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002527 */
Jethro Beekman66689272018-02-14 19:24:10 -08002528
2529 X->p[0] |= 2;
2530
2531 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2532 if( r == 0 )
2533 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2534 else if( r == 1 )
2535 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2536
2537 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2538 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2539 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2540
2541 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002542 {
Jethro Beekman66689272018-02-14 19:24:10 -08002543 /*
2544 * First, check small factors for X and Y
2545 * before doing Miller-Rabin on any of them
2546 */
2547 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2548 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002549 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002550 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002551 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002552 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002553 goto cleanup;
2554
2555 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2556 goto cleanup;
2557
2558 /*
2559 * Next candidates. We want to preserve Y = (X-1) / 2 and
2560 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2561 * so up Y by 6 and X by 12.
2562 */
2563 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2564 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002565 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002566 }
2567 }
2568
2569cleanup:
2570
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002571 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002572
2573 return( ret );
2574}
2575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002579
Paul Bakker23986e52011-04-24 08:57:21 +00002580#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002581
2582static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2583{
2584 { 693, 609, 21 },
2585 { 1764, 868, 28 },
2586 { 768454923, 542167814, 1 }
2587};
2588
Paul Bakker5121ce52009-01-03 21:22:43 +00002589/*
2590 * Checkup routine
2591 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002593{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002594 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2598 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
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( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002601 "EFE021C2645FD1DC586E69184AF4A31E" \
2602 "D5F53E93B5F123FA41680867BA110131" \
2603 "944FE7952E2517337780CB0DB80E61AA" \
2604 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002607 "B2E7EFD37075B9F03FF989C7C5051C20" \
2608 "34D2A323810251127E7BF8625A4F49A5" \
2609 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2610 "5B5C25763222FEFCCFC38B832366C29E" ) );
2611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002612 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002613 "0066A198186C18C10B2F5ED9B522752A" \
2614 "9830B69916E535C8F047518A889A43A5" \
2615 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002620 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2621 "9E857EA95A03512E2BAE7391688D264A" \
2622 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2623 "8001B72E848A38CAE1C65F78E56ABDEF" \
2624 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2625 "ECF677152EF804370C1A305CAF3B5BF1" \
2626 "30879B56C61DE584A0F53A2447A51E" ) );
2627
2628 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002631 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002632 {
2633 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002635
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002636 ret = 1;
2637 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002638 }
2639
2640 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002641 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002645 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002646 "256567336059E52CAE22925474705F39A94" ) );
2647
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002648 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002649 "6613F26162223DF488E9CD48CC132C7A" \
2650 "0AC93C701B001B092E4E5B9F73BCD27B" \
2651 "9EE50D0657C77F374E903CDFA4C642" ) );
2652
2653 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002656 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2657 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 {
2659 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002661
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002662 ret = 1;
2663 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002664 }
2665
2666 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002672 "36E139AEA55215609D2816998ED020BB" \
2673 "BD96C37890F65171D948E9BC7CBAA4D9" \
2674 "325D24D6A3C12710F10A09FA08AB87" ) );
2675
2676 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002679 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002680 {
2681 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002684 ret = 1;
2685 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002686 }
2687
2688 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002693 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002694 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2695 "C3DBA76456363A10869622EAC2DD84EC" \
2696 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2697
2698 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002699 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002702 {
2703 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002705
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002706 ret = 1;
2707 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002708 }
2709
2710 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002712
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002713 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002714 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002715
Paul Bakker66d5d072014-06-17 16:39:18 +02002716 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002717 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002718 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2719 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002721 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002723 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002724 {
2725 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002726 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002727
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002728 ret = 1;
2729 goto cleanup;
2730 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002731 }
2732
2733 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002734 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002735
Paul Bakker5121ce52009-01-03 21:22:43 +00002736cleanup:
2737
2738 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002739 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002741 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2742 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002743
2744 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002745 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002746
2747 return( ret );
2748}
2749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002750#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002751
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752#endif /* MBEDTLS_BIGNUM_C */