blob: d141a17e44d52c210ce434d21367beeb9b6df503 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
530 * Helper to write the digits high-order first
531 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000533{
534 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536
537 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
541 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
544 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000545
546 if( r < 10 )
547 *(*p)++ = (char)( r + 0x30 );
548 else
549 *(*p)++ = (char)( r + 0x37 );
550
551cleanup:
552
553 return( ret );
554}
555
556/*
557 * Export into an ASCII string
558 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100559int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
560 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000561{
Paul Bakker23986e52011-04-24 08:57:21 +0000562 int ret = 0;
563 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000566 MPI_VALIDATE_RET( X != NULL );
567 MPI_VALIDATE_RET( olen != NULL );
568 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
570 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000571 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000572
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200573 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 if( radix >= 4 ) n >>= 1;
575 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000576 /*
577 * Round up the buffer length to an even value to ensure that there is
578 * enough room for hexadecimal values that can be represented in an odd
579 * number of digits.
580 */
581 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100583 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100585 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 }
588
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100589 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
592 if( X->s == -1 )
593 *p++ = '-';
594
595 if( radix == 16 )
596 {
Paul Bakker23986e52011-04-24 08:57:21 +0000597 int c;
598 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Paul Bakker23986e52011-04-24 08:57:21 +0000600 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 {
Paul Bakker23986e52011-04-24 08:57:21 +0000602 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 {
Paul Bakker23986e52011-04-24 08:57:21 +0000604 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
Paul Bakker6c343d72014-07-10 14:36:19 +0200606 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000607 continue;
608
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000609 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000610 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 k = 1;
612 }
613 }
614 }
615 else
616 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000618
619 if( T.s == -1 )
620 T.s = 1;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 }
624
625 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100626 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
628cleanup:
629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 return( ret );
633}
634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000636/*
637 * Read X from an opened file
638 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000640{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000642 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000644 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000645 * Buffer should have space for (short) label and decimal formatted MPI,
646 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000647 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
Hanno Becker73d7d792018-12-11 10:35:51 +0000650 MPI_VALIDATE_RET( X != NULL );
651 MPI_VALIDATE_RET( fin != NULL );
652
653 if( radix < 2 || radix > 16 )
654 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
655
Paul Bakker5121ce52009-01-03 21:22:43 +0000656 memset( s, 0, sizeof( s ) );
657 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
660 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000661 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000663
Hanno Beckerb2034b72017-04-26 11:46:46 +0100664 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
665 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
667 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100668 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 if( mpi_get_digit( &d, radix, *p ) != 0 )
670 break;
671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673}
674
675/*
676 * Write X into an opened file (or stdout if fout == NULL)
677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000679{
Paul Bakker23986e52011-04-24 08:57:21 +0000680 int ret;
681 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000682 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000683 * Buffer should have space for (short) label and decimal formatted MPI,
684 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000685 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000687 MPI_VALIDATE_RET( X != NULL );
688
689 if( radix < 2 || radix > 16 )
690 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100692 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100694 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
696 if( p == NULL ) p = "";
697
698 plen = strlen( p );
699 slen = strlen( s );
700 s[slen++] = '\r';
701 s[slen++] = '\n';
702
703 if( fout != NULL )
704 {
705 if( fwrite( p, 1, plen, fout ) != plen ||
706 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000708 }
709 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
712cleanup:
713
714 return( ret );
715}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000717
Hanno Beckerda1655a2017-10-18 14:21:44 +0100718
719/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
720 * into the storage form used by mbedtls_mpi. */
721static int mpi_bigendian_to_host( unsigned char * const buf, size_t size )
722{
723 mbedtls_mpi_uint * const p = (mbedtls_mpi_uint *) buf;
724 size_t const limbs = size / ciL;
725 size_t i;
726
727 unsigned char *cur_byte_left;
728 unsigned char *cur_byte_right;
729
730 mbedtls_mpi_uint *cur_limb_left;
731 mbedtls_mpi_uint *cur_limb_right;
732
733 mbedtls_mpi_uint tmp_left, tmp_right;
734
735 if( size % ciL != 0 || limbs == 0 )
736 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
737
738 /*
739 * Traverse limbs and
740 * - adapt byte-order in each limb
741 * - swap the limbs themselves.
742 * For that, simultaneously traverse the limbs from left to right
743 * and from right to left, as long as the left index is not bigger
744 * than the right index (it's not a problem if limbs is odd and the
745 * indices coincide in the last iteration).
746 */
747
748 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
749 cur_limb_left <= cur_limb_right;
750 cur_limb_left++, cur_limb_right-- )
751 {
752 cur_byte_left = (unsigned char*) cur_limb_left;
753 cur_byte_right = (unsigned char*) cur_limb_right;
754
755 tmp_left = 0;
756 tmp_right = 0;
757
758 for( i = 0; i < ciL; i++ )
759 {
760 tmp_left |= ( (mbedtls_mpi_uint) *cur_byte_left++ )
761 << ( ( ciL - 1 - i ) << 3 );
762 tmp_right |= ( (mbedtls_mpi_uint) *cur_byte_right++ )
763 << ( ( ciL - 1 - i ) << 3 );
764 }
765
766 *cur_limb_right = tmp_left;
767 *cur_limb_left = tmp_right;
768 }
769
770 return( 0 );
771}
772
Paul Bakker5121ce52009-01-03 21:22:43 +0000773/*
774 * Import X from unsigned binary data, big endian
775 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000777{
Paul Bakker23986e52011-04-24 08:57:21 +0000778 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100779 size_t const limbs = CHARS_TO_LIMBS( buflen );
780 size_t const overhead = ( limbs * ciL ) - buflen;
781 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000782
Hanno Becker8ce11a32018-12-19 16:18:52 +0000783 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000784 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
785
Hanno Becker073c1992017-10-17 15:17:27 +0100786 /* Ensure that target MPI has exactly the necessary number of limbs */
787 if( X->n != limbs )
788 {
789 mbedtls_mpi_free( X );
790 mbedtls_mpi_init( X );
791 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
792 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200793 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000794
Hanno Beckerda1655a2017-10-18 14:21:44 +0100795 Xp = (unsigned char*) X->p;
796 memcpy( Xp + overhead, buf, buflen );
797
798 MBEDTLS_MPI_CHK( mpi_bigendian_to_host( Xp, limbs * ciL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000799
800cleanup:
801
802 return( ret );
803}
804
805/*
806 * Export X into unsigned binary data, big endian
807 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100808int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
809 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000810{
Hanno Becker73d7d792018-12-11 10:35:51 +0000811 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100812 size_t bytes_to_copy;
813 unsigned char *p;
814 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000815
Hanno Becker73d7d792018-12-11 10:35:51 +0000816 MPI_VALIDATE_RET( X != NULL );
817 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
818
819 stored_bytes = X->n * ciL;
820
Gilles Peskine11cdb052018-11-20 16:47:47 +0100821 if( stored_bytes < buflen )
822 {
823 /* There is enough space in the output buffer. Write initial
824 * null bytes and record the position at which to start
825 * writing the significant bytes. In this case, the execution
826 * trace of this function does not depend on the value of the
827 * number. */
828 bytes_to_copy = stored_bytes;
829 p = buf + buflen - stored_bytes;
830 memset( buf, 0, buflen - stored_bytes );
831 }
832 else
833 {
834 /* The output buffer is smaller than the allocated size of X.
835 * However X may fit if its leading bytes are zero. */
836 bytes_to_copy = buflen;
837 p = buf;
838 for( i = bytes_to_copy; i < stored_bytes; i++ )
839 {
840 if( GET_BYTE( X, i ) != 0 )
841 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
842 }
843 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000844
Gilles Peskine11cdb052018-11-20 16:47:47 +0100845 for( i = 0; i < bytes_to_copy; i++ )
846 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000847
848 return( 0 );
849}
850
851/*
852 * Left-shift: X <<= count
853 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000855{
Paul Bakker23986e52011-04-24 08:57:21 +0000856 int ret;
857 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000859 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000860
861 v0 = count / (biL );
862 t1 = count & (biL - 1);
863
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200864 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000865
Paul Bakkerf9688572011-05-05 10:00:45 +0000866 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000868
869 ret = 0;
870
871 /*
872 * shift by count / limb_size
873 */
874 if( v0 > 0 )
875 {
Paul Bakker23986e52011-04-24 08:57:21 +0000876 for( i = X->n; i > v0; i-- )
877 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000878
Paul Bakker23986e52011-04-24 08:57:21 +0000879 for( ; i > 0; i-- )
880 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000881 }
882
883 /*
884 * shift by count % limb_size
885 */
886 if( t1 > 0 )
887 {
888 for( i = v0; i < X->n; i++ )
889 {
890 r1 = X->p[i] >> (biL - t1);
891 X->p[i] <<= t1;
892 X->p[i] |= r0;
893 r0 = r1;
894 }
895 }
896
897cleanup:
898
899 return( ret );
900}
901
902/*
903 * Right-shift: X >>= count
904 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000906{
Paul Bakker23986e52011-04-24 08:57:21 +0000907 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000909 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000910
911 v0 = count / biL;
912 v1 = count & (biL - 1);
913
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100914 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100916
Paul Bakker5121ce52009-01-03 21:22:43 +0000917 /*
918 * shift by count / limb_size
919 */
920 if( v0 > 0 )
921 {
922 for( i = 0; i < X->n - v0; i++ )
923 X->p[i] = X->p[i + v0];
924
925 for( ; i < X->n; i++ )
926 X->p[i] = 0;
927 }
928
929 /*
930 * shift by count % limb_size
931 */
932 if( v1 > 0 )
933 {
Paul Bakker23986e52011-04-24 08:57:21 +0000934 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000935 {
Paul Bakker23986e52011-04-24 08:57:21 +0000936 r1 = X->p[i - 1] << (biL - v1);
937 X->p[i - 1] >>= v1;
938 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 r0 = r1;
940 }
941 }
942
943 return( 0 );
944}
945
946/*
947 * Compare unsigned values
948 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000950{
Paul Bakker23986e52011-04-24 08:57:21 +0000951 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000952 MPI_VALIDATE_RET( X != NULL );
953 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000954
Paul Bakker23986e52011-04-24 08:57:21 +0000955 for( i = X->n; i > 0; i-- )
956 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000957 break;
958
Paul Bakker23986e52011-04-24 08:57:21 +0000959 for( j = Y->n; j > 0; j-- )
960 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000961 break;
962
Paul Bakker23986e52011-04-24 08:57:21 +0000963 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000964 return( 0 );
965
966 if( i > j ) return( 1 );
967 if( j > i ) return( -1 );
968
Paul Bakker23986e52011-04-24 08:57:21 +0000969 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 {
Paul Bakker23986e52011-04-24 08:57:21 +0000971 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
972 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000973 }
974
975 return( 0 );
976}
977
978/*
979 * Compare signed values
980 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000982{
Paul Bakker23986e52011-04-24 08:57:21 +0000983 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000984 MPI_VALIDATE_RET( X != NULL );
985 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000986
Paul Bakker23986e52011-04-24 08:57:21 +0000987 for( i = X->n; i > 0; i-- )
988 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000989 break;
990
Paul Bakker23986e52011-04-24 08:57:21 +0000991 for( j = Y->n; j > 0; j-- )
992 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 break;
994
Paul Bakker23986e52011-04-24 08:57:21 +0000995 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000996 return( 0 );
997
998 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000999 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
1001 if( X->s > 0 && Y->s < 0 ) return( 1 );
1002 if( Y->s > 0 && X->s < 0 ) return( -1 );
1003
Paul Bakker23986e52011-04-24 08:57:21 +00001004 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001005 {
Paul Bakker23986e52011-04-24 08:57:21 +00001006 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1007 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001008 }
1009
1010 return( 0 );
1011}
1012
1013/*
1014 * Compare signed values
1015 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001017{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018 mbedtls_mpi Y;
1019 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001020 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021
1022 *p = ( z < 0 ) ? -z : z;
1023 Y.s = ( z < 0 ) ? -1 : 1;
1024 Y.n = 1;
1025 Y.p = p;
1026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001027 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001028}
1029
1030/*
1031 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1032 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001034{
Paul Bakker23986e52011-04-24 08:57:21 +00001035 int ret;
1036 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001037 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001038 MPI_VALIDATE_RET( X != NULL );
1039 MPI_VALIDATE_RET( A != NULL );
1040 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001041
1042 if( X == B )
1043 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001045 }
1046
1047 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001049
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001050 /*
1051 * X should always be positive as a result of unsigned additions.
1052 */
1053 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
Paul Bakker23986e52011-04-24 08:57:21 +00001055 for( j = B->n; j > 0; j-- )
1056 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 break;
1058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001059 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001060
1061 o = B->p; p = X->p; c = 0;
1062
Janos Follath6c922682015-10-30 17:43:11 +01001063 /*
1064 * tmp is used because it might happen that p == o
1065 */
Paul Bakker23986e52011-04-24 08:57:21 +00001066 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001067 {
Janos Follath6c922682015-10-30 17:43:11 +01001068 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001070 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001071 }
1072
1073 while( c != 0 )
1074 {
1075 if( i >= X->n )
1076 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001077 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001078 p = X->p + i;
1079 }
1080
Paul Bakker2d319fd2012-09-16 21:34:26 +00001081 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 }
1083
1084cleanup:
1085
1086 return( ret );
1087}
1088
1089/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001091 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001093{
Paul Bakker23986e52011-04-24 08:57:21 +00001094 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001096
1097 for( i = c = 0; i < n; i++, s++, d++ )
1098 {
1099 z = ( *d < c ); *d -= c;
1100 c = ( *d < *s ) + z; *d -= *s;
1101 }
1102
1103 while( c != 0 )
1104 {
1105 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001106 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001107 }
1108}
1109
1110/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001111 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001112 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001114{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001116 int ret;
1117 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001118 MPI_VALIDATE_RET( X != NULL );
1119 MPI_VALIDATE_RET( A != NULL );
1120 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1123 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126
1127 if( X == B )
1128 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 B = &TB;
1131 }
1132
1133 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001134 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001135
Paul Bakker1ef7a532009-06-20 10:50:55 +00001136 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001137 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001138 */
1139 X->s = 1;
1140
Paul Bakker5121ce52009-01-03 21:22:43 +00001141 ret = 0;
1142
Paul Bakker23986e52011-04-24 08:57:21 +00001143 for( n = B->n; n > 0; n-- )
1144 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001145 break;
1146
Paul Bakker23986e52011-04-24 08:57:21 +00001147 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
1149cleanup:
1150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
1153 return( ret );
1154}
1155
1156/*
1157 * Signed addition: X = A + B
1158 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001159int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001160{
Hanno Becker73d7d792018-12-11 10:35:51 +00001161 int ret, s;
1162 MPI_VALIDATE_RET( X != NULL );
1163 MPI_VALIDATE_RET( A != NULL );
1164 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001165
Hanno Becker73d7d792018-12-11 10:35:51 +00001166 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001167 if( A->s * B->s < 0 )
1168 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001170 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001171 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 X->s = s;
1173 }
1174 else
1175 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001176 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 X->s = -s;
1178 }
1179 }
1180 else
1181 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183 X->s = s;
1184 }
1185
1186cleanup:
1187
1188 return( ret );
1189}
1190
1191/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001192 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001193 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001194int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001195{
Hanno Becker73d7d792018-12-11 10:35:51 +00001196 int ret, s;
1197 MPI_VALIDATE_RET( X != NULL );
1198 MPI_VALIDATE_RET( A != NULL );
1199 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001200
Hanno Becker73d7d792018-12-11 10:35:51 +00001201 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 if( A->s * B->s > 0 )
1203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001204 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001205 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 X->s = s;
1208 }
1209 else
1210 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001212 X->s = -s;
1213 }
1214 }
1215 else
1216 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001218 X->s = s;
1219 }
1220
1221cleanup:
1222
1223 return( ret );
1224}
1225
1226/*
1227 * Signed addition: X = A + b
1228 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001230{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001231 mbedtls_mpi _B;
1232 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001233 MPI_VALIDATE_RET( X != NULL );
1234 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001235
1236 p[0] = ( b < 0 ) ? -b : b;
1237 _B.s = ( b < 0 ) ? -1 : 1;
1238 _B.n = 1;
1239 _B.p = p;
1240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001242}
1243
1244/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001245 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001248{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249 mbedtls_mpi _B;
1250 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001251 MPI_VALIDATE_RET( X != NULL );
1252 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001253
1254 p[0] = ( b < 0 ) ? -b : b;
1255 _B.s = ( b < 0 ) ? -1 : 1;
1256 _B.n = 1;
1257 _B.p = p;
1258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001260}
1261
1262/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001263 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001264 */
1265static
1266#if defined(__APPLE__) && defined(__arm__)
1267/*
1268 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1269 * appears to need this to prevent bad ARM code generation at -O3.
1270 */
1271__attribute__ ((noinline))
1272#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273void 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 +00001274{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001276
1277#if defined(MULADDC_HUIT)
1278 for( ; i >= 8; i -= 8 )
1279 {
1280 MULADDC_INIT
1281 MULADDC_HUIT
1282 MULADDC_STOP
1283 }
1284
1285 for( ; i > 0; i-- )
1286 {
1287 MULADDC_INIT
1288 MULADDC_CORE
1289 MULADDC_STOP
1290 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001291#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001292 for( ; i >= 16; i -= 16 )
1293 {
1294 MULADDC_INIT
1295 MULADDC_CORE MULADDC_CORE
1296 MULADDC_CORE MULADDC_CORE
1297 MULADDC_CORE MULADDC_CORE
1298 MULADDC_CORE MULADDC_CORE
1299
1300 MULADDC_CORE MULADDC_CORE
1301 MULADDC_CORE MULADDC_CORE
1302 MULADDC_CORE MULADDC_CORE
1303 MULADDC_CORE MULADDC_CORE
1304 MULADDC_STOP
1305 }
1306
1307 for( ; i >= 8; i -= 8 )
1308 {
1309 MULADDC_INIT
1310 MULADDC_CORE MULADDC_CORE
1311 MULADDC_CORE MULADDC_CORE
1312
1313 MULADDC_CORE MULADDC_CORE
1314 MULADDC_CORE MULADDC_CORE
1315 MULADDC_STOP
1316 }
1317
1318 for( ; i > 0; i-- )
1319 {
1320 MULADDC_INIT
1321 MULADDC_CORE
1322 MULADDC_STOP
1323 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001324#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001325
1326 t++;
1327
1328 do {
1329 *d += c; c = ( *d < c ); d++;
1330 }
1331 while( c != 0 );
1332}
1333
1334/*
1335 * Baseline multiplication: X = A * B (HAC 14.12)
1336 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001338{
Paul Bakker23986e52011-04-24 08:57:21 +00001339 int ret;
1340 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001342 MPI_VALIDATE_RET( X != NULL );
1343 MPI_VALIDATE_RET( A != NULL );
1344 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001348 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1349 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001350
Paul Bakker23986e52011-04-24 08:57:21 +00001351 for( i = A->n; i > 0; i-- )
1352 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001353 break;
1354
Paul Bakker23986e52011-04-24 08:57:21 +00001355 for( j = B->n; j > 0; j-- )
1356 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001357 break;
1358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1360 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001362 for( ; j > 0; j-- )
1363 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001364
1365 X->s = A->s * B->s;
1366
1367cleanup:
1368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001370
1371 return( ret );
1372}
1373
1374/*
1375 * Baseline multiplication: X = A * b
1376 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001378{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 mbedtls_mpi _B;
1380 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001381 MPI_VALIDATE_RET( X != NULL );
1382 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383
1384 _B.s = 1;
1385 _B.n = 1;
1386 _B.p = p;
1387 p[0] = b;
1388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001390}
1391
1392/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001393 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1394 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001395 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001396static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1397 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001398{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001399#if defined(MBEDTLS_HAVE_UDBL)
1400 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001401#else
Simon Butcher9803d072016-01-03 00:24:34 +00001402 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1403 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001404 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1405 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001406 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001407#endif
1408
Simon Butcher15b15d12015-11-26 19:35:03 +00001409 /*
1410 * Check for overflow
1411 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001412 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001413 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001414 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001415
Simon Butcherf5ba0452015-12-27 23:01:55 +00001416 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001417 }
1418
1419#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001420 dividend = (mbedtls_t_udbl) u1 << biL;
1421 dividend |= (mbedtls_t_udbl) u0;
1422 quotient = dividend / d;
1423 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1424 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1425
1426 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001427 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001428
1429 return (mbedtls_mpi_uint) quotient;
1430#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001431
1432 /*
1433 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1434 * Vol. 2 - Seminumerical Algorithms, Knuth
1435 */
1436
1437 /*
1438 * Normalize the divisor, d, and dividend, u0, u1
1439 */
1440 s = mbedtls_clz( d );
1441 d = d << s;
1442
1443 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001444 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001445 u0 = u0 << s;
1446
1447 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001448 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001449
1450 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001451 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001452
1453 /*
1454 * Find the first quotient and remainder
1455 */
1456 q1 = u1 / d1;
1457 r0 = u1 - d1 * q1;
1458
1459 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1460 {
1461 q1 -= 1;
1462 r0 += d1;
1463
1464 if ( r0 >= radix ) break;
1465 }
1466
Simon Butcherf5ba0452015-12-27 23:01:55 +00001467 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001468 q0 = rAX / d1;
1469 r0 = rAX - q0 * d1;
1470
1471 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1472 {
1473 q0 -= 1;
1474 r0 += d1;
1475
1476 if ( r0 >= radix ) break;
1477 }
1478
1479 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001480 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001481
1482 quotient = q1 * radix + q0;
1483
1484 return quotient;
1485#endif
1486}
1487
1488/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001489 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001490 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001491int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1492 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001493{
Paul Bakker23986e52011-04-24 08:57:21 +00001494 int ret;
1495 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001497 MPI_VALIDATE_RET( A != NULL );
1498 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001500 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1501 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1504 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001507 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001508 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1509 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510 return( 0 );
1511 }
1512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1514 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001515 X.s = Y.s = 1;
1516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1518 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1519 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1520 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001522 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001523 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001524 {
1525 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001526 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1527 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001528 }
1529 else k = 0;
1530
1531 n = X.n - 1;
1532 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001535 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001536 {
1537 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001539 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
1542 for( i = n; i > t ; i-- )
1543 {
1544 if( X.p[i] >= Y.p[t] )
1545 Z.p[i - t - 1] = ~0;
1546 else
1547 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001548 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1549 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001550 }
1551
1552 Z.p[i - t - 1]++;
1553 do
1554 {
1555 Z.p[i - t - 1]--;
1556
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001557 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001558 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001559 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001563 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1564 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001565 T2.p[2] = X.p[i];
1566 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1570 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1571 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001574 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001575 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1576 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1577 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001578 Z.p[i - t - 1]--;
1579 }
1580 }
1581
1582 if( Q != NULL )
1583 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 Q->s = A->s * B->s;
1586 }
1587
1588 if( R != NULL )
1589 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001591 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001595 R->s = 1;
1596 }
1597
1598cleanup:
1599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001600 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1601 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001602
1603 return( ret );
1604}
1605
1606/*
1607 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001608 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001609int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1610 const mbedtls_mpi *A,
1611 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001612{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001613 mbedtls_mpi _B;
1614 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001615 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001616
1617 p[0] = ( b < 0 ) ? -b : b;
1618 _B.s = ( b < 0 ) ? -1 : 1;
1619 _B.n = 1;
1620 _B.p = p;
1621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001623}
1624
1625/*
1626 * Modulo: R = A mod B
1627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001629{
1630 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001631 MPI_VALIDATE_RET( R != NULL );
1632 MPI_VALIDATE_RET( A != NULL );
1633 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1636 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1641 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001643 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1644 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001645
1646cleanup:
1647
1648 return( ret );
1649}
1650
1651/*
1652 * Modulo: r = A mod b
1653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001655{
Paul Bakker23986e52011-04-24 08:57:21 +00001656 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001658 MPI_VALIDATE_RET( r != NULL );
1659 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001660
1661 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
1664 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
1667 /*
1668 * handle trivial cases
1669 */
1670 if( b == 1 )
1671 {
1672 *r = 0;
1673 return( 0 );
1674 }
1675
1676 if( b == 2 )
1677 {
1678 *r = A->p[0] & 1;
1679 return( 0 );
1680 }
1681
1682 /*
1683 * general case
1684 */
Paul Bakker23986e52011-04-24 08:57:21 +00001685 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 {
Paul Bakker23986e52011-04-24 08:57:21 +00001687 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001688 y = ( y << biH ) | ( x >> biH );
1689 z = y / b;
1690 y -= z * b;
1691
1692 x <<= biH;
1693 y = ( y << biH ) | ( x >> biH );
1694 z = y / b;
1695 y -= z * b;
1696 }
1697
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001698 /*
1699 * If A is negative, then the current y represents a negative value.
1700 * Flipping it to the positive side.
1701 */
1702 if( A->s < 0 && y != 0 )
1703 y = b - y;
1704
Paul Bakker5121ce52009-01-03 21:22:43 +00001705 *r = y;
1706
1707 return( 0 );
1708}
1709
1710/*
1711 * Fast Montgomery initialization (thanks to Tom St Denis)
1712 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001713static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001714{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001716 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001717
1718 x = m0;
1719 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001720
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001721 for( i = biL; i >= 8; i /= 2 )
1722 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
1724 *mm = ~x + 1;
1725}
1726
1727/*
1728 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1729 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001730static 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 +02001731 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001732{
Paul Bakker23986e52011-04-24 08:57:21 +00001733 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001735
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001736 if( T->n < N->n + 1 || T->p == NULL )
1737 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1738
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 memset( T->p, 0, T->n * ciL );
1740
1741 d = T->p;
1742 n = N->n;
1743 m = ( B->n < n ) ? B->n : n;
1744
1745 for( i = 0; i < n; i++ )
1746 {
1747 /*
1748 * T = (T + u0*B + u1*N) / 2^biL
1749 */
1750 u0 = A->p[i];
1751 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1752
1753 mpi_mul_hlp( m, B->p, d, u0 );
1754 mpi_mul_hlp( n, N->p, d, u1 );
1755
1756 *d++ = u0; d[n + 1] = 0;
1757 }
1758
Paul Bakker66d5d072014-06-17 16:39:18 +02001759 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001762 mpi_sub_hlp( n, N->p, A->p );
1763 else
1764 /* prevent timing attacks */
1765 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001766
1767 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001768}
1769
1770/*
1771 * Montgomery reduction: A = A * R^-1 mod N
1772 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001773static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1774 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001775{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 mbedtls_mpi_uint z = 1;
1777 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
Paul Bakker8ddb6452013-02-27 14:56:33 +01001779 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001780 U.p = &z;
1781
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001782 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001783}
1784
1785/*
1786 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1787 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001788int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1789 const mbedtls_mpi *E, const mbedtls_mpi *N,
1790 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001791{
Paul Bakker23986e52011-04-24 08:57:21 +00001792 int ret;
1793 size_t wbits, wsize, one = 1;
1794 size_t i, j, nblimbs;
1795 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001796 mbedtls_mpi_uint ei, mm, state;
1797 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001798 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001799
Hanno Becker73d7d792018-12-11 10:35:51 +00001800 MPI_VALIDATE_RET( X != NULL );
1801 MPI_VALIDATE_RET( A != NULL );
1802 MPI_VALIDATE_RET( E != NULL );
1803 MPI_VALIDATE_RET( N != NULL );
1804
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001805 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1809 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001810
1811 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001812 * Init temps and window size
1813 */
1814 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1816 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817 memset( W, 0, sizeof( W ) );
1818
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001819 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001820
1821 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1822 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1825 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001826
Paul Bakker5121ce52009-01-03 21:22:43 +00001827 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1829 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1830 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
1832 /*
Paul Bakker50546922012-05-19 08:40:49 +00001833 * Compensate for negative A (and correct at the end)
1834 */
1835 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001836 if( neg )
1837 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001839 Apos.s = 1;
1840 A = &Apos;
1841 }
1842
1843 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001844 * If 1st call, pre-compute R^2 mod N
1845 */
1846 if( _RR == NULL || _RR->p == NULL )
1847 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1849 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1850 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001851
1852 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001854 }
1855 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001857
1858 /*
1859 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1860 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1862 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001863 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001865
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001866 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
1868 /*
1869 * X = R^2 * R^-1 mod N = R mod N
1870 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001872 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001873
1874 if( wsize > 1 )
1875 {
1876 /*
1877 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1878 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001879 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001880
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001881 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1882 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001883
1884 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001885 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001886
Paul Bakker5121ce52009-01-03 21:22:43 +00001887 /*
1888 * W[i] = W[i - 1] * W[1]
1889 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001890 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001891 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1893 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001895 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001896 }
1897 }
1898
1899 nblimbs = E->n;
1900 bufsize = 0;
1901 nbits = 0;
1902 wbits = 0;
1903 state = 0;
1904
1905 while( 1 )
1906 {
1907 if( bufsize == 0 )
1908 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001909 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001910 break;
1911
Paul Bakker0d7702c2013-10-29 16:18:35 +01001912 nblimbs--;
1913
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001914 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001915 }
1916
1917 bufsize--;
1918
1919 ei = (E->p[nblimbs] >> bufsize) & 1;
1920
1921 /*
1922 * skip leading 0s
1923 */
1924 if( ei == 0 && state == 0 )
1925 continue;
1926
1927 if( ei == 0 && state == 1 )
1928 {
1929 /*
1930 * out of window, square X
1931 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001932 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933 continue;
1934 }
1935
1936 /*
1937 * add ei to current window
1938 */
1939 state = 2;
1940
1941 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001942 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
1944 if( nbits == wsize )
1945 {
1946 /*
1947 * X = X^wsize R^-1 mod N
1948 */
1949 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001950 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001951
1952 /*
1953 * X = X * W[wbits] R^-1 mod N
1954 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001955 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
1957 state--;
1958 nbits = 0;
1959 wbits = 0;
1960 }
1961 }
1962
1963 /*
1964 * process the remaining bits
1965 */
1966 for( i = 0; i < nbits; i++ )
1967 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001968 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 wbits <<= 1;
1971
Paul Bakker66d5d072014-06-17 16:39:18 +02001972 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001973 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 }
1975
1976 /*
1977 * X = A^E * R * R^-1 mod N = A^E mod N
1978 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001979 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001980
Hanno Beckera4af1c42017-04-18 09:07:45 +01001981 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001982 {
1983 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001985 }
1986
Paul Bakker5121ce52009-01-03 21:22:43 +00001987cleanup:
1988
Paul Bakker66d5d072014-06-17 16:39:18 +02001989 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001993
Paul Bakker75a28602014-03-31 12:08:17 +02001994 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996
1997 return( ret );
1998}
1999
Paul Bakker5121ce52009-01-03 21:22:43 +00002000/*
2001 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2002 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002003int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002004{
Paul Bakker23986e52011-04-24 08:57:21 +00002005 int ret;
2006 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
Hanno Becker73d7d792018-12-11 10:35:51 +00002009 MPI_VALIDATE_RET( G != NULL );
2010 MPI_VALIDATE_RET( A != NULL );
2011 MPI_VALIDATE_RET( B != NULL );
2012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2016 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 lz = mbedtls_mpi_lsb( &TA );
2019 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002020
Paul Bakker66d5d072014-06-17 16:39:18 +02002021 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002022 lz = lzt;
2023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2025 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002026
Paul Bakker5121ce52009-01-03 21:22:43 +00002027 TA.s = TB.s = 1;
2028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002030 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2032 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002035 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2037 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002038 }
2039 else
2040 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2042 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002043 }
2044 }
2045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2047 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002048
2049cleanup:
2050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002052
2053 return( ret );
2054}
2055
Paul Bakker33dc46b2014-04-30 16:11:39 +02002056/*
2057 * Fill X with size bytes of random.
2058 *
2059 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002060 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002061 * deterministic, eg for tests).
2062 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002064 int (*f_rng)(void *, unsigned char *, size_t),
2065 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002066{
Paul Bakker23986e52011-04-24 08:57:21 +00002067 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +01002068 size_t const limbs CHARS_TO_LIMBS( size );
2069 size_t const overhead = ( limbs * ciL ) - size;
2070 unsigned char *Xp;
2071
Hanno Becker8ce11a32018-12-19 16:18:52 +00002072 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002073 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002074
Hanno Beckerda1655a2017-10-18 14:21:44 +01002075 /* Ensure that target MPI has exactly the necessary number of limbs */
2076 if( X->n != limbs )
2077 {
2078 mbedtls_mpi_free( X );
2079 mbedtls_mpi_init( X );
2080 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2081 }
2082 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002083
Hanno Beckerda1655a2017-10-18 14:21:44 +01002084 Xp = (unsigned char*) X->p;
2085 f_rng( p_rng, Xp + overhead, size );
2086
2087 MBEDTLS_MPI_CHK( mpi_bigendian_to_host( Xp, limbs * ciL ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002088
2089cleanup:
2090 return( ret );
2091}
2092
Paul Bakker5121ce52009-01-03 21:22:43 +00002093/*
2094 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002097{
2098 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002100 MPI_VALIDATE_RET( X != NULL );
2101 MPI_VALIDATE_RET( A != NULL );
2102 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002103
Hanno Becker4bcb4912017-04-18 15:49:39 +01002104 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2108 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2109 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002114 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002116 goto cleanup;
2117 }
2118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2120 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2121 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2122 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2125 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2126 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2127 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002128
2129 do
2130 {
2131 while( ( TU.p[0] & 1 ) == 0 )
2132 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002133 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002134
2135 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2136 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002137 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2138 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002139 }
2140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2142 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002143 }
2144
2145 while( ( TV.p[0] & 1 ) == 0 )
2146 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002148
2149 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2150 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2152 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002153 }
2154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2156 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002157 }
2158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002160 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2162 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2163 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002164 }
2165 else
2166 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2168 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2169 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 }
2171 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2175 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2178 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
2182cleanup:
2183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2185 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2186 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002187
2188 return( ret );
2189}
2190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002192
Paul Bakker5121ce52009-01-03 21:22:43 +00002193static const int small_prime[] =
2194{
2195 3, 5, 7, 11, 13, 17, 19, 23,
2196 29, 31, 37, 41, 43, 47, 53, 59,
2197 61, 67, 71, 73, 79, 83, 89, 97,
2198 101, 103, 107, 109, 113, 127, 131, 137,
2199 139, 149, 151, 157, 163, 167, 173, 179,
2200 181, 191, 193, 197, 199, 211, 223, 227,
2201 229, 233, 239, 241, 251, 257, 263, 269,
2202 271, 277, 281, 283, 293, 307, 311, 313,
2203 317, 331, 337, 347, 349, 353, 359, 367,
2204 373, 379, 383, 389, 397, 401, 409, 419,
2205 421, 431, 433, 439, 443, 449, 457, 461,
2206 463, 467, 479, 487, 491, 499, 503, 509,
2207 521, 523, 541, 547, 557, 563, 569, 571,
2208 577, 587, 593, 599, 601, 607, 613, 617,
2209 619, 631, 641, 643, 647, 653, 659, 661,
2210 673, 677, 683, 691, 701, 709, 719, 727,
2211 733, 739, 743, 751, 757, 761, 769, 773,
2212 787, 797, 809, 811, 821, 823, 827, 829,
2213 839, 853, 857, 859, 863, 877, 881, 883,
2214 887, 907, 911, 919, 929, 937, 941, 947,
2215 953, 967, 971, 977, 983, 991, 997, -103
2216};
2217
2218/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002219 * Small divisors test (X must be positive)
2220 *
2221 * Return values:
2222 * 0: no small factor (possible prime, more tests needed)
2223 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002225 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002226 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002228{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002229 int ret = 0;
2230 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002232
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002235
2236 for( i = 0; small_prime[i] > 0; i++ )
2237 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002239 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002241 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
2243 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002245 }
2246
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002247cleanup:
2248 return( ret );
2249}
2250
2251/*
2252 * Miller-Rabin pseudo-primality test (HAC 4.24)
2253 */
Janos Follathda31fa12018-09-03 14:45:23 +01002254static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002255 int (*f_rng)(void *, unsigned char *, size_t),
2256 void *p_rng )
2257{
Pascal Junodb99183d2015-03-11 16:49:45 +01002258 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002259 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002261
Hanno Becker8ce11a32018-12-19 16:18:52 +00002262 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002263 MPI_VALIDATE_RET( f_rng != NULL );
2264
2265 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2266 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002268
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 /*
2270 * W = |X| - 1
2271 * R = W >> lsb( W )
2272 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2274 s = mbedtls_mpi_lsb( &W );
2275 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2276 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002277
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002278 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002279
Janos Follathda31fa12018-09-03 14:45:23 +01002280 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 {
2282 /*
2283 * pick a random A, 1 < A < |X| - 1
2284 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002285 count = 0;
2286 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002287 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002288
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002289 j = mbedtls_mpi_bitlen( &A );
2290 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002291 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002292 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002293 }
2294
2295 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002296 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002297 }
2298
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002299 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2300 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002301
2302 /*
2303 * A = A^R mod |X|
2304 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2308 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002309 continue;
2310
2311 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002313 {
2314 /*
2315 * A = A * A mod |X|
2316 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002317 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2318 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002321 break;
2322
2323 j++;
2324 }
2325
2326 /*
2327 * not prime if A != |X| - 1 or A == 1
2328 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2330 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 break;
2334 }
2335 }
2336
2337cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002338 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2339 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002341
2342 return( ret );
2343}
2344
2345/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002346 * Pseudo-primality test: small factors, then Miller-Rabin
2347 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002348int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2349 int (*f_rng)(void *, unsigned char *, size_t),
2350 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002351{
2352 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002354 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002355 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002356
2357 XX.s = 1;
2358 XX.n = X->n;
2359 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2362 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2363 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002366 return( 0 );
2367
2368 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2369 {
2370 if( ret == 1 )
2371 return( 0 );
2372
2373 return( ret );
2374 }
2375
Janos Follathda31fa12018-09-03 14:45:23 +01002376 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002377}
2378
Janos Follatha0b67c22018-09-18 14:48:23 +01002379#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002380/*
2381 * Pseudo-primality test, error probability 2^-80
2382 */
2383int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2384 int (*f_rng)(void *, unsigned char *, size_t),
2385 void *p_rng )
2386{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002387 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002388 MPI_VALIDATE_RET( f_rng != NULL );
2389
Janos Follatha0b67c22018-09-18 14:48:23 +01002390 /*
2391 * In the past our key generation aimed for an error rate of at most
2392 * 2^-80. Since this function is deprecated, aim for the same certainty
2393 * here as well.
2394 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002395 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002396}
Janos Follatha0b67c22018-09-18 14:48:23 +01002397#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002398
2399/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002401 *
Janos Follathf301d232018-08-14 13:34:01 +01002402 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2403 * be either 1024 bits or 1536 bits long, and flags must contain
2404 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 */
Janos Follath7c025a92018-08-14 11:08:41 +01002406int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002407 int (*f_rng)(void *, unsigned char *, size_t),
2408 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002409{
Jethro Beekman66689272018-02-14 19:24:10 -08002410#ifdef MBEDTLS_HAVE_INT64
2411// ceil(2^63.5)
2412#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2413#else
2414// ceil(2^31.5)
2415#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2416#endif
2417 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002418 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002419 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 mbedtls_mpi_uint r;
2421 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002422
Hanno Becker8ce11a32018-12-19 16:18:52 +00002423 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002424 MPI_VALIDATE_RET( f_rng != NULL );
2425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2427 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002429 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
2431 n = BITS_TO_LIMBS( nbits );
2432
Janos Follathda31fa12018-09-03 14:45:23 +01002433 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2434 {
2435 /*
2436 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2437 */
2438 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2439 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2440 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2441 }
2442 else
2443 {
2444 /*
2445 * 2^-100 error probability, number of rounds computed based on HAC,
2446 * fact 4.48
2447 */
2448 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2449 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2450 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2451 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2452 }
2453
Jethro Beekman66689272018-02-14 19:24:10 -08002454 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002455 {
Jethro Beekman66689272018-02-14 19:24:10 -08002456 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2457 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2458 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2459
2460 k = n * biL;
2461 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2462 X->p[0] |= 1;
2463
Janos Follath7c025a92018-08-14 11:08:41 +01002464 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002465 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002466 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002469 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002470 }
Jethro Beekman66689272018-02-14 19:24:10 -08002471 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002472 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002473 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002474 * An necessary condition for Y and X = 2Y + 1 to be prime
2475 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2476 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002477 */
Jethro Beekman66689272018-02-14 19:24:10 -08002478
2479 X->p[0] |= 2;
2480
2481 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2482 if( r == 0 )
2483 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2484 else if( r == 1 )
2485 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2486
2487 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2488 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2489 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2490
2491 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002492 {
Jethro Beekman66689272018-02-14 19:24:10 -08002493 /*
2494 * First, check small factors for X and Y
2495 * before doing Miller-Rabin on any of them
2496 */
2497 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2498 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002499 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002500 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002501 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002502 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002503 goto cleanup;
2504
2505 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2506 goto cleanup;
2507
2508 /*
2509 * Next candidates. We want to preserve Y = (X-1) / 2 and
2510 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2511 * so up Y by 6 and X by 12.
2512 */
2513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2514 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002516 }
2517 }
2518
2519cleanup:
2520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002522
2523 return( ret );
2524}
2525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002528#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002529
Paul Bakker23986e52011-04-24 08:57:21 +00002530#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002531
2532static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2533{
2534 { 693, 609, 21 },
2535 { 1764, 868, 28 },
2536 { 768454923, 542167814, 1 }
2537};
2538
Paul Bakker5121ce52009-01-03 21:22:43 +00002539/*
2540 * Checkup routine
2541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002543{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002544 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002547 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2548 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002551 "EFE021C2645FD1DC586E69184AF4A31E" \
2552 "D5F53E93B5F123FA41680867BA110131" \
2553 "944FE7952E2517337780CB0DB80E61AA" \
2554 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002557 "B2E7EFD37075B9F03FF989C7C5051C20" \
2558 "34D2A323810251127E7BF8625A4F49A5" \
2559 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2560 "5B5C25763222FEFCCFC38B832366C29E" ) );
2561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002563 "0066A198186C18C10B2F5ED9B522752A" \
2564 "9830B69916E535C8F047518A889A43A5" \
2565 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002567 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002570 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2571 "9E857EA95A03512E2BAE7391688D264A" \
2572 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2573 "8001B72E848A38CAE1C65F78E56ABDEF" \
2574 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2575 "ECF677152EF804370C1A305CAF3B5BF1" \
2576 "30879B56C61DE584A0F53A2447A51E" ) );
2577
2578 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002582 {
2583 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002586 ret = 1;
2587 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002588 }
2589
2590 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 "256567336059E52CAE22925474705F39A94" ) );
2597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002599 "6613F26162223DF488E9CD48CC132C7A" \
2600 "0AC93C701B001B092E4E5B9F73BCD27B" \
2601 "9EE50D0657C77F374E903CDFA4C642" ) );
2602
2603 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2607 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002608 {
2609 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002611
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002612 ret = 1;
2613 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002614 }
2615
2616 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002620
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002621 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002622 "36E139AEA55215609D2816998ED020BB" \
2623 "BD96C37890F65171D948E9BC7CBAA4D9" \
2624 "325D24D6A3C12710F10A09FA08AB87" ) );
2625
2626 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002627 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002630 {
2631 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002633
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002634 ret = 1;
2635 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002636 }
2637
2638 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002639 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002641 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002644 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2645 "C3DBA76456363A10869622EAC2DD84EC" \
2646 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2647
2648 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002649 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002651 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002652 {
2653 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002656 ret = 1;
2657 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 }
2659
2660 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002662
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002663 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002664 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002665
Paul Bakker66d5d072014-06-17 16:39:18 +02002666 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002667 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002668 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2669 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002674 {
2675 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002676 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002677
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002678 ret = 1;
2679 goto cleanup;
2680 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002681 }
2682
2683 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002685
Paul Bakker5121ce52009-01-03 21:22:43 +00002686cleanup:
2687
2688 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2692 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002693
2694 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002696
2697 return( ret );
2698}
2699
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002700#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702#endif /* MBEDTLS_BIGNUM_C */