blob: 402a3d5c1dd856d8da0a717329a531e037696d2f [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
530 * Helper to write the digits high-order first
531 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000533{
534 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536
537 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
541 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
544 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000545
546 if( r < 10 )
547 *(*p)++ = (char)( r + 0x30 );
548 else
549 *(*p)++ = (char)( r + 0x37 );
550
551cleanup:
552
553 return( ret );
554}
555
556/*
557 * Export into an ASCII string
558 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100559int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
560 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000561{
Paul Bakker23986e52011-04-24 08:57:21 +0000562 int ret = 0;
563 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000566 MPI_VALIDATE_RET( X != NULL );
567 MPI_VALIDATE_RET( olen != NULL );
568 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
570 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000571 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000572
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200573 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 if( radix >= 4 ) n >>= 1;
575 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000576 /*
577 * Round up the buffer length to an even value to ensure that there is
578 * enough room for hexadecimal values that can be represented in an odd
579 * number of digits.
580 */
581 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100583 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100585 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 }
588
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100589 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
592 if( X->s == -1 )
593 *p++ = '-';
594
595 if( radix == 16 )
596 {
Paul Bakker23986e52011-04-24 08:57:21 +0000597 int c;
598 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Paul Bakker23986e52011-04-24 08:57:21 +0000600 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 {
Paul Bakker23986e52011-04-24 08:57:21 +0000602 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 {
Paul Bakker23986e52011-04-24 08:57:21 +0000604 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
Paul Bakker6c343d72014-07-10 14:36:19 +0200606 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000607 continue;
608
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000609 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000610 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 k = 1;
612 }
613 }
614 }
615 else
616 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000618
619 if( T.s == -1 )
620 T.s = 1;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 }
624
625 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100626 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
628cleanup:
629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 return( ret );
633}
634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000636/*
637 * Read X from an opened file
638 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000640{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000642 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000644 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000645 * Buffer should have space for (short) label and decimal formatted MPI,
646 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000647 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
Hanno Becker73d7d792018-12-11 10:35:51 +0000650 MPI_VALIDATE_RET( X != NULL );
651 MPI_VALIDATE_RET( fin != NULL );
652
653 if( radix < 2 || radix > 16 )
654 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
655
Paul Bakker5121ce52009-01-03 21:22:43 +0000656 memset( s, 0, sizeof( s ) );
657 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
660 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000661 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000663
Hanno Beckerb2034b72017-04-26 11:46:46 +0100664 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
665 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
667 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100668 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 if( mpi_get_digit( &d, radix, *p ) != 0 )
670 break;
671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673}
674
675/*
676 * Write X into an opened file (or stdout if fout == NULL)
677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000679{
Paul Bakker23986e52011-04-24 08:57:21 +0000680 int ret;
681 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000682 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000683 * Buffer should have space for (short) label and decimal formatted MPI,
684 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000685 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000687 MPI_VALIDATE_RET( X != NULL );
688
689 if( radix < 2 || radix > 16 )
690 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100692 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100694 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
696 if( p == NULL ) p = "";
697
698 plen = strlen( p );
699 slen = strlen( s );
700 s[slen++] = '\r';
701 s[slen++] = '\n';
702
703 if( fout != NULL )
704 {
705 if( fwrite( p, 1, plen, fout ) != plen ||
706 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000708 }
709 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
712cleanup:
713
714 return( ret );
715}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000717
Hanno Beckerda1655a2017-10-18 14:21:44 +0100718
719/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
720 * into the storage form used by mbedtls_mpi. */
Hanno Becker2be8a552018-10-25 12:40:09 +0100721static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100722{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100723 size_t i;
724
725 unsigned char *cur_byte_left;
726 unsigned char *cur_byte_right;
727
728 mbedtls_mpi_uint *cur_limb_left;
729 mbedtls_mpi_uint *cur_limb_right;
730
731 mbedtls_mpi_uint tmp_left, tmp_right;
732
Hanno Becker2be8a552018-10-25 12:40:09 +0100733 if( limbs == 0 )
734 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100735
736 /*
737 * Traverse limbs and
738 * - adapt byte-order in each limb
739 * - swap the limbs themselves.
740 * For that, simultaneously traverse the limbs from left to right
741 * and from right to left, as long as the left index is not bigger
742 * than the right index (it's not a problem if limbs is odd and the
743 * indices coincide in the last iteration).
744 */
745
746 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
747 cur_limb_left <= cur_limb_right;
748 cur_limb_left++, cur_limb_right-- )
749 {
750 cur_byte_left = (unsigned char*) cur_limb_left;
751 cur_byte_right = (unsigned char*) cur_limb_right;
752
753 tmp_left = 0;
754 tmp_right = 0;
755
756 for( i = 0; i < ciL; i++ )
757 {
758 tmp_left |= ( (mbedtls_mpi_uint) *cur_byte_left++ )
759 << ( ( ciL - 1 - i ) << 3 );
760 tmp_right |= ( (mbedtls_mpi_uint) *cur_byte_right++ )
761 << ( ( ciL - 1 - i ) << 3 );
762 }
763
764 *cur_limb_right = tmp_left;
765 *cur_limb_left = tmp_right;
766 }
767
Hanno Becker2be8a552018-10-25 12:40:09 +0100768 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100769}
770
Paul Bakker5121ce52009-01-03 21:22:43 +0000771/*
772 * Import X from unsigned binary data, big endian
773 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000775{
Paul Bakker23986e52011-04-24 08:57:21 +0000776 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100777 size_t const limbs = CHARS_TO_LIMBS( buflen );
778 size_t const overhead = ( limbs * ciL ) - buflen;
779 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
Hanno Becker8ce11a32018-12-19 16:18:52 +0000781 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000782 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
783
Hanno Becker073c1992017-10-17 15:17:27 +0100784 /* Ensure that target MPI has exactly the necessary number of limbs */
785 if( X->n != limbs )
786 {
787 mbedtls_mpi_free( X );
788 mbedtls_mpi_init( X );
789 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
790 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200791 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000792
Hanno Beckerda1655a2017-10-18 14:21:44 +0100793 Xp = (unsigned char*) X->p;
794 memcpy( Xp + overhead, buf, buflen );
795
Hanno Becker2be8a552018-10-25 12:40:09 +0100796 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker5121ce52009-01-03 21:22:43 +0000797
798cleanup:
799
800 return( ret );
801}
802
803/*
804 * Export X into unsigned binary data, big endian
805 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100806int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
807 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000808{
Hanno Becker73d7d792018-12-11 10:35:51 +0000809 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100810 size_t bytes_to_copy;
811 unsigned char *p;
812 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000813
Hanno Becker73d7d792018-12-11 10:35:51 +0000814 MPI_VALIDATE_RET( X != NULL );
815 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
816
817 stored_bytes = X->n * ciL;
818
Gilles Peskine11cdb052018-11-20 16:47:47 +0100819 if( stored_bytes < buflen )
820 {
821 /* There is enough space in the output buffer. Write initial
822 * null bytes and record the position at which to start
823 * writing the significant bytes. In this case, the execution
824 * trace of this function does not depend on the value of the
825 * number. */
826 bytes_to_copy = stored_bytes;
827 p = buf + buflen - stored_bytes;
828 memset( buf, 0, buflen - stored_bytes );
829 }
830 else
831 {
832 /* The output buffer is smaller than the allocated size of X.
833 * However X may fit if its leading bytes are zero. */
834 bytes_to_copy = buflen;
835 p = buf;
836 for( i = bytes_to_copy; i < stored_bytes; i++ )
837 {
838 if( GET_BYTE( X, i ) != 0 )
839 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
840 }
841 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000842
Gilles Peskine11cdb052018-11-20 16:47:47 +0100843 for( i = 0; i < bytes_to_copy; i++ )
844 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
846 return( 0 );
847}
848
849/*
850 * Left-shift: X <<= count
851 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200852int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000853{
Paul Bakker23986e52011-04-24 08:57:21 +0000854 int ret;
855 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200856 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000857 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000858
859 v0 = count / (biL );
860 t1 = count & (biL - 1);
861
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200862 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000863
Paul Bakkerf9688572011-05-05 10:00:45 +0000864 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200865 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000866
867 ret = 0;
868
869 /*
870 * shift by count / limb_size
871 */
872 if( v0 > 0 )
873 {
Paul Bakker23986e52011-04-24 08:57:21 +0000874 for( i = X->n; i > v0; i-- )
875 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000876
Paul Bakker23986e52011-04-24 08:57:21 +0000877 for( ; i > 0; i-- )
878 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000879 }
880
881 /*
882 * shift by count % limb_size
883 */
884 if( t1 > 0 )
885 {
886 for( i = v0; i < X->n; i++ )
887 {
888 r1 = X->p[i] >> (biL - t1);
889 X->p[i] <<= t1;
890 X->p[i] |= r0;
891 r0 = r1;
892 }
893 }
894
895cleanup:
896
897 return( ret );
898}
899
900/*
901 * Right-shift: X >>= count
902 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000904{
Paul Bakker23986e52011-04-24 08:57:21 +0000905 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000907 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000908
909 v0 = count / biL;
910 v1 = count & (biL - 1);
911
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100912 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200913 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100914
Paul Bakker5121ce52009-01-03 21:22:43 +0000915 /*
916 * shift by count / limb_size
917 */
918 if( v0 > 0 )
919 {
920 for( i = 0; i < X->n - v0; i++ )
921 X->p[i] = X->p[i + v0];
922
923 for( ; i < X->n; i++ )
924 X->p[i] = 0;
925 }
926
927 /*
928 * shift by count % limb_size
929 */
930 if( v1 > 0 )
931 {
Paul Bakker23986e52011-04-24 08:57:21 +0000932 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000933 {
Paul Bakker23986e52011-04-24 08:57:21 +0000934 r1 = X->p[i - 1] << (biL - v1);
935 X->p[i - 1] >>= v1;
936 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000937 r0 = r1;
938 }
939 }
940
941 return( 0 );
942}
943
944/*
945 * Compare unsigned values
946 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000948{
Paul Bakker23986e52011-04-24 08:57:21 +0000949 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000950 MPI_VALIDATE_RET( X != NULL );
951 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000952
Paul Bakker23986e52011-04-24 08:57:21 +0000953 for( i = X->n; i > 0; i-- )
954 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000955 break;
956
Paul Bakker23986e52011-04-24 08:57:21 +0000957 for( j = Y->n; j > 0; j-- )
958 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000959 break;
960
Paul Bakker23986e52011-04-24 08:57:21 +0000961 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000962 return( 0 );
963
964 if( i > j ) return( 1 );
965 if( j > i ) return( -1 );
966
Paul Bakker23986e52011-04-24 08:57:21 +0000967 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000968 {
Paul Bakker23986e52011-04-24 08:57:21 +0000969 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
970 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000971 }
972
973 return( 0 );
974}
975
976/*
977 * Compare signed values
978 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200979int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000980{
Paul Bakker23986e52011-04-24 08:57:21 +0000981 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000982 MPI_VALIDATE_RET( X != NULL );
983 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000984
Paul Bakker23986e52011-04-24 08:57:21 +0000985 for( i = X->n; i > 0; i-- )
986 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000987 break;
988
Paul Bakker23986e52011-04-24 08:57:21 +0000989 for( j = Y->n; j > 0; j-- )
990 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000991 break;
992
Paul Bakker23986e52011-04-24 08:57:21 +0000993 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000994 return( 0 );
995
996 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000997 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000998
999 if( X->s > 0 && Y->s < 0 ) return( 1 );
1000 if( Y->s > 0 && X->s < 0 ) return( -1 );
1001
Paul Bakker23986e52011-04-24 08:57:21 +00001002 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001003 {
Paul Bakker23986e52011-04-24 08:57:21 +00001004 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1005 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001006 }
1007
1008 return( 0 );
1009}
1010
1011/*
1012 * Compare signed values
1013 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001015{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 mbedtls_mpi Y;
1017 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001018 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001019
1020 *p = ( z < 0 ) ? -z : z;
1021 Y.s = ( z < 0 ) ? -1 : 1;
1022 Y.n = 1;
1023 Y.p = p;
1024
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001026}
1027
1028/*
1029 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1030 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001032{
Paul Bakker23986e52011-04-24 08:57:21 +00001033 int ret;
1034 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001035 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001036 MPI_VALIDATE_RET( X != NULL );
1037 MPI_VALIDATE_RET( A != NULL );
1038 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001039
1040 if( X == B )
1041 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001043 }
1044
1045 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001047
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001048 /*
1049 * X should always be positive as a result of unsigned additions.
1050 */
1051 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001052
Paul Bakker23986e52011-04-24 08:57:21 +00001053 for( j = B->n; j > 0; j-- )
1054 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 break;
1056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001058
1059 o = B->p; p = X->p; c = 0;
1060
Janos Follath6c922682015-10-30 17:43:11 +01001061 /*
1062 * tmp is used because it might happen that p == o
1063 */
Paul Bakker23986e52011-04-24 08:57:21 +00001064 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001065 {
Janos Follath6c922682015-10-30 17:43:11 +01001066 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001067 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001068 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 }
1070
1071 while( c != 0 )
1072 {
1073 if( i >= X->n )
1074 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001076 p = X->p + i;
1077 }
1078
Paul Bakker2d319fd2012-09-16 21:34:26 +00001079 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001080 }
1081
1082cleanup:
1083
1084 return( ret );
1085}
1086
1087/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001089 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001091{
Paul Bakker23986e52011-04-24 08:57:21 +00001092 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001094
1095 for( i = c = 0; i < n; i++, s++, d++ )
1096 {
1097 z = ( *d < c ); *d -= c;
1098 c = ( *d < *s ) + z; *d -= *s;
1099 }
1100
1101 while( c != 0 )
1102 {
1103 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001104 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001105 }
1106}
1107
1108/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001109 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001112{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001114 int ret;
1115 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001116 MPI_VALIDATE_RET( X != NULL );
1117 MPI_VALIDATE_RET( A != NULL );
1118 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1121 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001124
1125 if( X == B )
1126 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001128 B = &TB;
1129 }
1130
1131 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001132 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133
Paul Bakker1ef7a532009-06-20 10:50:55 +00001134 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001135 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001136 */
1137 X->s = 1;
1138
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 ret = 0;
1140
Paul Bakker23986e52011-04-24 08:57:21 +00001141 for( n = B->n; n > 0; n-- )
1142 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 break;
1144
Paul Bakker23986e52011-04-24 08:57:21 +00001145 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001146
1147cleanup:
1148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150
1151 return( ret );
1152}
1153
1154/*
1155 * Signed addition: X = A + B
1156 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001157int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001158{
Hanno Becker73d7d792018-12-11 10:35:51 +00001159 int ret, s;
1160 MPI_VALIDATE_RET( X != NULL );
1161 MPI_VALIDATE_RET( A != NULL );
1162 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001163
Hanno Becker73d7d792018-12-11 10:35:51 +00001164 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001165 if( A->s * B->s < 0 )
1166 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001170 X->s = s;
1171 }
1172 else
1173 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001174 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001175 X->s = -s;
1176 }
1177 }
1178 else
1179 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001180 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 X->s = s;
1182 }
1183
1184cleanup:
1185
1186 return( ret );
1187}
1188
1189/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001190 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001193{
Hanno Becker73d7d792018-12-11 10:35:51 +00001194 int ret, s;
1195 MPI_VALIDATE_RET( X != NULL );
1196 MPI_VALIDATE_RET( A != NULL );
1197 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001198
Hanno Becker73d7d792018-12-11 10:35:51 +00001199 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001200 if( A->s * B->s > 0 )
1201 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001204 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001205 X->s = s;
1206 }
1207 else
1208 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001209 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001210 X->s = -s;
1211 }
1212 }
1213 else
1214 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001216 X->s = s;
1217 }
1218
1219cleanup:
1220
1221 return( ret );
1222}
1223
1224/*
1225 * Signed addition: X = A + b
1226 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001228{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 mbedtls_mpi _B;
1230 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001231 MPI_VALIDATE_RET( X != NULL );
1232 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001233
1234 p[0] = ( b < 0 ) ? -b : b;
1235 _B.s = ( b < 0 ) ? -1 : 1;
1236 _B.n = 1;
1237 _B.p = p;
1238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001240}
1241
1242/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001243 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001244 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001246{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 mbedtls_mpi _B;
1248 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001249 MPI_VALIDATE_RET( X != NULL );
1250 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001251
1252 p[0] = ( b < 0 ) ? -b : b;
1253 _B.s = ( b < 0 ) ? -1 : 1;
1254 _B.n = 1;
1255 _B.p = p;
1256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001258}
1259
1260/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001261 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001262 */
1263static
1264#if defined(__APPLE__) && defined(__arm__)
1265/*
1266 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1267 * appears to need this to prevent bad ARM code generation at -O3.
1268 */
1269__attribute__ ((noinline))
1270#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001271void 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 +00001272{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001274
1275#if defined(MULADDC_HUIT)
1276 for( ; i >= 8; i -= 8 )
1277 {
1278 MULADDC_INIT
1279 MULADDC_HUIT
1280 MULADDC_STOP
1281 }
1282
1283 for( ; i > 0; i-- )
1284 {
1285 MULADDC_INIT
1286 MULADDC_CORE
1287 MULADDC_STOP
1288 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001289#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001290 for( ; i >= 16; i -= 16 )
1291 {
1292 MULADDC_INIT
1293 MULADDC_CORE MULADDC_CORE
1294 MULADDC_CORE MULADDC_CORE
1295 MULADDC_CORE MULADDC_CORE
1296 MULADDC_CORE MULADDC_CORE
1297
1298 MULADDC_CORE MULADDC_CORE
1299 MULADDC_CORE MULADDC_CORE
1300 MULADDC_CORE MULADDC_CORE
1301 MULADDC_CORE MULADDC_CORE
1302 MULADDC_STOP
1303 }
1304
1305 for( ; i >= 8; i -= 8 )
1306 {
1307 MULADDC_INIT
1308 MULADDC_CORE MULADDC_CORE
1309 MULADDC_CORE MULADDC_CORE
1310
1311 MULADDC_CORE MULADDC_CORE
1312 MULADDC_CORE MULADDC_CORE
1313 MULADDC_STOP
1314 }
1315
1316 for( ; i > 0; i-- )
1317 {
1318 MULADDC_INIT
1319 MULADDC_CORE
1320 MULADDC_STOP
1321 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001322#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001323
1324 t++;
1325
1326 do {
1327 *d += c; c = ( *d < c ); d++;
1328 }
1329 while( c != 0 );
1330}
1331
1332/*
1333 * Baseline multiplication: X = A * B (HAC 14.12)
1334 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001336{
Paul Bakker23986e52011-04-24 08:57:21 +00001337 int ret;
1338 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001340 MPI_VALIDATE_RET( X != NULL );
1341 MPI_VALIDATE_RET( A != NULL );
1342 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1347 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001348
Paul Bakker23986e52011-04-24 08:57:21 +00001349 for( i = A->n; i > 0; i-- )
1350 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001351 break;
1352
Paul Bakker23986e52011-04-24 08:57:21 +00001353 for( j = B->n; j > 0; j-- )
1354 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001355 break;
1356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1358 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001359
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001360 for( ; j > 0; j-- )
1361 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
1363 X->s = A->s * B->s;
1364
1365cleanup:
1366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001368
1369 return( ret );
1370}
1371
1372/*
1373 * Baseline multiplication: X = A * b
1374 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001376{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 mbedtls_mpi _B;
1378 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001379 MPI_VALIDATE_RET( X != NULL );
1380 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001381
1382 _B.s = 1;
1383 _B.n = 1;
1384 _B.p = p;
1385 p[0] = b;
1386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001388}
1389
1390/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001391 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1392 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001393 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001394static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1395 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001396{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001397#if defined(MBEDTLS_HAVE_UDBL)
1398 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001399#else
Simon Butcher9803d072016-01-03 00:24:34 +00001400 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1401 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001402 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1403 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001404 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001405#endif
1406
Simon Butcher15b15d12015-11-26 19:35:03 +00001407 /*
1408 * Check for overflow
1409 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001410 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001411 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001412 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001413
Simon Butcherf5ba0452015-12-27 23:01:55 +00001414 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001415 }
1416
1417#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001418 dividend = (mbedtls_t_udbl) u1 << biL;
1419 dividend |= (mbedtls_t_udbl) u0;
1420 quotient = dividend / d;
1421 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1422 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1423
1424 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001425 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001426
1427 return (mbedtls_mpi_uint) quotient;
1428#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001429
1430 /*
1431 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1432 * Vol. 2 - Seminumerical Algorithms, Knuth
1433 */
1434
1435 /*
1436 * Normalize the divisor, d, and dividend, u0, u1
1437 */
1438 s = mbedtls_clz( d );
1439 d = d << s;
1440
1441 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001442 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001443 u0 = u0 << s;
1444
1445 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001446 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001447
1448 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001449 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001450
1451 /*
1452 * Find the first quotient and remainder
1453 */
1454 q1 = u1 / d1;
1455 r0 = u1 - d1 * q1;
1456
1457 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1458 {
1459 q1 -= 1;
1460 r0 += d1;
1461
1462 if ( r0 >= radix ) break;
1463 }
1464
Simon Butcherf5ba0452015-12-27 23:01:55 +00001465 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001466 q0 = rAX / d1;
1467 r0 = rAX - q0 * d1;
1468
1469 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1470 {
1471 q0 -= 1;
1472 r0 += d1;
1473
1474 if ( r0 >= radix ) break;
1475 }
1476
1477 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001478 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001479
1480 quotient = q1 * radix + q0;
1481
1482 return quotient;
1483#endif
1484}
1485
1486/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001487 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001488 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001489int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1490 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001491{
Paul Bakker23986e52011-04-24 08:57:21 +00001492 int ret;
1493 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001495 MPI_VALIDATE_RET( A != NULL );
1496 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001498 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1499 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1502 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001505 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1507 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 return( 0 );
1509 }
1510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1512 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001513 X.s = Y.s = 1;
1514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1516 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1517 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1518 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001519
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001520 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001521 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001522 {
1523 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1525 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001526 }
1527 else k = 0;
1528
1529 n = X.n - 1;
1530 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001534 {
1535 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001537 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001539
1540 for( i = n; i > t ; i-- )
1541 {
1542 if( X.p[i] >= Y.p[t] )
1543 Z.p[i - t - 1] = ~0;
1544 else
1545 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001546 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1547 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001548 }
1549
1550 Z.p[i - t - 1]++;
1551 do
1552 {
1553 Z.p[i - t - 1]--;
1554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001556 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001557 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001561 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1562 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001563 T2.p[2] = X.p[i];
1564 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1568 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1569 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001570
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001572 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1574 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1575 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 Z.p[i - t - 1]--;
1577 }
1578 }
1579
1580 if( Q != NULL )
1581 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001582 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001583 Q->s = A->s * B->s;
1584 }
1585
1586 if( R != NULL )
1587 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001589 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001593 R->s = 1;
1594 }
1595
1596cleanup:
1597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1599 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001600
1601 return( ret );
1602}
1603
1604/*
1605 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001606 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001607int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1608 const mbedtls_mpi *A,
1609 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001610{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 mbedtls_mpi _B;
1612 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001613 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614
1615 p[0] = ( b < 0 ) ? -b : b;
1616 _B.s = ( b < 0 ) ? -1 : 1;
1617 _B.n = 1;
1618 _B.p = p;
1619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001621}
1622
1623/*
1624 * Modulo: R = A mod B
1625 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001627{
1628 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001629 MPI_VALIDATE_RET( R != NULL );
1630 MPI_VALIDATE_RET( A != NULL );
1631 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001632
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1634 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1639 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1642 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643
1644cleanup:
1645
1646 return( ret );
1647}
1648
1649/*
1650 * Modulo: r = A mod b
1651 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001653{
Paul Bakker23986e52011-04-24 08:57:21 +00001654 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001656 MPI_VALIDATE_RET( r != NULL );
1657 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001658
1659 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661
1662 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
1665 /*
1666 * handle trivial cases
1667 */
1668 if( b == 1 )
1669 {
1670 *r = 0;
1671 return( 0 );
1672 }
1673
1674 if( b == 2 )
1675 {
1676 *r = A->p[0] & 1;
1677 return( 0 );
1678 }
1679
1680 /*
1681 * general case
1682 */
Paul Bakker23986e52011-04-24 08:57:21 +00001683 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001684 {
Paul Bakker23986e52011-04-24 08:57:21 +00001685 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 y = ( y << biH ) | ( x >> biH );
1687 z = y / b;
1688 y -= z * b;
1689
1690 x <<= biH;
1691 y = ( y << biH ) | ( x >> biH );
1692 z = y / b;
1693 y -= z * b;
1694 }
1695
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001696 /*
1697 * If A is negative, then the current y represents a negative value.
1698 * Flipping it to the positive side.
1699 */
1700 if( A->s < 0 && y != 0 )
1701 y = b - y;
1702
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 *r = y;
1704
1705 return( 0 );
1706}
1707
1708/*
1709 * Fast Montgomery initialization (thanks to Tom St Denis)
1710 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001711static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001712{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001713 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001714 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001715
1716 x = m0;
1717 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001718
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001719 for( i = biL; i >= 8; i /= 2 )
1720 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
1722 *mm = ~x + 1;
1723}
1724
1725/*
1726 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1727 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001728static 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 +02001729 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001730{
Paul Bakker23986e52011-04-24 08:57:21 +00001731 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001734 if( T->n < N->n + 1 || T->p == NULL )
1735 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1736
Paul Bakker5121ce52009-01-03 21:22:43 +00001737 memset( T->p, 0, T->n * ciL );
1738
1739 d = T->p;
1740 n = N->n;
1741 m = ( B->n < n ) ? B->n : n;
1742
1743 for( i = 0; i < n; i++ )
1744 {
1745 /*
1746 * T = (T + u0*B + u1*N) / 2^biL
1747 */
1748 u0 = A->p[i];
1749 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1750
1751 mpi_mul_hlp( m, B->p, d, u0 );
1752 mpi_mul_hlp( n, N->p, d, u1 );
1753
1754 *d++ = u0; d[n + 1] = 0;
1755 }
1756
Paul Bakker66d5d072014-06-17 16:39:18 +02001757 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 mpi_sub_hlp( n, N->p, A->p );
1761 else
1762 /* prevent timing attacks */
1763 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001764
1765 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001766}
1767
1768/*
1769 * Montgomery reduction: A = A * R^-1 mod N
1770 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001771static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1772 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001773{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774 mbedtls_mpi_uint z = 1;
1775 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001776
Paul Bakker8ddb6452013-02-27 14:56:33 +01001777 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001778 U.p = &z;
1779
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001780 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781}
1782
1783/*
1784 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1785 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001786int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1787 const mbedtls_mpi *E, const mbedtls_mpi *N,
1788 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001789{
Paul Bakker23986e52011-04-24 08:57:21 +00001790 int ret;
1791 size_t wbits, wsize, one = 1;
1792 size_t i, j, nblimbs;
1793 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 mbedtls_mpi_uint ei, mm, state;
1795 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001796 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
Hanno Becker73d7d792018-12-11 10:35:51 +00001798 MPI_VALIDATE_RET( X != NULL );
1799 MPI_VALIDATE_RET( A != NULL );
1800 MPI_VALIDATE_RET( E != NULL );
1801 MPI_VALIDATE_RET( N != NULL );
1802
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001803 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001805
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1807 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001808
1809 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001810 * Init temps and window size
1811 */
1812 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1814 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815 memset( W, 0, sizeof( W ) );
1816
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001817 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001818
1819 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1820 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1823 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001824
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1827 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1828 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829
1830 /*
Paul Bakker50546922012-05-19 08:40:49 +00001831 * Compensate for negative A (and correct at the end)
1832 */
1833 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001834 if( neg )
1835 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001837 Apos.s = 1;
1838 A = &Apos;
1839 }
1840
1841 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001842 * If 1st call, pre-compute R^2 mod N
1843 */
1844 if( _RR == NULL || _RR->p == NULL )
1845 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1847 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1848 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001849
1850 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001851 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001852 }
1853 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001854 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001855
1856 /*
1857 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1858 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1860 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001861 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001863
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001864 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001865
1866 /*
1867 * X = R^2 * R^-1 mod N = R mod N
1868 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001870 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
1872 if( wsize > 1 )
1873 {
1874 /*
1875 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1876 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001877 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
1882 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001883 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001884
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 /*
1886 * W[i] = W[i - 1] * W[1]
1887 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001888 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1891 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001892
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001893 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894 }
1895 }
1896
1897 nblimbs = E->n;
1898 bufsize = 0;
1899 nbits = 0;
1900 wbits = 0;
1901 state = 0;
1902
1903 while( 1 )
1904 {
1905 if( bufsize == 0 )
1906 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001907 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001908 break;
1909
Paul Bakker0d7702c2013-10-29 16:18:35 +01001910 nblimbs--;
1911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 }
1914
1915 bufsize--;
1916
1917 ei = (E->p[nblimbs] >> bufsize) & 1;
1918
1919 /*
1920 * skip leading 0s
1921 */
1922 if( ei == 0 && state == 0 )
1923 continue;
1924
1925 if( ei == 0 && state == 1 )
1926 {
1927 /*
1928 * out of window, square X
1929 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001930 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001931 continue;
1932 }
1933
1934 /*
1935 * add ei to current window
1936 */
1937 state = 2;
1938
1939 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001940 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001941
1942 if( nbits == wsize )
1943 {
1944 /*
1945 * X = X^wsize R^-1 mod N
1946 */
1947 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001948 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001949
1950 /*
1951 * X = X * W[wbits] R^-1 mod N
1952 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001953 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001954
1955 state--;
1956 nbits = 0;
1957 wbits = 0;
1958 }
1959 }
1960
1961 /*
1962 * process the remaining bits
1963 */
1964 for( i = 0; i < nbits; i++ )
1965 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001966 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
1968 wbits <<= 1;
1969
Paul Bakker66d5d072014-06-17 16:39:18 +02001970 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001971 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972 }
1973
1974 /*
1975 * X = A^E * R * R^-1 mod N = A^E mod N
1976 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001977 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001978
Hanno Beckera4af1c42017-04-18 09:07:45 +01001979 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001980 {
1981 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001982 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001983 }
1984
Paul Bakker5121ce52009-01-03 21:22:43 +00001985cleanup:
1986
Paul Bakker66d5d072014-06-17 16:39:18 +02001987 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001991
Paul Bakker75a28602014-03-31 12:08:17 +02001992 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001994
1995 return( ret );
1996}
1997
Paul Bakker5121ce52009-01-03 21:22:43 +00001998/*
1999 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2000 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002002{
Paul Bakker23986e52011-04-24 08:57:21 +00002003 int ret;
2004 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
Hanno Becker73d7d792018-12-11 10:35:51 +00002007 MPI_VALIDATE_RET( G != NULL );
2008 MPI_VALIDATE_RET( A != NULL );
2009 MPI_VALIDATE_RET( B != NULL );
2010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2014 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 lz = mbedtls_mpi_lsb( &TA );
2017 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002018
Paul Bakker66d5d072014-06-17 16:39:18 +02002019 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002020 lz = lzt;
2021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002022 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2023 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002024
Paul Bakker5121ce52009-01-03 21:22:43 +00002025 TA.s = TB.s = 1;
2026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002028 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2030 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002033 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2035 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002036 }
2037 else
2038 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2040 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002041 }
2042 }
2043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2045 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002046
2047cleanup:
2048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002050
2051 return( ret );
2052}
2053
Paul Bakker33dc46b2014-04-30 16:11:39 +02002054/*
2055 * Fill X with size bytes of random.
2056 *
2057 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002058 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002059 * deterministic, eg for tests).
2060 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002062 int (*f_rng)(void *, unsigned char *, size_t),
2063 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002064{
Paul Bakker23986e52011-04-24 08:57:21 +00002065 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +01002066 size_t const limbs CHARS_TO_LIMBS( size );
2067 size_t const overhead = ( limbs * ciL ) - size;
2068 unsigned char *Xp;
2069
Hanno Becker8ce11a32018-12-19 16:18:52 +00002070 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002071 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002072
Hanno Beckerda1655a2017-10-18 14:21:44 +01002073 /* Ensure that target MPI has exactly the necessary number of limbs */
2074 if( X->n != limbs )
2075 {
2076 mbedtls_mpi_free( X );
2077 mbedtls_mpi_init( X );
2078 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2079 }
2080 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002081
Hanno Beckerda1655a2017-10-18 14:21:44 +01002082 Xp = (unsigned char*) X->p;
2083 f_rng( p_rng, Xp + overhead, size );
2084
Hanno Becker2be8a552018-10-25 12:40:09 +01002085 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002086
2087cleanup:
2088 return( ret );
2089}
2090
Paul Bakker5121ce52009-01-03 21:22:43 +00002091/*
2092 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2093 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002095{
2096 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002098 MPI_VALIDATE_RET( X != NULL );
2099 MPI_VALIDATE_RET( A != NULL );
2100 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
Hanno Becker4bcb4912017-04-18 15:49:39 +01002102 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002103 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2106 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2107 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002112 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002114 goto cleanup;
2115 }
2116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2118 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2119 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2120 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002122 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2123 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2124 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2125 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126
2127 do
2128 {
2129 while( ( TU.p[0] & 1 ) == 0 )
2130 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002131 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002132
2133 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2134 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2136 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002137 }
2138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002139 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2140 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141 }
2142
2143 while( ( TV.p[0] & 1 ) == 0 )
2144 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002146
2147 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2148 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2150 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002151 }
2152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2154 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002155 }
2156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002158 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2160 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2161 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002162 }
2163 else
2164 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2166 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2167 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002168 }
2169 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2173 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2176 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179
2180cleanup:
2181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2183 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2184 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002185
2186 return( ret );
2187}
2188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002190
Paul Bakker5121ce52009-01-03 21:22:43 +00002191static const int small_prime[] =
2192{
2193 3, 5, 7, 11, 13, 17, 19, 23,
2194 29, 31, 37, 41, 43, 47, 53, 59,
2195 61, 67, 71, 73, 79, 83, 89, 97,
2196 101, 103, 107, 109, 113, 127, 131, 137,
2197 139, 149, 151, 157, 163, 167, 173, 179,
2198 181, 191, 193, 197, 199, 211, 223, 227,
2199 229, 233, 239, 241, 251, 257, 263, 269,
2200 271, 277, 281, 283, 293, 307, 311, 313,
2201 317, 331, 337, 347, 349, 353, 359, 367,
2202 373, 379, 383, 389, 397, 401, 409, 419,
2203 421, 431, 433, 439, 443, 449, 457, 461,
2204 463, 467, 479, 487, 491, 499, 503, 509,
2205 521, 523, 541, 547, 557, 563, 569, 571,
2206 577, 587, 593, 599, 601, 607, 613, 617,
2207 619, 631, 641, 643, 647, 653, 659, 661,
2208 673, 677, 683, 691, 701, 709, 719, 727,
2209 733, 739, 743, 751, 757, 761, 769, 773,
2210 787, 797, 809, 811, 821, 823, 827, 829,
2211 839, 853, 857, 859, 863, 877, 881, 883,
2212 887, 907, 911, 919, 929, 937, 941, 947,
2213 953, 967, 971, 977, 983, 991, 997, -103
2214};
2215
2216/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002217 * Small divisors test (X must be positive)
2218 *
2219 * Return values:
2220 * 0: no small factor (possible prime, more tests needed)
2221 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002222 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002223 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002224 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002226{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002227 int ret = 0;
2228 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002230
Paul Bakker5121ce52009-01-03 21:22:43 +00002231 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002233
2234 for( i = 0; small_prime[i] > 0; i++ )
2235 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002237 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002239 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002240
2241 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002243 }
2244
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002245cleanup:
2246 return( ret );
2247}
2248
2249/*
2250 * Miller-Rabin pseudo-primality test (HAC 4.24)
2251 */
Janos Follathda31fa12018-09-03 14:45:23 +01002252static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002253 int (*f_rng)(void *, unsigned char *, size_t),
2254 void *p_rng )
2255{
Pascal Junodb99183d2015-03-11 16:49:45 +01002256 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002257 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002259
Hanno Becker8ce11a32018-12-19 16:18:52 +00002260 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002261 MPI_VALIDATE_RET( f_rng != NULL );
2262
2263 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2264 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002266
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 /*
2268 * W = |X| - 1
2269 * R = W >> lsb( W )
2270 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2272 s = mbedtls_mpi_lsb( &W );
2273 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2274 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002275
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002276 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002277
Janos Follathda31fa12018-09-03 14:45:23 +01002278 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 {
2280 /*
2281 * pick a random A, 1 < A < |X| - 1
2282 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002283 count = 0;
2284 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002285 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002286
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002287 j = mbedtls_mpi_bitlen( &A );
2288 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002289 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002290 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002291 }
2292
2293 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002294 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002295 }
2296
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002297 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2298 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299
2300 /*
2301 * A = A^R mod |X|
2302 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2306 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002307 continue;
2308
2309 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002311 {
2312 /*
2313 * A = A * A mod |X|
2314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002315 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2316 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002319 break;
2320
2321 j++;
2322 }
2323
2324 /*
2325 * not prime if A != |X| - 1 or A == 1
2326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2328 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002329 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 break;
2332 }
2333 }
2334
2335cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002336 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2337 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002339
2340 return( ret );
2341}
2342
2343/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002344 * Pseudo-primality test: small factors, then Miller-Rabin
2345 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002346int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2347 int (*f_rng)(void *, unsigned char *, size_t),
2348 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002349{
2350 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002352 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002353 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002354
2355 XX.s = 1;
2356 XX.n = X->n;
2357 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2360 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2361 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002364 return( 0 );
2365
2366 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2367 {
2368 if( ret == 1 )
2369 return( 0 );
2370
2371 return( ret );
2372 }
2373
Janos Follathda31fa12018-09-03 14:45:23 +01002374 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002375}
2376
Janos Follatha0b67c22018-09-18 14:48:23 +01002377#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002378/*
2379 * Pseudo-primality test, error probability 2^-80
2380 */
2381int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2382 int (*f_rng)(void *, unsigned char *, size_t),
2383 void *p_rng )
2384{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002385 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002386 MPI_VALIDATE_RET( f_rng != NULL );
2387
Janos Follatha0b67c22018-09-18 14:48:23 +01002388 /*
2389 * In the past our key generation aimed for an error rate of at most
2390 * 2^-80. Since this function is deprecated, aim for the same certainty
2391 * here as well.
2392 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002393 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002394}
Janos Follatha0b67c22018-09-18 14:48:23 +01002395#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002396
2397/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002399 *
Janos Follathf301d232018-08-14 13:34:01 +01002400 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2401 * be either 1024 bits or 1536 bits long, and flags must contain
2402 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002403 */
Janos Follath7c025a92018-08-14 11:08:41 +01002404int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002405 int (*f_rng)(void *, unsigned char *, size_t),
2406 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002407{
Jethro Beekman66689272018-02-14 19:24:10 -08002408#ifdef MBEDTLS_HAVE_INT64
2409// ceil(2^63.5)
2410#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2411#else
2412// ceil(2^31.5)
2413#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2414#endif
2415 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002416 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002417 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 mbedtls_mpi_uint r;
2419 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002420
Hanno Becker8ce11a32018-12-19 16:18:52 +00002421 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002422 MPI_VALIDATE_RET( f_rng != NULL );
2423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2425 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002428
2429 n = BITS_TO_LIMBS( nbits );
2430
Janos Follathda31fa12018-09-03 14:45:23 +01002431 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2432 {
2433 /*
2434 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2435 */
2436 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2437 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2438 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2439 }
2440 else
2441 {
2442 /*
2443 * 2^-100 error probability, number of rounds computed based on HAC,
2444 * fact 4.48
2445 */
2446 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2447 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2448 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2449 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2450 }
2451
Jethro Beekman66689272018-02-14 19:24:10 -08002452 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002453 {
Jethro Beekman66689272018-02-14 19:24:10 -08002454 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2455 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2456 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2457
2458 k = n * biL;
2459 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2460 X->p[0] |= 1;
2461
Janos Follath7c025a92018-08-14 11:08:41 +01002462 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002463 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002464 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002467 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002468 }
Jethro Beekman66689272018-02-14 19:24:10 -08002469 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002470 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002471 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002472 * An necessary condition for Y and X = 2Y + 1 to be prime
2473 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2474 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002475 */
Jethro Beekman66689272018-02-14 19:24:10 -08002476
2477 X->p[0] |= 2;
2478
2479 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2480 if( r == 0 )
2481 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2482 else if( r == 1 )
2483 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2484
2485 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2486 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2487 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2488
2489 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002490 {
Jethro Beekman66689272018-02-14 19:24:10 -08002491 /*
2492 * First, check small factors for X and Y
2493 * before doing Miller-Rabin on any of them
2494 */
2495 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2496 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002497 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002498 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002499 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002500 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002501 goto cleanup;
2502
2503 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2504 goto cleanup;
2505
2506 /*
2507 * Next candidates. We want to preserve Y = (X-1) / 2 and
2508 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2509 * so up Y by 6 and X by 12.
2510 */
2511 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2512 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002514 }
2515 }
2516
2517cleanup:
2518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002519 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002520
2521 return( ret );
2522}
2523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002527
Paul Bakker23986e52011-04-24 08:57:21 +00002528#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002529
2530static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2531{
2532 { 693, 609, 21 },
2533 { 1764, 868, 28 },
2534 { 768454923, 542167814, 1 }
2535};
2536
Paul Bakker5121ce52009-01-03 21:22:43 +00002537/*
2538 * Checkup routine
2539 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002541{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002542 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2546 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002549 "EFE021C2645FD1DC586E69184AF4A31E" \
2550 "D5F53E93B5F123FA41680867BA110131" \
2551 "944FE7952E2517337780CB0DB80E61AA" \
2552 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002555 "B2E7EFD37075B9F03FF989C7C5051C20" \
2556 "34D2A323810251127E7BF8625A4F49A5" \
2557 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2558 "5B5C25763222FEFCCFC38B832366C29E" ) );
2559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002560 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002561 "0066A198186C18C10B2F5ED9B522752A" \
2562 "9830B69916E535C8F047518A889A43A5" \
2563 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002567 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002568 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2569 "9E857EA95A03512E2BAE7391688D264A" \
2570 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2571 "8001B72E848A38CAE1C65F78E56ABDEF" \
2572 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2573 "ECF677152EF804370C1A305CAF3B5BF1" \
2574 "30879B56C61DE584A0F53A2447A51E" ) );
2575
2576 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002580 {
2581 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002583
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002584 ret = 1;
2585 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002586 }
2587
2588 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002594 "256567336059E52CAE22925474705F39A94" ) );
2595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002596 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 "6613F26162223DF488E9CD48CC132C7A" \
2598 "0AC93C701B001B092E4E5B9F73BCD27B" \
2599 "9EE50D0657C77F374E903CDFA4C642" ) );
2600
2601 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002602 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2605 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002606 {
2607 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002608 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002609
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002610 ret = 1;
2611 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002612 }
2613
2614 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002620 "36E139AEA55215609D2816998ED020BB" \
2621 "BD96C37890F65171D948E9BC7CBAA4D9" \
2622 "325D24D6A3C12710F10A09FA08AB87" ) );
2623
2624 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002625 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002627 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002628 {
2629 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002631
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002632 ret = 1;
2633 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002634 }
2635
2636 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002637 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002639 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002641 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002642 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2643 "C3DBA76456363A10869622EAC2DD84EC" \
2644 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2645
2646 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002649 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002650 {
2651 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002652 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002653
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002654 ret = 1;
2655 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002656 }
2657
2658 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002659 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002660
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002661 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002662 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002663
Paul Bakker66d5d072014-06-17 16:39:18 +02002664 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002665 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002666 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2667 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002672 {
2673 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002674 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002675
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002676 ret = 1;
2677 goto cleanup;
2678 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002679 }
2680
2681 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002683
Paul Bakker5121ce52009-01-03 21:22:43 +00002684cleanup:
2685
2686 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002688
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2690 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002691
2692 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002693 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002694
2695 return( ret );
2696}
2697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002699
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002700#endif /* MBEDTLS_BIGNUM_C */