blob: 8b01bad6cb3795faaa5fd95c838f4f9f3700333b [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 Becker73d7d792018-12-11 10:35:51 +0000383 MPI_VALIDATE_RET( X != NULL );
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
718/*
719 * Import X from unsigned binary data, big endian
720 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000722{
Paul Bakker23986e52011-04-24 08:57:21 +0000723 int ret;
Hanno Becker073c1992017-10-17 15:17:27 +0100724 size_t i, j;
725 size_t const limbs = CHARS_TO_LIMBS( buflen );
Paul Bakker5121ce52009-01-03 21:22:43 +0000726
Hanno Becker73d7d792018-12-11 10:35:51 +0000727 MPI_VALIDATE_RET( X != NULL );
728 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
729
Hanno Becker073c1992017-10-17 15:17:27 +0100730 /* Ensure that target MPI has exactly the necessary number of limbs */
731 if( X->n != limbs )
732 {
733 mbedtls_mpi_free( X );
734 mbedtls_mpi_init( X );
735 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
736 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000739
Hanno Becker073c1992017-10-17 15:17:27 +0100740 for( i = buflen, j = 0; i > 0; i--, j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000742
743cleanup:
744
745 return( ret );
746}
747
748/*
749 * Export X into unsigned binary data, big endian
750 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100751int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
752 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000753{
Hanno Becker73d7d792018-12-11 10:35:51 +0000754 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100755 size_t bytes_to_copy;
756 unsigned char *p;
757 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000758
Hanno Becker73d7d792018-12-11 10:35:51 +0000759 MPI_VALIDATE_RET( X != NULL );
760 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
761
762 stored_bytes = X->n * ciL;
763
Gilles Peskine11cdb052018-11-20 16:47:47 +0100764 if( stored_bytes < buflen )
765 {
766 /* There is enough space in the output buffer. Write initial
767 * null bytes and record the position at which to start
768 * writing the significant bytes. In this case, the execution
769 * trace of this function does not depend on the value of the
770 * number. */
771 bytes_to_copy = stored_bytes;
772 p = buf + buflen - stored_bytes;
773 memset( buf, 0, buflen - stored_bytes );
774 }
775 else
776 {
777 /* The output buffer is smaller than the allocated size of X.
778 * However X may fit if its leading bytes are zero. */
779 bytes_to_copy = buflen;
780 p = buf;
781 for( i = bytes_to_copy; i < stored_bytes; i++ )
782 {
783 if( GET_BYTE( X, i ) != 0 )
784 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
785 }
786 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000787
Gilles Peskine11cdb052018-11-20 16:47:47 +0100788 for( i = 0; i < bytes_to_copy; i++ )
789 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000790
791 return( 0 );
792}
793
794/*
795 * Left-shift: X <<= count
796 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000798{
Paul Bakker23986e52011-04-24 08:57:21 +0000799 int ret;
800 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200801 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000802 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000803
804 v0 = count / (biL );
805 t1 = count & (biL - 1);
806
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200807 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000808
Paul Bakkerf9688572011-05-05 10:00:45 +0000809 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200810 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
812 ret = 0;
813
814 /*
815 * shift by count / limb_size
816 */
817 if( v0 > 0 )
818 {
Paul Bakker23986e52011-04-24 08:57:21 +0000819 for( i = X->n; i > v0; i-- )
820 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000821
Paul Bakker23986e52011-04-24 08:57:21 +0000822 for( ; i > 0; i-- )
823 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000824 }
825
826 /*
827 * shift by count % limb_size
828 */
829 if( t1 > 0 )
830 {
831 for( i = v0; i < X->n; i++ )
832 {
833 r1 = X->p[i] >> (biL - t1);
834 X->p[i] <<= t1;
835 X->p[i] |= r0;
836 r0 = r1;
837 }
838 }
839
840cleanup:
841
842 return( ret );
843}
844
845/*
846 * Right-shift: X >>= count
847 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000849{
Paul Bakker23986e52011-04-24 08:57:21 +0000850 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000852 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000853
854 v0 = count / biL;
855 v1 = count & (biL - 1);
856
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100857 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100859
Paul Bakker5121ce52009-01-03 21:22:43 +0000860 /*
861 * shift by count / limb_size
862 */
863 if( v0 > 0 )
864 {
865 for( i = 0; i < X->n - v0; i++ )
866 X->p[i] = X->p[i + v0];
867
868 for( ; i < X->n; i++ )
869 X->p[i] = 0;
870 }
871
872 /*
873 * shift by count % limb_size
874 */
875 if( v1 > 0 )
876 {
Paul Bakker23986e52011-04-24 08:57:21 +0000877 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000878 {
Paul Bakker23986e52011-04-24 08:57:21 +0000879 r1 = X->p[i - 1] << (biL - v1);
880 X->p[i - 1] >>= v1;
881 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000882 r0 = r1;
883 }
884 }
885
886 return( 0 );
887}
888
889/*
890 * Compare unsigned values
891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000893{
Paul Bakker23986e52011-04-24 08:57:21 +0000894 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000895 MPI_VALIDATE_RET( X != NULL );
896 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000897
Paul Bakker23986e52011-04-24 08:57:21 +0000898 for( i = X->n; i > 0; i-- )
899 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000900 break;
901
Paul Bakker23986e52011-04-24 08:57:21 +0000902 for( j = Y->n; j > 0; j-- )
903 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000904 break;
905
Paul Bakker23986e52011-04-24 08:57:21 +0000906 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000907 return( 0 );
908
909 if( i > j ) return( 1 );
910 if( j > i ) return( -1 );
911
Paul Bakker23986e52011-04-24 08:57:21 +0000912 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000913 {
Paul Bakker23986e52011-04-24 08:57:21 +0000914 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
915 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000916 }
917
918 return( 0 );
919}
920
921/*
922 * Compare signed values
923 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000925{
Paul Bakker23986e52011-04-24 08:57:21 +0000926 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000927 MPI_VALIDATE_RET( X != NULL );
928 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
Paul Bakker23986e52011-04-24 08:57:21 +0000930 for( i = X->n; i > 0; i-- )
931 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000932 break;
933
Paul Bakker23986e52011-04-24 08:57:21 +0000934 for( j = Y->n; j > 0; j-- )
935 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000936 break;
937
Paul Bakker23986e52011-04-24 08:57:21 +0000938 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 return( 0 );
940
941 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +0000942 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000943
944 if( X->s > 0 && Y->s < 0 ) return( 1 );
945 if( Y->s > 0 && X->s < 0 ) return( -1 );
946
Paul Bakker23986e52011-04-24 08:57:21 +0000947 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000948 {
Paul Bakker23986e52011-04-24 08:57:21 +0000949 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
950 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000951 }
952
953 return( 0 );
954}
955
956/*
957 * Compare signed values
958 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200959int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000960{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200961 mbedtls_mpi Y;
962 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +0000963 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000964
965 *p = ( z < 0 ) ? -z : z;
966 Y.s = ( z < 0 ) ? -1 : 1;
967 Y.n = 1;
968 Y.p = p;
969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000971}
972
973/*
974 * Unsigned addition: X = |A| + |B| (HAC 14.7)
975 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200976int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000977{
Paul Bakker23986e52011-04-24 08:57:21 +0000978 int ret;
979 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +0100980 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000981 MPI_VALIDATE_RET( X != NULL );
982 MPI_VALIDATE_RET( A != NULL );
983 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000984
985 if( X == B )
986 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000988 }
989
990 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +0200992
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000993 /*
994 * X should always be positive as a result of unsigned additions.
995 */
996 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000997
Paul Bakker23986e52011-04-24 08:57:21 +0000998 for( j = B->n; j > 0; j-- )
999 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 break;
1001
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001002 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001003
1004 o = B->p; p = X->p; c = 0;
1005
Janos Follath6c922682015-10-30 17:43:11 +01001006 /*
1007 * tmp is used because it might happen that p == o
1008 */
Paul Bakker23986e52011-04-24 08:57:21 +00001009 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001010 {
Janos Follath6c922682015-10-30 17:43:11 +01001011 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001013 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001014 }
1015
1016 while( c != 0 )
1017 {
1018 if( i >= X->n )
1019 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001021 p = X->p + i;
1022 }
1023
Paul Bakker2d319fd2012-09-16 21:34:26 +00001024 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 }
1026
1027cleanup:
1028
1029 return( ret );
1030}
1031
1032/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001034 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001036{
Paul Bakker23986e52011-04-24 08:57:21 +00001037 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001039
1040 for( i = c = 0; i < n; i++, s++, d++ )
1041 {
1042 z = ( *d < c ); *d -= c;
1043 c = ( *d < *s ) + z; *d -= *s;
1044 }
1045
1046 while( c != 0 )
1047 {
1048 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001049 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 }
1051}
1052
1053/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001054 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001056int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001057{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001058 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001059 int ret;
1060 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001061 MPI_VALIDATE_RET( X != NULL );
1062 MPI_VALIDATE_RET( A != NULL );
1063 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1066 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069
1070 if( X == B )
1071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001073 B = &TB;
1074 }
1075
1076 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001077 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001078
Paul Bakker1ef7a532009-06-20 10:50:55 +00001079 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001080 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001081 */
1082 X->s = 1;
1083
Paul Bakker5121ce52009-01-03 21:22:43 +00001084 ret = 0;
1085
Paul Bakker23986e52011-04-24 08:57:21 +00001086 for( n = B->n; n > 0; n-- )
1087 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 break;
1089
Paul Bakker23986e52011-04-24 08:57:21 +00001090 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001091
1092cleanup:
1093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001095
1096 return( ret );
1097}
1098
1099/*
1100 * Signed addition: X = A + B
1101 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001103{
Hanno Becker73d7d792018-12-11 10:35:51 +00001104 int ret, s;
1105 MPI_VALIDATE_RET( X != NULL );
1106 MPI_VALIDATE_RET( A != NULL );
1107 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001108
Hanno Becker73d7d792018-12-11 10:35:51 +00001109 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 if( A->s * B->s < 0 )
1111 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001112 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001113 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001115 X->s = s;
1116 }
1117 else
1118 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001120 X->s = -s;
1121 }
1122 }
1123 else
1124 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001126 X->s = s;
1127 }
1128
1129cleanup:
1130
1131 return( ret );
1132}
1133
1134/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001135 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001136 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001137int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001138{
Hanno Becker73d7d792018-12-11 10:35:51 +00001139 int ret, s;
1140 MPI_VALIDATE_RET( X != NULL );
1141 MPI_VALIDATE_RET( A != NULL );
1142 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001143
Hanno Becker73d7d792018-12-11 10:35:51 +00001144 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001145 if( A->s * B->s > 0 )
1146 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001147 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001148 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001150 X->s = s;
1151 }
1152 else
1153 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001154 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001155 X->s = -s;
1156 }
1157 }
1158 else
1159 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161 X->s = s;
1162 }
1163
1164cleanup:
1165
1166 return( ret );
1167}
1168
1169/*
1170 * Signed addition: X = A + b
1171 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001172int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001173{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001174 mbedtls_mpi _B;
1175 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001176 MPI_VALIDATE_RET( X != NULL );
1177 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001178
1179 p[0] = ( b < 0 ) ? -b : b;
1180 _B.s = ( b < 0 ) ? -1 : 1;
1181 _B.n = 1;
1182 _B.p = p;
1183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001184 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001185}
1186
1187/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001188 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001191{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 mbedtls_mpi _B;
1193 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001194 MPI_VALIDATE_RET( X != NULL );
1195 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
1197 p[0] = ( b < 0 ) ? -b : b;
1198 _B.s = ( b < 0 ) ? -1 : 1;
1199 _B.n = 1;
1200 _B.p = p;
1201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203}
1204
1205/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001207 */
1208static
1209#if defined(__APPLE__) && defined(__arm__)
1210/*
1211 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1212 * appears to need this to prevent bad ARM code generation at -O3.
1213 */
1214__attribute__ ((noinline))
1215#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216void 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 +00001217{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001219
1220#if defined(MULADDC_HUIT)
1221 for( ; i >= 8; i -= 8 )
1222 {
1223 MULADDC_INIT
1224 MULADDC_HUIT
1225 MULADDC_STOP
1226 }
1227
1228 for( ; i > 0; i-- )
1229 {
1230 MULADDC_INIT
1231 MULADDC_CORE
1232 MULADDC_STOP
1233 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001234#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001235 for( ; i >= 16; i -= 16 )
1236 {
1237 MULADDC_INIT
1238 MULADDC_CORE MULADDC_CORE
1239 MULADDC_CORE MULADDC_CORE
1240 MULADDC_CORE MULADDC_CORE
1241 MULADDC_CORE MULADDC_CORE
1242
1243 MULADDC_CORE MULADDC_CORE
1244 MULADDC_CORE MULADDC_CORE
1245 MULADDC_CORE MULADDC_CORE
1246 MULADDC_CORE MULADDC_CORE
1247 MULADDC_STOP
1248 }
1249
1250 for( ; i >= 8; i -= 8 )
1251 {
1252 MULADDC_INIT
1253 MULADDC_CORE MULADDC_CORE
1254 MULADDC_CORE MULADDC_CORE
1255
1256 MULADDC_CORE MULADDC_CORE
1257 MULADDC_CORE MULADDC_CORE
1258 MULADDC_STOP
1259 }
1260
1261 for( ; i > 0; i-- )
1262 {
1263 MULADDC_INIT
1264 MULADDC_CORE
1265 MULADDC_STOP
1266 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001267#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001268
1269 t++;
1270
1271 do {
1272 *d += c; c = ( *d < c ); d++;
1273 }
1274 while( c != 0 );
1275}
1276
1277/*
1278 * Baseline multiplication: X = A * B (HAC 14.12)
1279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001281{
Paul Bakker23986e52011-04-24 08:57:21 +00001282 int ret;
1283 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001285 MPI_VALIDATE_RET( X != NULL );
1286 MPI_VALIDATE_RET( A != NULL );
1287 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1292 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001293
Paul Bakker23986e52011-04-24 08:57:21 +00001294 for( i = A->n; i > 0; i-- )
1295 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001296 break;
1297
Paul Bakker23986e52011-04-24 08:57:21 +00001298 for( j = B->n; j > 0; j-- )
1299 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001300 break;
1301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001302 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1303 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001304
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001305 for( ; j > 0; j-- )
1306 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001307
1308 X->s = A->s * B->s;
1309
1310cleanup:
1311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001312 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001313
1314 return( ret );
1315}
1316
1317/*
1318 * Baseline multiplication: X = A * b
1319 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001320int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001321{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 mbedtls_mpi _B;
1323 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001324 MPI_VALIDATE_RET( X != NULL );
1325 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001326
1327 _B.s = 1;
1328 _B.n = 1;
1329 _B.p = p;
1330 p[0] = b;
1331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001333}
1334
1335/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001336 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1337 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001338 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001339static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1340 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001341{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001342#if defined(MBEDTLS_HAVE_UDBL)
1343 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001344#else
Simon Butcher9803d072016-01-03 00:24:34 +00001345 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1346 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001347 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1348 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001349 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001350#endif
1351
Simon Butcher15b15d12015-11-26 19:35:03 +00001352 /*
1353 * Check for overflow
1354 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001355 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001356 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001357 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001358
Simon Butcherf5ba0452015-12-27 23:01:55 +00001359 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001360 }
1361
1362#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001363 dividend = (mbedtls_t_udbl) u1 << biL;
1364 dividend |= (mbedtls_t_udbl) u0;
1365 quotient = dividend / d;
1366 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1367 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1368
1369 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001370 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001371
1372 return (mbedtls_mpi_uint) quotient;
1373#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001374
1375 /*
1376 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1377 * Vol. 2 - Seminumerical Algorithms, Knuth
1378 */
1379
1380 /*
1381 * Normalize the divisor, d, and dividend, u0, u1
1382 */
1383 s = mbedtls_clz( d );
1384 d = d << s;
1385
1386 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001387 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001388 u0 = u0 << s;
1389
1390 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001391 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001392
1393 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001394 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001395
1396 /*
1397 * Find the first quotient and remainder
1398 */
1399 q1 = u1 / d1;
1400 r0 = u1 - d1 * q1;
1401
1402 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1403 {
1404 q1 -= 1;
1405 r0 += d1;
1406
1407 if ( r0 >= radix ) break;
1408 }
1409
Simon Butcherf5ba0452015-12-27 23:01:55 +00001410 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001411 q0 = rAX / d1;
1412 r0 = rAX - q0 * d1;
1413
1414 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1415 {
1416 q0 -= 1;
1417 r0 += d1;
1418
1419 if ( r0 >= radix ) break;
1420 }
1421
1422 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001423 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001424
1425 quotient = q1 * radix + q0;
1426
1427 return quotient;
1428#endif
1429}
1430
1431/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001433 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001434int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1435 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001436{
Paul Bakker23986e52011-04-24 08:57:21 +00001437 int ret;
1438 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001440 MPI_VALIDATE_RET( A != NULL );
1441 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1444 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1447 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001450 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1452 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001453 return( 0 );
1454 }
1455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001456 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1457 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001458 X.s = Y.s = 1;
1459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1461 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1462 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1463 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001464
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001465 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001466 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001467 {
1468 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1470 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001471 }
1472 else k = 0;
1473
1474 n = X.n - 1;
1475 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001479 {
1480 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001484
1485 for( i = n; i > t ; i-- )
1486 {
1487 if( X.p[i] >= Y.p[t] )
1488 Z.p[i - t - 1] = ~0;
1489 else
1490 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001491 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1492 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001493 }
1494
1495 Z.p[i - t - 1]++;
1496 do
1497 {
1498 Z.p[i - t - 1]--;
1499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001500 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001501 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001502 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001505 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001506 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1507 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 T2.p[2] = X.p[i];
1509 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1513 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1514 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001517 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001518 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1519 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1520 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521 Z.p[i - t - 1]--;
1522 }
1523 }
1524
1525 if( Q != NULL )
1526 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001527 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001528 Q->s = A->s * B->s;
1529 }
1530
1531 if( R != NULL )
1532 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001533 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001534 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001535 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001538 R->s = 1;
1539 }
1540
1541cleanup:
1542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1544 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001545
1546 return( ret );
1547}
1548
1549/*
1550 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001551 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001552int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1553 const mbedtls_mpi *A,
1554 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001555{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 mbedtls_mpi _B;
1557 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001558 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001559
1560 p[0] = ( b < 0 ) ? -b : b;
1561 _B.s = ( b < 0 ) ? -1 : 1;
1562 _B.n = 1;
1563 _B.p = p;
1564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001566}
1567
1568/*
1569 * Modulo: R = A mod B
1570 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001572{
1573 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001574 MPI_VALIDATE_RET( R != NULL );
1575 MPI_VALIDATE_RET( A != NULL );
1576 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1579 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1584 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1587 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001588
1589cleanup:
1590
1591 return( ret );
1592}
1593
1594/*
1595 * Modulo: r = A mod b
1596 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001598{
Paul Bakker23986e52011-04-24 08:57:21 +00001599 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001600 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001601 MPI_VALIDATE_RET( r != NULL );
1602 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001603
1604 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001606
1607 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001609
1610 /*
1611 * handle trivial cases
1612 */
1613 if( b == 1 )
1614 {
1615 *r = 0;
1616 return( 0 );
1617 }
1618
1619 if( b == 2 )
1620 {
1621 *r = A->p[0] & 1;
1622 return( 0 );
1623 }
1624
1625 /*
1626 * general case
1627 */
Paul Bakker23986e52011-04-24 08:57:21 +00001628 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001629 {
Paul Bakker23986e52011-04-24 08:57:21 +00001630 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001631 y = ( y << biH ) | ( x >> biH );
1632 z = y / b;
1633 y -= z * b;
1634
1635 x <<= biH;
1636 y = ( y << biH ) | ( x >> biH );
1637 z = y / b;
1638 y -= z * b;
1639 }
1640
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001641 /*
1642 * If A is negative, then the current y represents a negative value.
1643 * Flipping it to the positive side.
1644 */
1645 if( A->s < 0 && y != 0 )
1646 y = b - y;
1647
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 *r = y;
1649
1650 return( 0 );
1651}
1652
1653/*
1654 * Fast Montgomery initialization (thanks to Tom St Denis)
1655 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001656static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001657{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001659 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001660
1661 x = m0;
1662 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001664 for( i = biL; i >= 8; i /= 2 )
1665 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
1667 *mm = ~x + 1;
1668}
1669
1670/*
1671 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1672 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001673static 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 +02001674 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001675{
Paul Bakker23986e52011-04-24 08:57:21 +00001676 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001679 if( T->n < N->n + 1 || T->p == NULL )
1680 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1681
Paul Bakker5121ce52009-01-03 21:22:43 +00001682 memset( T->p, 0, T->n * ciL );
1683
1684 d = T->p;
1685 n = N->n;
1686 m = ( B->n < n ) ? B->n : n;
1687
1688 for( i = 0; i < n; i++ )
1689 {
1690 /*
1691 * T = (T + u0*B + u1*N) / 2^biL
1692 */
1693 u0 = A->p[i];
1694 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1695
1696 mpi_mul_hlp( m, B->p, d, u0 );
1697 mpi_mul_hlp( n, N->p, d, u1 );
1698
1699 *d++ = u0; d[n + 1] = 0;
1700 }
1701
Paul Bakker66d5d072014-06-17 16:39:18 +02001702 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001705 mpi_sub_hlp( n, N->p, A->p );
1706 else
1707 /* prevent timing attacks */
1708 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001709
1710 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001711}
1712
1713/*
1714 * Montgomery reduction: A = A * R^-1 mod N
1715 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001716static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1717 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001718{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 mbedtls_mpi_uint z = 1;
1720 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
Paul Bakker8ddb6452013-02-27 14:56:33 +01001722 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001723 U.p = &z;
1724
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001725 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726}
1727
1728/*
1729 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1730 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001731int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1732 const mbedtls_mpi *E, const mbedtls_mpi *N,
1733 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001734{
Paul Bakker23986e52011-04-24 08:57:21 +00001735 int ret;
1736 size_t wbits, wsize, one = 1;
1737 size_t i, j, nblimbs;
1738 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 mbedtls_mpi_uint ei, mm, state;
1740 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001741 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001742
Hanno Becker73d7d792018-12-11 10:35:51 +00001743 MPI_VALIDATE_RET( X != NULL );
1744 MPI_VALIDATE_RET( A != NULL );
1745 MPI_VALIDATE_RET( E != NULL );
1746 MPI_VALIDATE_RET( N != NULL );
1747
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001748 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001751 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1752 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001753
1754 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001755 * Init temps and window size
1756 */
1757 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1759 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 memset( W, 0, sizeof( W ) );
1761
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001762 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001763
1764 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1765 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1766
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001767 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1768 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001769
Paul Bakker5121ce52009-01-03 21:22:43 +00001770 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001771 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1772 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1773 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001774
1775 /*
Paul Bakker50546922012-05-19 08:40:49 +00001776 * Compensate for negative A (and correct at the end)
1777 */
1778 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001779 if( neg )
1780 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001781 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001782 Apos.s = 1;
1783 A = &Apos;
1784 }
1785
1786 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001787 * If 1st call, pre-compute R^2 mod N
1788 */
1789 if( _RR == NULL || _RR->p == NULL )
1790 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1792 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1793 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001794
1795 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001796 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001797 }
1798 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001800
1801 /*
1802 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1803 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1805 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001806 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001808
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001809 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
1811 /*
1812 * X = R^2 * R^-1 mod N = R mod N
1813 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001815 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001816
1817 if( wsize > 1 )
1818 {
1819 /*
1820 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1821 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001822 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1825 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001826
1827 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001828 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001829
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 /*
1831 * W[i] = W[i - 1] * W[1]
1832 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001833 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001834 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1836 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001837
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001838 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001839 }
1840 }
1841
1842 nblimbs = E->n;
1843 bufsize = 0;
1844 nbits = 0;
1845 wbits = 0;
1846 state = 0;
1847
1848 while( 1 )
1849 {
1850 if( bufsize == 0 )
1851 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001852 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 break;
1854
Paul Bakker0d7702c2013-10-29 16:18:35 +01001855 nblimbs--;
1856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001858 }
1859
1860 bufsize--;
1861
1862 ei = (E->p[nblimbs] >> bufsize) & 1;
1863
1864 /*
1865 * skip leading 0s
1866 */
1867 if( ei == 0 && state == 0 )
1868 continue;
1869
1870 if( ei == 0 && state == 1 )
1871 {
1872 /*
1873 * out of window, square X
1874 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001875 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001876 continue;
1877 }
1878
1879 /*
1880 * add ei to current window
1881 */
1882 state = 2;
1883
1884 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001885 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
1887 if( nbits == wsize )
1888 {
1889 /*
1890 * X = X^wsize R^-1 mod N
1891 */
1892 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001893 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894
1895 /*
1896 * X = X * W[wbits] R^-1 mod N
1897 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001898 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001899
1900 state--;
1901 nbits = 0;
1902 wbits = 0;
1903 }
1904 }
1905
1906 /*
1907 * process the remaining bits
1908 */
1909 for( i = 0; i < nbits; i++ )
1910 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001911 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001912
1913 wbits <<= 1;
1914
Paul Bakker66d5d072014-06-17 16:39:18 +02001915 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001916 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 }
1918
1919 /*
1920 * X = A^E * R * R^-1 mod N = A^E mod N
1921 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001922 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923
Hanno Beckera4af1c42017-04-18 09:07:45 +01001924 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00001925 {
1926 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001928 }
1929
Paul Bakker5121ce52009-01-03 21:22:43 +00001930cleanup:
1931
Paul Bakker66d5d072014-06-17 16:39:18 +02001932 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001934
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001935 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00001936
Paul Bakker75a28602014-03-31 12:08:17 +02001937 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00001939
1940 return( ret );
1941}
1942
Paul Bakker5121ce52009-01-03 21:22:43 +00001943/*
1944 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1945 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001947{
Paul Bakker23986e52011-04-24 08:57:21 +00001948 int ret;
1949 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001951
Hanno Becker73d7d792018-12-11 10:35:51 +00001952 MPI_VALIDATE_RET( G != NULL );
1953 MPI_VALIDATE_RET( A != NULL );
1954 MPI_VALIDATE_RET( B != NULL );
1955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1959 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 lz = mbedtls_mpi_lsb( &TA );
1962 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001963
Paul Bakker66d5d072014-06-17 16:39:18 +02001964 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001965 lz = lzt;
1966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001967 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1968 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001969
Paul Bakker5121ce52009-01-03 21:22:43 +00001970 TA.s = TB.s = 1;
1971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001973 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1975 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001979 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1980 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001981 }
1982 else
1983 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001984 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1985 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001986 }
1987 }
1988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1990 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001991
1992cleanup:
1993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
1996 return( ret );
1997}
1998
Paul Bakker33dc46b2014-04-30 16:11:39 +02001999/*
2000 * Fill X with size bytes of random.
2001 *
2002 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002003 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002004 * deterministic, eg for tests).
2005 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002007 int (*f_rng)(void *, unsigned char *, size_t),
2008 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002009{
Paul Bakker23986e52011-04-24 08:57:21 +00002010 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002011 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Hanno Becker73d7d792018-12-11 10:35:51 +00002012 MPI_VALIDATE_RET( X != NULL );
2013 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 if( size > MBEDTLS_MPI_MAX_SIZE )
2016 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker287781a2011-03-26 13:18:49 +00002017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
2019 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002020
2021cleanup:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05002022 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002023 return( ret );
2024}
2025
Paul Bakker5121ce52009-01-03 21:22:43 +00002026/*
2027 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2028 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002030{
2031 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002033 MPI_VALIDATE_RET( X != NULL );
2034 MPI_VALIDATE_RET( A != NULL );
2035 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
Hanno Becker4bcb4912017-04-18 15:49:39 +01002037 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2041 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2042 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002047 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 goto cleanup;
2050 }
2051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2053 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2054 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2055 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2058 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2059 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2060 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002061
2062 do
2063 {
2064 while( ( TU.p[0] & 1 ) == 0 )
2065 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002067
2068 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2069 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2071 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002072 }
2073
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002074 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2075 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002076 }
2077
2078 while( ( TV.p[0] & 1 ) == 0 )
2079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002080 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
2082 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2083 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2085 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086 }
2087
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2089 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 }
2091
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002093 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2095 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2096 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097 }
2098 else
2099 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002100 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2101 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2102 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002103 }
2104 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002105 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002107 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2108 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2111 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002114
2115cleanup:
2116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2118 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2119 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
2121 return( ret );
2122}
2123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002124#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002125
Paul Bakker5121ce52009-01-03 21:22:43 +00002126static const int small_prime[] =
2127{
2128 3, 5, 7, 11, 13, 17, 19, 23,
2129 29, 31, 37, 41, 43, 47, 53, 59,
2130 61, 67, 71, 73, 79, 83, 89, 97,
2131 101, 103, 107, 109, 113, 127, 131, 137,
2132 139, 149, 151, 157, 163, 167, 173, 179,
2133 181, 191, 193, 197, 199, 211, 223, 227,
2134 229, 233, 239, 241, 251, 257, 263, 269,
2135 271, 277, 281, 283, 293, 307, 311, 313,
2136 317, 331, 337, 347, 349, 353, 359, 367,
2137 373, 379, 383, 389, 397, 401, 409, 419,
2138 421, 431, 433, 439, 443, 449, 457, 461,
2139 463, 467, 479, 487, 491, 499, 503, 509,
2140 521, 523, 541, 547, 557, 563, 569, 571,
2141 577, 587, 593, 599, 601, 607, 613, 617,
2142 619, 631, 641, 643, 647, 653, 659, 661,
2143 673, 677, 683, 691, 701, 709, 719, 727,
2144 733, 739, 743, 751, 757, 761, 769, 773,
2145 787, 797, 809, 811, 821, 823, 827, 829,
2146 839, 853, 857, 859, 863, 877, 881, 883,
2147 887, 907, 911, 919, 929, 937, 941, 947,
2148 953, 967, 971, 977, 983, 991, 997, -103
2149};
2150
2151/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002152 * Small divisors test (X must be positive)
2153 *
2154 * Return values:
2155 * 0: no small factor (possible prime, more tests needed)
2156 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002158 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002159 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002161{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002162 int ret = 0;
2163 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002164 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002165
Paul Bakker5121ce52009-01-03 21:22:43 +00002166 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002168
2169 for( i = 0; small_prime[i] > 0; i++ )
2170 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002172 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
2176 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002178 }
2179
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002180cleanup:
2181 return( ret );
2182}
2183
2184/*
2185 * Miller-Rabin pseudo-primality test (HAC 4.24)
2186 */
Janos Follathda31fa12018-09-03 14:45:23 +01002187static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002188 int (*f_rng)(void *, unsigned char *, size_t),
2189 void *p_rng )
2190{
Pascal Junodb99183d2015-03-11 16:49:45 +01002191 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002192 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002194
Hanno Becker73d7d792018-12-11 10:35:51 +00002195 MPI_VALIDATE_RET( X != NULL );
2196 MPI_VALIDATE_RET( f_rng != NULL );
2197
2198 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2199 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002201
Paul Bakker5121ce52009-01-03 21:22:43 +00002202 /*
2203 * W = |X| - 1
2204 * R = W >> lsb( W )
2205 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2207 s = mbedtls_mpi_lsb( &W );
2208 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2209 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002211 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002212
Janos Follathda31fa12018-09-03 14:45:23 +01002213 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002214 {
2215 /*
2216 * pick a random A, 1 < A < |X| - 1
2217 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002218 count = 0;
2219 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002220 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002221
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002222 j = mbedtls_mpi_bitlen( &A );
2223 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002224 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002225 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002226 }
2227
2228 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002229 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002230 }
2231
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002232 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2233 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002234
2235 /*
2236 * A = A^R mod |X|
2237 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2241 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002242 continue;
2243
2244 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002245 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002246 {
2247 /*
2248 * A = A * A mod |X|
2249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2251 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002254 break;
2255
2256 j++;
2257 }
2258
2259 /*
2260 * not prime if A != |X| - 1 or A == 1
2261 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2263 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002266 break;
2267 }
2268 }
2269
2270cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002271 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2272 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
2275 return( ret );
2276}
2277
2278/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002279 * Pseudo-primality test: small factors, then Miller-Rabin
2280 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002281int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2282 int (*f_rng)(void *, unsigned char *, size_t),
2283 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002284{
2285 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 mbedtls_mpi XX;
Hanno Becker73d7d792018-12-11 10:35:51 +00002287 MPI_VALIDATE_RET( X != NULL );
2288 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002289
2290 XX.s = 1;
2291 XX.n = X->n;
2292 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2295 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2296 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002299 return( 0 );
2300
2301 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2302 {
2303 if( ret == 1 )
2304 return( 0 );
2305
2306 return( ret );
2307 }
2308
Janos Follathda31fa12018-09-03 14:45:23 +01002309 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002310}
2311
Janos Follatha0b67c22018-09-18 14:48:23 +01002312#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002313/*
2314 * Pseudo-primality test, error probability 2^-80
2315 */
2316int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2317 int (*f_rng)(void *, unsigned char *, size_t),
2318 void *p_rng )
2319{
Hanno Becker73d7d792018-12-11 10:35:51 +00002320 MPI_VALIDATE_RET( X != NULL );
2321 MPI_VALIDATE_RET( f_rng != NULL );
2322
Janos Follatha0b67c22018-09-18 14:48:23 +01002323 /*
2324 * In the past our key generation aimed for an error rate of at most
2325 * 2^-80. Since this function is deprecated, aim for the same certainty
2326 * here as well.
2327 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002328 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002329}
Janos Follatha0b67c22018-09-18 14:48:23 +01002330#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002331
2332/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002333 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002334 *
Janos Follathf301d232018-08-14 13:34:01 +01002335 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2336 * be either 1024 bits or 1536 bits long, and flags must contain
2337 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002338 */
Janos Follath7c025a92018-08-14 11:08:41 +01002339int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002340 int (*f_rng)(void *, unsigned char *, size_t),
2341 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002342{
Jethro Beekman66689272018-02-14 19:24:10 -08002343#ifdef MBEDTLS_HAVE_INT64
2344// ceil(2^63.5)
2345#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2346#else
2347// ceil(2^31.5)
2348#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2349#endif
2350 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002351 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002352 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 mbedtls_mpi_uint r;
2354 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
Hanno Becker73d7d792018-12-11 10:35:51 +00002356 MPI_VALIDATE_RET( X != NULL );
2357 MPI_VALIDATE_RET( f_rng != NULL );
2358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2360 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002363
2364 n = BITS_TO_LIMBS( nbits );
2365
Janos Follathda31fa12018-09-03 14:45:23 +01002366 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2367 {
2368 /*
2369 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2370 */
2371 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2372 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2373 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2374 }
2375 else
2376 {
2377 /*
2378 * 2^-100 error probability, number of rounds computed based on HAC,
2379 * fact 4.48
2380 */
2381 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2382 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2383 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2384 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2385 }
2386
Jethro Beekman66689272018-02-14 19:24:10 -08002387 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002388 {
Jethro Beekman66689272018-02-14 19:24:10 -08002389 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2390 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2391 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2392
2393 k = n * biL;
2394 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2395 X->p[0] |= 1;
2396
Janos Follath7c025a92018-08-14 11:08:41 +01002397 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002399 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002402 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002403 }
Jethro Beekman66689272018-02-14 19:24:10 -08002404 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002405 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002406 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002407 * An necessary condition for Y and X = 2Y + 1 to be prime
2408 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2409 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002410 */
Jethro Beekman66689272018-02-14 19:24:10 -08002411
2412 X->p[0] |= 2;
2413
2414 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2415 if( r == 0 )
2416 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2417 else if( r == 1 )
2418 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2419
2420 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2421 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2422 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2423
2424 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002425 {
Jethro Beekman66689272018-02-14 19:24:10 -08002426 /*
2427 * First, check small factors for X and Y
2428 * before doing Miller-Rabin on any of them
2429 */
2430 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2431 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002432 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002433 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002434 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002435 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002436 goto cleanup;
2437
2438 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2439 goto cleanup;
2440
2441 /*
2442 * Next candidates. We want to preserve Y = (X-1) / 2 and
2443 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2444 * so up Y by 6 and X by 12.
2445 */
2446 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2447 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002449 }
2450 }
2451
2452cleanup:
2453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002454 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002455
2456 return( ret );
2457}
2458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
Paul Bakker23986e52011-04-24 08:57:21 +00002463#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002464
2465static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2466{
2467 { 693, 609, 21 },
2468 { 1764, 868, 28 },
2469 { 768454923, 542167814, 1 }
2470};
2471
Paul Bakker5121ce52009-01-03 21:22:43 +00002472/*
2473 * Checkup routine
2474 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002476{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002477 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2481 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002484 "EFE021C2645FD1DC586E69184AF4A31E" \
2485 "D5F53E93B5F123FA41680867BA110131" \
2486 "944FE7952E2517337780CB0DB80E61AA" \
2487 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002490 "B2E7EFD37075B9F03FF989C7C5051C20" \
2491 "34D2A323810251127E7BF8625A4F49A5" \
2492 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2493 "5B5C25763222FEFCCFC38B832366C29E" ) );
2494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002496 "0066A198186C18C10B2F5ED9B522752A" \
2497 "9830B69916E535C8F047518A889A43A5" \
2498 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002503 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2504 "9E857EA95A03512E2BAE7391688D264A" \
2505 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2506 "8001B72E848A38CAE1C65F78E56ABDEF" \
2507 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2508 "ECF677152EF804370C1A305CAF3B5BF1" \
2509 "30879B56C61DE584A0F53A2447A51E" ) );
2510
2511 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002515 {
2516 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002518
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002519 ret = 1;
2520 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002521 }
2522
2523 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002528 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002529 "256567336059E52CAE22925474705F39A94" ) );
2530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002531 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002532 "6613F26162223DF488E9CD48CC132C7A" \
2533 "0AC93C701B001B092E4E5B9F73BCD27B" \
2534 "9EE50D0657C77F374E903CDFA4C642" ) );
2535
2536 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002539 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2540 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002541 {
2542 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002544
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002545 ret = 1;
2546 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002547 }
2548
2549 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002555 "36E139AEA55215609D2816998ED020BB" \
2556 "BD96C37890F65171D948E9BC7CBAA4D9" \
2557 "325D24D6A3C12710F10A09FA08AB87" ) );
2558
2559 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002560 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002563 {
2564 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002566
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002567 ret = 1;
2568 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002569 }
2570
2571 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002577 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2578 "C3DBA76456363A10869622EAC2DD84EC" \
2579 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2580
2581 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002585 {
2586 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002588
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002589 ret = 1;
2590 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002591 }
2592
2593 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002595
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002596 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002598
Paul Bakker66d5d072014-06-17 16:39:18 +02002599 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002600 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2602 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002607 {
2608 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002609 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002610
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002611 ret = 1;
2612 goto cleanup;
2613 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002614 }
2615
2616 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002618
Paul Bakker5121ce52009-01-03 21:22:43 +00002619cleanup:
2620
2621 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002623
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2625 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002626
2627 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002628 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002629
2630 return( ret );
2631}
2632
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002633#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635#endif /* MBEDTLS_BIGNUM_C */