blob: d3d02b1a03b5fe5566d70461fc8e6d760b1a0461 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
530 * Helper to write the digits high-order first
531 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
Paul Bakker5121ce52009-01-03 21:22:43 +0000533{
534 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536
537 if( radix < 2 || radix > 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
541 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
544 MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000545
546 if( r < 10 )
547 *(*p)++ = (char)( r + 0x30 );
548 else
549 *(*p)++ = (char)( r + 0x37 );
550
551cleanup:
552
553 return( ret );
554}
555
556/*
557 * Export into an ASCII string
558 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100559int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
560 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000561{
Paul Bakker23986e52011-04-24 08:57:21 +0000562 int ret = 0;
563 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000564 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000566 MPI_VALIDATE_RET( X != NULL );
567 MPI_VALIDATE_RET( olen != NULL );
568 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
570 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000571 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000572
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200573 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000574 if( radix >= 4 ) n >>= 1;
575 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000576 /*
577 * Round up the buffer length to an even value to ensure that there is
578 * enough room for hexadecimal values that can be represented in an odd
579 * number of digits.
580 */
581 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100583 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100585 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000587 }
588
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100589 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
592 if( X->s == -1 )
593 *p++ = '-';
594
595 if( radix == 16 )
596 {
Paul Bakker23986e52011-04-24 08:57:21 +0000597 int c;
598 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Paul Bakker23986e52011-04-24 08:57:21 +0000600 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 {
Paul Bakker23986e52011-04-24 08:57:21 +0000602 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 {
Paul Bakker23986e52011-04-24 08:57:21 +0000604 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000605
Paul Bakker6c343d72014-07-10 14:36:19 +0200606 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000607 continue;
608
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000609 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000610 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 k = 1;
612 }
613 }
614 }
615 else
616 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000618
619 if( T.s == -1 )
620 T.s = 1;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 }
624
625 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100626 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000627
628cleanup:
629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 return( ret );
633}
634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000636/*
637 * Read X from an opened file
638 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000640{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000642 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000644 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000645 * Buffer should have space for (short) label and decimal formatted MPI,
646 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000647 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
Hanno Becker73d7d792018-12-11 10:35:51 +0000650 MPI_VALIDATE_RET( X != NULL );
651 MPI_VALIDATE_RET( fin != NULL );
652
653 if( radix < 2 || radix > 16 )
654 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
655
Paul Bakker5121ce52009-01-03 21:22:43 +0000656 memset( s, 0, sizeof( s ) );
657 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
660 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000661 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000663
Hanno Beckerb2034b72017-04-26 11:46:46 +0100664 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
665 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000666
667 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100668 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000669 if( mpi_get_digit( &d, radix, *p ) != 0 )
670 break;
671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000673}
674
675/*
676 * Write X into an opened file (or stdout if fout == NULL)
677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000679{
Paul Bakker23986e52011-04-24 08:57:21 +0000680 int ret;
681 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000682 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000683 * Buffer should have space for (short) label and decimal formatted MPI,
684 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000685 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000687 MPI_VALIDATE_RET( X != NULL );
688
689 if( radix < 2 || radix > 16 )
690 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100692 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100694 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
696 if( p == NULL ) p = "";
697
698 plen = strlen( p );
699 slen = strlen( s );
700 s[slen++] = '\r';
701 s[slen++] = '\n';
702
703 if( fout != NULL )
704 {
705 if( fwrite( p, 1, plen, fout ) != plen ||
706 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000708 }
709 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
712cleanup:
713
714 return( ret );
715}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000717
Hanno Beckerda1655a2017-10-18 14:21:44 +0100718
719/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
720 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000721
722static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
723{
724 uint8_t i;
725 mbedtls_mpi_uint tmp = 0;
726 /* This works regardless of the endianness. */
727 for( i = 0; i < ciL; i++, x >>= 8 )
728 tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
729 return( tmp );
730}
731
732static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
733{
734#if defined(__BYTE_ORDER__)
735
736/* Nothing to do on bigendian systems. */
737#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
738 return( x );
739#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
740
741#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
742
743/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000744#if defined(__GNUC__) && defined(__GNUC_PREREQ)
745#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000746#define have_bswap
747#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000748#endif
749
750#if defined(__clang__) && defined(__has_builtin)
751#if __has_builtin(__builtin_bswap32) && \
752 __has_builtin(__builtin_bswap64)
753#define have_bswap
754#endif
755#endif
756
Hanno Beckerf8720072018-11-08 11:53:49 +0000757#if defined(have_bswap)
758 /* The compiler is hopefully able to statically evaluate this! */
759 switch( sizeof(mbedtls_mpi_uint) )
760 {
761 case 4:
762 return( __builtin_bswap32(x) );
763 case 8:
764 return( __builtin_bswap64(x) );
765 }
766#endif
767#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
768#endif /* __BYTE_ORDER__ */
769
770 /* Fall back to C-based reordering if we don't know the byte order
771 * or we couldn't use a compiler-specific builtin. */
772 return( mpi_uint_bigendian_to_host_c( x ) );
773}
774
Hanno Becker2be8a552018-10-25 12:40:09 +0100775static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100776{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100777 mbedtls_mpi_uint *cur_limb_left;
778 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100779 if( limbs == 0 )
780 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100781
782 /*
783 * Traverse limbs and
784 * - adapt byte-order in each limb
785 * - swap the limbs themselves.
786 * For that, simultaneously traverse the limbs from left to right
787 * and from right to left, as long as the left index is not bigger
788 * than the right index (it's not a problem if limbs is odd and the
789 * indices coincide in the last iteration).
790 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100791 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
792 cur_limb_left <= cur_limb_right;
793 cur_limb_left++, cur_limb_right-- )
794 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000795 mbedtls_mpi_uint tmp;
796 /* Note that if cur_limb_left == cur_limb_right,
797 * this code effectively swaps the bytes only once. */
798 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
799 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
800 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100801 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100802}
803
Paul Bakker5121ce52009-01-03 21:22:43 +0000804/*
805 * Import X from unsigned binary data, big endian
806 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000808{
Paul Bakker23986e52011-04-24 08:57:21 +0000809 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100810 size_t const limbs = CHARS_TO_LIMBS( buflen );
811 size_t const overhead = ( limbs * ciL ) - buflen;
812 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000813
Hanno Becker8ce11a32018-12-19 16:18:52 +0000814 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000815 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
816
Hanno Becker073c1992017-10-17 15:17:27 +0100817 /* Ensure that target MPI has exactly the necessary number of limbs */
818 if( X->n != limbs )
819 {
820 mbedtls_mpi_free( X );
821 mbedtls_mpi_init( X );
822 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
823 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200824 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000825
Hanno Becker0e810b92019-01-03 17:13:11 +0000826 /* Avoid calling `memcpy` with NULL source argument,
827 * even if buflen is 0. */
828 if( buf != NULL )
829 {
830 Xp = (unsigned char*) X->p;
831 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100832
Hanno Becker0e810b92019-01-03 17:13:11 +0000833 mpi_bigendian_to_host( X->p, limbs );
834 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000835
836cleanup:
837
838 return( ret );
839}
840
841/*
842 * Export X into unsigned binary data, big endian
843 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100844int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
845 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000846{
Hanno Becker73d7d792018-12-11 10:35:51 +0000847 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100848 size_t bytes_to_copy;
849 unsigned char *p;
850 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000851
Hanno Becker73d7d792018-12-11 10:35:51 +0000852 MPI_VALIDATE_RET( X != NULL );
853 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
854
855 stored_bytes = X->n * ciL;
856
Gilles Peskine11cdb052018-11-20 16:47:47 +0100857 if( stored_bytes < buflen )
858 {
859 /* There is enough space in the output buffer. Write initial
860 * null bytes and record the position at which to start
861 * writing the significant bytes. In this case, the execution
862 * trace of this function does not depend on the value of the
863 * number. */
864 bytes_to_copy = stored_bytes;
865 p = buf + buflen - stored_bytes;
866 memset( buf, 0, buflen - stored_bytes );
867 }
868 else
869 {
870 /* The output buffer is smaller than the allocated size of X.
871 * However X may fit if its leading bytes are zero. */
872 bytes_to_copy = buflen;
873 p = buf;
874 for( i = bytes_to_copy; i < stored_bytes; i++ )
875 {
876 if( GET_BYTE( X, i ) != 0 )
877 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
878 }
879 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000880
Gilles Peskine11cdb052018-11-20 16:47:47 +0100881 for( i = 0; i < bytes_to_copy; i++ )
882 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000883
884 return( 0 );
885}
886
887/*
888 * Left-shift: X <<= count
889 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000891{
Paul Bakker23986e52011-04-24 08:57:21 +0000892 int ret;
893 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000895 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000896
897 v0 = count / (biL );
898 t1 = count & (biL - 1);
899
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200900 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000901
Paul Bakkerf9688572011-05-05 10:00:45 +0000902 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000904
905 ret = 0;
906
907 /*
908 * shift by count / limb_size
909 */
910 if( v0 > 0 )
911 {
Paul Bakker23986e52011-04-24 08:57:21 +0000912 for( i = X->n; i > v0; i-- )
913 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000914
Paul Bakker23986e52011-04-24 08:57:21 +0000915 for( ; i > 0; i-- )
916 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000917 }
918
919 /*
920 * shift by count % limb_size
921 */
922 if( t1 > 0 )
923 {
924 for( i = v0; i < X->n; i++ )
925 {
926 r1 = X->p[i] >> (biL - t1);
927 X->p[i] <<= t1;
928 X->p[i] |= r0;
929 r0 = r1;
930 }
931 }
932
933cleanup:
934
935 return( ret );
936}
937
938/*
939 * Right-shift: X >>= count
940 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000942{
Paul Bakker23986e52011-04-24 08:57:21 +0000943 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000945 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000946
947 v0 = count / biL;
948 v1 = count & (biL - 1);
949
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100950 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200951 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100952
Paul Bakker5121ce52009-01-03 21:22:43 +0000953 /*
954 * shift by count / limb_size
955 */
956 if( v0 > 0 )
957 {
958 for( i = 0; i < X->n - v0; i++ )
959 X->p[i] = X->p[i + v0];
960
961 for( ; i < X->n; i++ )
962 X->p[i] = 0;
963 }
964
965 /*
966 * shift by count % limb_size
967 */
968 if( v1 > 0 )
969 {
Paul Bakker23986e52011-04-24 08:57:21 +0000970 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000971 {
Paul Bakker23986e52011-04-24 08:57:21 +0000972 r1 = X->p[i - 1] << (biL - v1);
973 X->p[i - 1] >>= v1;
974 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000975 r0 = r1;
976 }
977 }
978
979 return( 0 );
980}
981
982/*
983 * Compare unsigned values
984 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000986{
Paul Bakker23986e52011-04-24 08:57:21 +0000987 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +0000988 MPI_VALIDATE_RET( X != NULL );
989 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000990
Paul Bakker23986e52011-04-24 08:57:21 +0000991 for( i = X->n; i > 0; i-- )
992 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000993 break;
994
Paul Bakker23986e52011-04-24 08:57:21 +0000995 for( j = Y->n; j > 0; j-- )
996 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 break;
998
Paul Bakker23986e52011-04-24 08:57:21 +0000999 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 return( 0 );
1001
1002 if( i > j ) return( 1 );
1003 if( j > i ) return( -1 );
1004
Paul Bakker23986e52011-04-24 08:57:21 +00001005 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001006 {
Paul Bakker23986e52011-04-24 08:57:21 +00001007 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1008 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001009 }
1010
1011 return( 0 );
1012}
1013
1014/*
1015 * Compare signed values
1016 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018{
Paul Bakker23986e52011-04-24 08:57:21 +00001019 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001020 MPI_VALIDATE_RET( X != NULL );
1021 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001022
Paul Bakker23986e52011-04-24 08:57:21 +00001023 for( i = X->n; i > 0; i-- )
1024 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 break;
1026
Paul Bakker23986e52011-04-24 08:57:21 +00001027 for( j = Y->n; j > 0; j-- )
1028 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001029 break;
1030
Paul Bakker23986e52011-04-24 08:57:21 +00001031 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001032 return( 0 );
1033
1034 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001035 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001036
1037 if( X->s > 0 && Y->s < 0 ) return( 1 );
1038 if( Y->s > 0 && X->s < 0 ) return( -1 );
1039
Paul Bakker23986e52011-04-24 08:57:21 +00001040 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001041 {
Paul Bakker23986e52011-04-24 08:57:21 +00001042 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1043 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001044 }
1045
1046 return( 0 );
1047}
1048
1049/*
1050 * Compare signed values
1051 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001053{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054 mbedtls_mpi Y;
1055 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001056 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001057
1058 *p = ( z < 0 ) ? -z : z;
1059 Y.s = ( z < 0 ) ? -1 : 1;
1060 Y.n = 1;
1061 Y.p = p;
1062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001064}
1065
1066/*
1067 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1068 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001070{
Paul Bakker23986e52011-04-24 08:57:21 +00001071 int ret;
1072 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001073 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001074 MPI_VALIDATE_RET( X != NULL );
1075 MPI_VALIDATE_RET( A != NULL );
1076 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001077
1078 if( X == B )
1079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001081 }
1082
1083 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001084 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001085
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001086 /*
1087 * X should always be positive as a result of unsigned additions.
1088 */
1089 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001090
Paul Bakker23986e52011-04-24 08:57:21 +00001091 for( j = B->n; j > 0; j-- )
1092 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001093 break;
1094
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001096
1097 o = B->p; p = X->p; c = 0;
1098
Janos Follath6c922682015-10-30 17:43:11 +01001099 /*
1100 * tmp is used because it might happen that p == o
1101 */
Paul Bakker23986e52011-04-24 08:57:21 +00001102 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001103 {
Janos Follath6c922682015-10-30 17:43:11 +01001104 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001105 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001106 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001107 }
1108
1109 while( c != 0 )
1110 {
1111 if( i >= X->n )
1112 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001114 p = X->p + i;
1115 }
1116
Paul Bakker2d319fd2012-09-16 21:34:26 +00001117 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001118 }
1119
1120cleanup:
1121
1122 return( ret );
1123}
1124
1125/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001126 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001127 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001128static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001129{
Paul Bakker23986e52011-04-24 08:57:21 +00001130 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001131 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001132
1133 for( i = c = 0; i < n; i++, s++, d++ )
1134 {
1135 z = ( *d < c ); *d -= c;
1136 c = ( *d < *s ) + z; *d -= *s;
1137 }
1138
1139 while( c != 0 )
1140 {
1141 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001142 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 }
1144}
1145
1146/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001147 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001148 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001150{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001152 int ret;
1153 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001154 MPI_VALIDATE_RET( X != NULL );
1155 MPI_VALIDATE_RET( A != NULL );
1156 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001158 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1159 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001161 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001162
1163 if( X == B )
1164 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001165 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166 B = &TB;
1167 }
1168
1169 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001171
Paul Bakker1ef7a532009-06-20 10:50:55 +00001172 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001173 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001174 */
1175 X->s = 1;
1176
Paul Bakker5121ce52009-01-03 21:22:43 +00001177 ret = 0;
1178
Paul Bakker23986e52011-04-24 08:57:21 +00001179 for( n = B->n; n > 0; n-- )
1180 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001181 break;
1182
Paul Bakker23986e52011-04-24 08:57:21 +00001183 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
1185cleanup:
1186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001187 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001188
1189 return( ret );
1190}
1191
1192/*
1193 * Signed addition: X = A + B
1194 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001196{
Hanno Becker73d7d792018-12-11 10:35:51 +00001197 int ret, s;
1198 MPI_VALIDATE_RET( X != NULL );
1199 MPI_VALIDATE_RET( A != NULL );
1200 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001201
Hanno Becker73d7d792018-12-11 10:35:51 +00001202 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 if( A->s * B->s < 0 )
1204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001208 X->s = s;
1209 }
1210 else
1211 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001212 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001213 X->s = -s;
1214 }
1215 }
1216 else
1217 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001219 X->s = s;
1220 }
1221
1222cleanup:
1223
1224 return( ret );
1225}
1226
1227/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001228 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001229 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001231{
Hanno Becker73d7d792018-12-11 10:35:51 +00001232 int ret, s;
1233 MPI_VALIDATE_RET( X != NULL );
1234 MPI_VALIDATE_RET( A != NULL );
1235 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001236
Hanno Becker73d7d792018-12-11 10:35:51 +00001237 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 if( A->s * B->s > 0 )
1239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001243 X->s = s;
1244 }
1245 else
1246 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001248 X->s = -s;
1249 }
1250 }
1251 else
1252 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001254 X->s = s;
1255 }
1256
1257cleanup:
1258
1259 return( ret );
1260}
1261
1262/*
1263 * Signed addition: X = A + b
1264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001266{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 mbedtls_mpi _B;
1268 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001269 MPI_VALIDATE_RET( X != NULL );
1270 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001271
1272 p[0] = ( b < 0 ) ? -b : b;
1273 _B.s = ( b < 0 ) ? -1 : 1;
1274 _B.n = 1;
1275 _B.p = p;
1276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001278}
1279
1280/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001281 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001282 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001284{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 mbedtls_mpi _B;
1286 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001287 MPI_VALIDATE_RET( X != NULL );
1288 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001289
1290 p[0] = ( b < 0 ) ? -b : b;
1291 _B.s = ( b < 0 ) ? -1 : 1;
1292 _B.n = 1;
1293 _B.p = p;
1294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001295 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001296}
1297
1298/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001300 */
1301static
1302#if defined(__APPLE__) && defined(__arm__)
1303/*
1304 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1305 * appears to need this to prevent bad ARM code generation at -O3.
1306 */
1307__attribute__ ((noinline))
1308#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001309void 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 +00001310{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001312
1313#if defined(MULADDC_HUIT)
1314 for( ; i >= 8; i -= 8 )
1315 {
1316 MULADDC_INIT
1317 MULADDC_HUIT
1318 MULADDC_STOP
1319 }
1320
1321 for( ; i > 0; i-- )
1322 {
1323 MULADDC_INIT
1324 MULADDC_CORE
1325 MULADDC_STOP
1326 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001327#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001328 for( ; i >= 16; i -= 16 )
1329 {
1330 MULADDC_INIT
1331 MULADDC_CORE MULADDC_CORE
1332 MULADDC_CORE MULADDC_CORE
1333 MULADDC_CORE MULADDC_CORE
1334 MULADDC_CORE MULADDC_CORE
1335
1336 MULADDC_CORE MULADDC_CORE
1337 MULADDC_CORE MULADDC_CORE
1338 MULADDC_CORE MULADDC_CORE
1339 MULADDC_CORE MULADDC_CORE
1340 MULADDC_STOP
1341 }
1342
1343 for( ; i >= 8; i -= 8 )
1344 {
1345 MULADDC_INIT
1346 MULADDC_CORE MULADDC_CORE
1347 MULADDC_CORE MULADDC_CORE
1348
1349 MULADDC_CORE MULADDC_CORE
1350 MULADDC_CORE MULADDC_CORE
1351 MULADDC_STOP
1352 }
1353
1354 for( ; i > 0; i-- )
1355 {
1356 MULADDC_INIT
1357 MULADDC_CORE
1358 MULADDC_STOP
1359 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001360#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001361
1362 t++;
1363
1364 do {
1365 *d += c; c = ( *d < c ); d++;
1366 }
1367 while( c != 0 );
1368}
1369
1370/*
1371 * Baseline multiplication: X = A * B (HAC 14.12)
1372 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001373int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001374{
Paul Bakker23986e52011-04-24 08:57:21 +00001375 int ret;
1376 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001378 MPI_VALIDATE_RET( X != NULL );
1379 MPI_VALIDATE_RET( A != NULL );
1380 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1385 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
Paul Bakker23986e52011-04-24 08:57:21 +00001387 for( i = A->n; i > 0; i-- )
1388 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001389 break;
1390
Paul Bakker23986e52011-04-24 08:57:21 +00001391 for( j = B->n; j > 0; j-- )
1392 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001393 break;
1394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1396 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001397
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001398 for( ; j > 0; j-- )
1399 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
1401 X->s = A->s * B->s;
1402
1403cleanup:
1404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001406
1407 return( ret );
1408}
1409
1410/*
1411 * Baseline multiplication: X = A * b
1412 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001414{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 mbedtls_mpi _B;
1416 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001417 MPI_VALIDATE_RET( X != NULL );
1418 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001419
1420 _B.s = 1;
1421 _B.n = 1;
1422 _B.p = p;
1423 p[0] = b;
1424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001425 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001426}
1427
1428/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001429 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1430 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001431 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001432static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1433 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001434{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001435#if defined(MBEDTLS_HAVE_UDBL)
1436 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001437#else
Simon Butcher9803d072016-01-03 00:24:34 +00001438 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1439 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001440 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1441 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001442 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001443#endif
1444
Simon Butcher15b15d12015-11-26 19:35:03 +00001445 /*
1446 * Check for overflow
1447 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001448 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001449 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001450 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001451
Simon Butcherf5ba0452015-12-27 23:01:55 +00001452 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001453 }
1454
1455#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001456 dividend = (mbedtls_t_udbl) u1 << biL;
1457 dividend |= (mbedtls_t_udbl) u0;
1458 quotient = dividend / d;
1459 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1460 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1461
1462 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001463 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001464
1465 return (mbedtls_mpi_uint) quotient;
1466#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001467
1468 /*
1469 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1470 * Vol. 2 - Seminumerical Algorithms, Knuth
1471 */
1472
1473 /*
1474 * Normalize the divisor, d, and dividend, u0, u1
1475 */
1476 s = mbedtls_clz( d );
1477 d = d << s;
1478
1479 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001480 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001481 u0 = u0 << s;
1482
1483 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001484 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001485
1486 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001487 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001488
1489 /*
1490 * Find the first quotient and remainder
1491 */
1492 q1 = u1 / d1;
1493 r0 = u1 - d1 * q1;
1494
1495 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1496 {
1497 q1 -= 1;
1498 r0 += d1;
1499
1500 if ( r0 >= radix ) break;
1501 }
1502
Simon Butcherf5ba0452015-12-27 23:01:55 +00001503 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001504 q0 = rAX / d1;
1505 r0 = rAX - q0 * d1;
1506
1507 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1508 {
1509 q0 -= 1;
1510 r0 += d1;
1511
1512 if ( r0 >= radix ) break;
1513 }
1514
1515 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001516 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001517
1518 quotient = q1 * radix + q0;
1519
1520 return quotient;
1521#endif
1522}
1523
1524/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001525 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001526 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001527int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1528 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001529{
Paul Bakker23986e52011-04-24 08:57:21 +00001530 int ret;
1531 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001532 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001533 MPI_VALIDATE_RET( A != NULL );
1534 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001536 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1537 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1540 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001543 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1545 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001546 return( 0 );
1547 }
1548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1550 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001551 X.s = Y.s = 1;
1552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001553 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1554 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1555 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1556 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001557
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001558 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001559 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001560 {
1561 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001562 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1563 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001564 }
1565 else k = 0;
1566
1567 n = X.n - 1;
1568 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001570
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001572 {
1573 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001575 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001577
1578 for( i = n; i > t ; i-- )
1579 {
1580 if( X.p[i] >= Y.p[t] )
1581 Z.p[i - t - 1] = ~0;
1582 else
1583 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001584 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1585 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001586 }
1587
1588 Z.p[i - t - 1]++;
1589 do
1590 {
1591 Z.p[i - t - 1]--;
1592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001594 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001595 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001596 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001599 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1600 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001601 T2.p[2] = X.p[i];
1602 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001603 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1606 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1607 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001608
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001610 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1612 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1613 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001614 Z.p[i - t - 1]--;
1615 }
1616 }
1617
1618 if( Q != NULL )
1619 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001621 Q->s = A->s * B->s;
1622 }
1623
1624 if( R != NULL )
1625 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001627 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001631 R->s = 1;
1632 }
1633
1634cleanup:
1635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1637 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001638
1639 return( ret );
1640}
1641
1642/*
1643 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001644 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001645int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1646 const mbedtls_mpi *A,
1647 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001648{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 mbedtls_mpi _B;
1650 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001651 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001652
1653 p[0] = ( b < 0 ) ? -b : b;
1654 _B.s = ( b < 0 ) ? -1 : 1;
1655 _B.n = 1;
1656 _B.p = p;
1657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001659}
1660
1661/*
1662 * Modulo: R = A mod B
1663 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001665{
1666 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001667 MPI_VALIDATE_RET( R != NULL );
1668 MPI_VALIDATE_RET( A != NULL );
1669 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1672 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1680 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001681
1682cleanup:
1683
1684 return( ret );
1685}
1686
1687/*
1688 * Modulo: r = A mod b
1689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001691{
Paul Bakker23986e52011-04-24 08:57:21 +00001692 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001694 MPI_VALIDATE_RET( r != NULL );
1695 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
1697 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
1700 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001701 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001702
1703 /*
1704 * handle trivial cases
1705 */
1706 if( b == 1 )
1707 {
1708 *r = 0;
1709 return( 0 );
1710 }
1711
1712 if( b == 2 )
1713 {
1714 *r = A->p[0] & 1;
1715 return( 0 );
1716 }
1717
1718 /*
1719 * general case
1720 */
Paul Bakker23986e52011-04-24 08:57:21 +00001721 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 {
Paul Bakker23986e52011-04-24 08:57:21 +00001723 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001724 y = ( y << biH ) | ( x >> biH );
1725 z = y / b;
1726 y -= z * b;
1727
1728 x <<= biH;
1729 y = ( y << biH ) | ( x >> biH );
1730 z = y / b;
1731 y -= z * b;
1732 }
1733
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001734 /*
1735 * If A is negative, then the current y represents a negative value.
1736 * Flipping it to the positive side.
1737 */
1738 if( A->s < 0 && y != 0 )
1739 y = b - y;
1740
Paul Bakker5121ce52009-01-03 21:22:43 +00001741 *r = y;
1742
1743 return( 0 );
1744}
1745
1746/*
1747 * Fast Montgomery initialization (thanks to Tom St Denis)
1748 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001750{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001751 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001752 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
1754 x = m0;
1755 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001756
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001757 for( i = biL; i >= 8; i /= 2 )
1758 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
1760 *mm = ~x + 1;
1761}
1762
1763/*
1764 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1765 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001766static 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 +02001767 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001768{
Paul Bakker23986e52011-04-24 08:57:21 +00001769 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001770 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001771
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001772 if( T->n < N->n + 1 || T->p == NULL )
1773 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1774
Paul Bakker5121ce52009-01-03 21:22:43 +00001775 memset( T->p, 0, T->n * ciL );
1776
1777 d = T->p;
1778 n = N->n;
1779 m = ( B->n < n ) ? B->n : n;
1780
1781 for( i = 0; i < n; i++ )
1782 {
1783 /*
1784 * T = (T + u0*B + u1*N) / 2^biL
1785 */
1786 u0 = A->p[i];
1787 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1788
1789 mpi_mul_hlp( m, B->p, d, u0 );
1790 mpi_mul_hlp( n, N->p, d, u1 );
1791
1792 *d++ = u0; d[n + 1] = 0;
1793 }
1794
Paul Bakker66d5d072014-06-17 16:39:18 +02001795 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001798 mpi_sub_hlp( n, N->p, A->p );
1799 else
1800 /* prevent timing attacks */
1801 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001802
1803 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804}
1805
1806/*
1807 * Montgomery reduction: A = A * R^-1 mod N
1808 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001809static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1810 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001811{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 mbedtls_mpi_uint z = 1;
1813 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
Paul Bakker8ddb6452013-02-27 14:56:33 +01001815 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001816 U.p = &z;
1817
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001818 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001819}
1820
1821/*
1822 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1823 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001824int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1825 const mbedtls_mpi *E, const mbedtls_mpi *N,
1826 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001827{
Paul Bakker23986e52011-04-24 08:57:21 +00001828 int ret;
1829 size_t wbits, wsize, one = 1;
1830 size_t i, j, nblimbs;
1831 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 mbedtls_mpi_uint ei, mm, state;
1833 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001834 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001835
Hanno Becker73d7d792018-12-11 10:35:51 +00001836 MPI_VALIDATE_RET( X != NULL );
1837 MPI_VALIDATE_RET( A != NULL );
1838 MPI_VALIDATE_RET( E != NULL );
1839 MPI_VALIDATE_RET( N != NULL );
1840
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001841 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1845 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001846
1847 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001848 * Init temps and window size
1849 */
1850 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001851 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1852 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 memset( W, 0, sizeof( W ) );
1854
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001855 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
1857 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1858 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1859
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001860 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1861 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001862
Paul Bakker5121ce52009-01-03 21:22:43 +00001863 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1865 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1866 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
1868 /*
Paul Bakker50546922012-05-19 08:40:49 +00001869 * Compensate for negative A (and correct at the end)
1870 */
1871 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001872 if( neg )
1873 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001875 Apos.s = 1;
1876 A = &Apos;
1877 }
1878
1879 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001880 * If 1st call, pre-compute R^2 mod N
1881 */
1882 if( _RR == NULL || _RR->p == NULL )
1883 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1885 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001887
1888 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001890 }
1891 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
1894 /*
1895 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1896 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1898 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001899 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001901
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001902 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
1904 /*
1905 * X = R^2 * R^-1 mod N = R mod N
1906 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001908 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001909
1910 if( wsize > 1 )
1911 {
1912 /*
1913 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1914 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001915 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001916
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1918 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919
1920 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001921 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001922
Paul Bakker5121ce52009-01-03 21:22:43 +00001923 /*
1924 * W[i] = W[i - 1] * W[1]
1925 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001926 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001927 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1929 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001931 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932 }
1933 }
1934
1935 nblimbs = E->n;
1936 bufsize = 0;
1937 nbits = 0;
1938 wbits = 0;
1939 state = 0;
1940
1941 while( 1 )
1942 {
1943 if( bufsize == 0 )
1944 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001945 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001946 break;
1947
Paul Bakker0d7702c2013-10-29 16:18:35 +01001948 nblimbs--;
1949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001951 }
1952
1953 bufsize--;
1954
1955 ei = (E->p[nblimbs] >> bufsize) & 1;
1956
1957 /*
1958 * skip leading 0s
1959 */
1960 if( ei == 0 && state == 0 )
1961 continue;
1962
1963 if( ei == 0 && state == 1 )
1964 {
1965 /*
1966 * out of window, square X
1967 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001968 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969 continue;
1970 }
1971
1972 /*
1973 * add ei to current window
1974 */
1975 state = 2;
1976
1977 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02001978 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979
1980 if( nbits == wsize )
1981 {
1982 /*
1983 * X = X^wsize R^-1 mod N
1984 */
1985 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001986 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001987
1988 /*
1989 * X = X * W[wbits] R^-1 mod N
1990 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001991 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
1993 state--;
1994 nbits = 0;
1995 wbits = 0;
1996 }
1997 }
1998
1999 /*
2000 * process the remaining bits
2001 */
2002 for( i = 0; i < nbits; i++ )
2003 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002004 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002005
2006 wbits <<= 1;
2007
Paul Bakker66d5d072014-06-17 16:39:18 +02002008 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002009 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002010 }
2011
2012 /*
2013 * X = A^E * R * R^-1 mod N = A^E mod N
2014 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002015 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002016
Hanno Beckera4af1c42017-04-18 09:07:45 +01002017 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002018 {
2019 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002021 }
2022
Paul Bakker5121ce52009-01-03 21:22:43 +00002023cleanup:
2024
Paul Bakker66d5d072014-06-17 16:39:18 +02002025 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002026 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002029
Paul Bakker75a28602014-03-31 12:08:17 +02002030 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
2033 return( ret );
2034}
2035
Paul Bakker5121ce52009-01-03 21:22:43 +00002036/*
2037 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2038 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002040{
Paul Bakker23986e52011-04-24 08:57:21 +00002041 int ret;
2042 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002044
Hanno Becker73d7d792018-12-11 10:35:51 +00002045 MPI_VALIDATE_RET( G != NULL );
2046 MPI_VALIDATE_RET( A != NULL );
2047 MPI_VALIDATE_RET( B != NULL );
2048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2052 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002053
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 lz = mbedtls_mpi_lsb( &TA );
2055 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002056
Paul Bakker66d5d072014-06-17 16:39:18 +02002057 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002058 lz = lzt;
2059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2061 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002062
Paul Bakker5121ce52009-01-03 21:22:43 +00002063 TA.s = TB.s = 1;
2064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002066 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2068 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002071 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2073 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002074 }
2075 else
2076 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002077 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2078 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002079 }
2080 }
2081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2083 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002084
2085cleanup:
2086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002088
2089 return( ret );
2090}
2091
Paul Bakker33dc46b2014-04-30 16:11:39 +02002092/*
2093 * Fill X with size bytes of random.
2094 *
2095 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002096 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002097 * deterministic, eg for tests).
2098 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002100 int (*f_rng)(void *, unsigned char *, size_t),
2101 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002102{
Paul Bakker23986e52011-04-24 08:57:21 +00002103 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002104 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002105 size_t const overhead = ( limbs * ciL ) - size;
2106 unsigned char *Xp;
2107
Hanno Becker8ce11a32018-12-19 16:18:52 +00002108 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002109 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002110
Hanno Beckerda1655a2017-10-18 14:21:44 +01002111 /* Ensure that target MPI has exactly the necessary number of limbs */
2112 if( X->n != limbs )
2113 {
2114 mbedtls_mpi_free( X );
2115 mbedtls_mpi_init( X );
2116 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2117 }
2118 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002119
Hanno Beckerda1655a2017-10-18 14:21:44 +01002120 Xp = (unsigned char*) X->p;
2121 f_rng( p_rng, Xp + overhead, size );
2122
Hanno Becker2be8a552018-10-25 12:40:09 +01002123 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002124
2125cleanup:
2126 return( ret );
2127}
2128
Paul Bakker5121ce52009-01-03 21:22:43 +00002129/*
2130 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2131 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002132int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002133{
2134 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002135 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002136 MPI_VALIDATE_RET( X != NULL );
2137 MPI_VALIDATE_RET( A != NULL );
2138 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002139
Hanno Becker4bcb4912017-04-18 15:49:39 +01002140 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002142
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002143 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2144 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2145 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002146
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002150 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002152 goto cleanup;
2153 }
2154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2156 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2157 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2158 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2161 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2162 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2163 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002164
2165 do
2166 {
2167 while( ( TU.p[0] & 1 ) == 0 )
2168 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002170
2171 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2172 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2174 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175 }
2176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2178 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002179 }
2180
2181 while( ( TV.p[0] & 1 ) == 0 )
2182 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002183 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184
2185 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2186 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2188 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002189 }
2190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2192 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002193 }
2194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002196 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2198 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 }
2201 else
2202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2204 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2205 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002206 }
2207 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2211 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2214 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002216 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002217
2218cleanup:
2219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2221 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2222 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002223
2224 return( ret );
2225}
2226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002228
Paul Bakker5121ce52009-01-03 21:22:43 +00002229static const int small_prime[] =
2230{
2231 3, 5, 7, 11, 13, 17, 19, 23,
2232 29, 31, 37, 41, 43, 47, 53, 59,
2233 61, 67, 71, 73, 79, 83, 89, 97,
2234 101, 103, 107, 109, 113, 127, 131, 137,
2235 139, 149, 151, 157, 163, 167, 173, 179,
2236 181, 191, 193, 197, 199, 211, 223, 227,
2237 229, 233, 239, 241, 251, 257, 263, 269,
2238 271, 277, 281, 283, 293, 307, 311, 313,
2239 317, 331, 337, 347, 349, 353, 359, 367,
2240 373, 379, 383, 389, 397, 401, 409, 419,
2241 421, 431, 433, 439, 443, 449, 457, 461,
2242 463, 467, 479, 487, 491, 499, 503, 509,
2243 521, 523, 541, 547, 557, 563, 569, 571,
2244 577, 587, 593, 599, 601, 607, 613, 617,
2245 619, 631, 641, 643, 647, 653, 659, 661,
2246 673, 677, 683, 691, 701, 709, 719, 727,
2247 733, 739, 743, 751, 757, 761, 769, 773,
2248 787, 797, 809, 811, 821, 823, 827, 829,
2249 839, 853, 857, 859, 863, 877, 881, 883,
2250 887, 907, 911, 919, 929, 937, 941, 947,
2251 953, 967, 971, 977, 983, 991, 997, -103
2252};
2253
2254/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002255 * Small divisors test (X must be positive)
2256 *
2257 * Return values:
2258 * 0: no small factor (possible prime, more tests needed)
2259 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002261 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002264{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002265 int ret = 0;
2266 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002268
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002271
2272 for( i = 0; small_prime[i] > 0; i++ )
2273 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002275 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278
2279 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 }
2282
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002283cleanup:
2284 return( ret );
2285}
2286
2287/*
2288 * Miller-Rabin pseudo-primality test (HAC 4.24)
2289 */
Janos Follathda31fa12018-09-03 14:45:23 +01002290static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002291 int (*f_rng)(void *, unsigned char *, size_t),
2292 void *p_rng )
2293{
Pascal Junodb99183d2015-03-11 16:49:45 +01002294 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002295 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002297
Hanno Becker8ce11a32018-12-19 16:18:52 +00002298 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002299 MPI_VALIDATE_RET( f_rng != NULL );
2300
2301 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2302 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002303 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002304
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 /*
2306 * W = |X| - 1
2307 * R = W >> lsb( W )
2308 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2310 s = mbedtls_mpi_lsb( &W );
2311 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2312 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002314 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002315
Janos Follathda31fa12018-09-03 14:45:23 +01002316 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 {
2318 /*
2319 * pick a random A, 1 < A < |X| - 1
2320 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002321 count = 0;
2322 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002323 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002324
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002325 j = mbedtls_mpi_bitlen( &A );
2326 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002327 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002328 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002329 }
2330
2331 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002332 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002333 }
2334
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002335 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2336 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
2338 /*
2339 * A = A^R mod |X|
2340 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2344 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002345 continue;
2346
2347 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002349 {
2350 /*
2351 * A = A * A mod |X|
2352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002353 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2354 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002357 break;
2358
2359 j++;
2360 }
2361
2362 /*
2363 * not prime if A != |X| - 1 or A == 1
2364 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2366 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002367 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002369 break;
2370 }
2371 }
2372
2373cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002374 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2375 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
2378 return( ret );
2379}
2380
2381/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002382 * Pseudo-primality test: small factors, then Miller-Rabin
2383 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002384int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2385 int (*f_rng)(void *, unsigned char *, size_t),
2386 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002387{
2388 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002389 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002390 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002391 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002392
2393 XX.s = 1;
2394 XX.n = X->n;
2395 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2398 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2399 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002402 return( 0 );
2403
2404 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2405 {
2406 if( ret == 1 )
2407 return( 0 );
2408
2409 return( ret );
2410 }
2411
Janos Follathda31fa12018-09-03 14:45:23 +01002412 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002413}
2414
Janos Follatha0b67c22018-09-18 14:48:23 +01002415#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002416/*
2417 * Pseudo-primality test, error probability 2^-80
2418 */
2419int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2420 int (*f_rng)(void *, unsigned char *, size_t),
2421 void *p_rng )
2422{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002423 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002424 MPI_VALIDATE_RET( f_rng != NULL );
2425
Janos Follatha0b67c22018-09-18 14:48:23 +01002426 /*
2427 * In the past our key generation aimed for an error rate of at most
2428 * 2^-80. Since this function is deprecated, aim for the same certainty
2429 * here as well.
2430 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002431 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002432}
Janos Follatha0b67c22018-09-18 14:48:23 +01002433#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002434
2435/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002436 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002437 *
Janos Follathf301d232018-08-14 13:34:01 +01002438 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2439 * be either 1024 bits or 1536 bits long, and flags must contain
2440 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002441 */
Janos Follath7c025a92018-08-14 11:08:41 +01002442int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002443 int (*f_rng)(void *, unsigned char *, size_t),
2444 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002445{
Jethro Beekman66689272018-02-14 19:24:10 -08002446#ifdef MBEDTLS_HAVE_INT64
2447// ceil(2^63.5)
2448#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2449#else
2450// ceil(2^31.5)
2451#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2452#endif
2453 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002454 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002455 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 mbedtls_mpi_uint r;
2457 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002458
Hanno Becker8ce11a32018-12-19 16:18:52 +00002459 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002460 MPI_VALIDATE_RET( f_rng != NULL );
2461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002462 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2463 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002465 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002466
2467 n = BITS_TO_LIMBS( nbits );
2468
Janos Follathda31fa12018-09-03 14:45:23 +01002469 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2470 {
2471 /*
2472 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2473 */
2474 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2475 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2476 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2477 }
2478 else
2479 {
2480 /*
2481 * 2^-100 error probability, number of rounds computed based on HAC,
2482 * fact 4.48
2483 */
2484 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2485 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2486 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2487 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2488 }
2489
Jethro Beekman66689272018-02-14 19:24:10 -08002490 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002491 {
Jethro Beekman66689272018-02-14 19:24:10 -08002492 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2493 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2494 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2495
2496 k = n * biL;
2497 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2498 X->p[0] |= 1;
2499
Janos Follath7c025a92018-08-14 11:08:41 +01002500 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002501 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002502 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002505 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002506 }
Jethro Beekman66689272018-02-14 19:24:10 -08002507 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002508 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002509 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002510 * An necessary condition for Y and X = 2Y + 1 to be prime
2511 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2512 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002513 */
Jethro Beekman66689272018-02-14 19:24:10 -08002514
2515 X->p[0] |= 2;
2516
2517 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2518 if( r == 0 )
2519 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2520 else if( r == 1 )
2521 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2522
2523 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2524 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2525 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2526
2527 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002528 {
Jethro Beekman66689272018-02-14 19:24:10 -08002529 /*
2530 * First, check small factors for X and Y
2531 * before doing Miller-Rabin on any of them
2532 */
2533 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2534 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002535 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002536 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002537 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002538 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002539 goto cleanup;
2540
2541 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2542 goto cleanup;
2543
2544 /*
2545 * Next candidates. We want to preserve Y = (X-1) / 2 and
2546 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2547 * so up Y by 6 and X by 12.
2548 */
2549 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2550 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002551 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002552 }
2553 }
2554
2555cleanup:
2556
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002557 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002558
2559 return( ret );
2560}
2561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002565
Paul Bakker23986e52011-04-24 08:57:21 +00002566#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002567
2568static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2569{
2570 { 693, 609, 21 },
2571 { 1764, 868, 28 },
2572 { 768454923, 542167814, 1 }
2573};
2574
Paul Bakker5121ce52009-01-03 21:22:43 +00002575/*
2576 * Checkup routine
2577 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002579{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002580 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002583 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2584 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002586 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002587 "EFE021C2645FD1DC586E69184AF4A31E" \
2588 "D5F53E93B5F123FA41680867BA110131" \
2589 "944FE7952E2517337780CB0DB80E61AA" \
2590 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002593 "B2E7EFD37075B9F03FF989C7C5051C20" \
2594 "34D2A323810251127E7BF8625A4F49A5" \
2595 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2596 "5B5C25763222FEFCCFC38B832366C29E" ) );
2597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002598 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002599 "0066A198186C18C10B2F5ED9B522752A" \
2600 "9830B69916E535C8F047518A889A43A5" \
2601 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002606 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2607 "9E857EA95A03512E2BAE7391688D264A" \
2608 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2609 "8001B72E848A38CAE1C65F78E56ABDEF" \
2610 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2611 "ECF677152EF804370C1A305CAF3B5BF1" \
2612 "30879B56C61DE584A0F53A2447A51E" ) );
2613
2614 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002618 {
2619 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002620 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002621
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002622 ret = 1;
2623 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002624 }
2625
2626 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002627 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002631 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002632 "256567336059E52CAE22925474705F39A94" ) );
2633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002635 "6613F26162223DF488E9CD48CC132C7A" \
2636 "0AC93C701B001B092E4E5B9F73BCD27B" \
2637 "9EE50D0657C77F374E903CDFA4C642" ) );
2638
2639 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002640 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002642 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2643 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002644 {
2645 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002646 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002647
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002648 ret = 1;
2649 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002650 }
2651
2652 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002653 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002655 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 "36E139AEA55215609D2816998ED020BB" \
2659 "BD96C37890F65171D948E9BC7CBAA4D9" \
2660 "325D24D6A3C12710F10A09FA08AB87" ) );
2661
2662 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002663 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002665 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002666 {
2667 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002668 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002669
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002670 ret = 1;
2671 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002672 }
2673
2674 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002675 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002679 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002680 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2681 "C3DBA76456363A10869622EAC2DD84EC" \
2682 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2683
2684 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002685 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002688 {
2689 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002691
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002692 ret = 1;
2693 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002694 }
2695
2696 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002698
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002699 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002700 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002701
Paul Bakker66d5d072014-06-17 16:39:18 +02002702 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002703 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2705 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002706
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002707 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002708
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002709 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002710 {
2711 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002712 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002713
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002714 ret = 1;
2715 goto cleanup;
2716 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002717 }
2718
2719 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002720 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002721
Paul Bakker5121ce52009-01-03 21:22:43 +00002722cleanup:
2723
2724 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002727 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2728 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002729
2730 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002732
2733 return( ret );
2734}
2735
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002736#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002738#endif /* MBEDTLS_BIGNUM_C */