blob: a1822fc6c089bb0f204955dfb94d85108e7a59cd [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
Ron Eldora16fa292018-11-20 14:07:01 +0200530 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000531 */
Ron Eldora16fa292018-11-20 14:07:01 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix,
533 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534{
535 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200537 size_t length = 0;
538 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Ron Eldora16fa292018-11-20 14:07:01 +0200540 do
541 {
542 if( length >= buflen )
543 {
544 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
545 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
Ron Eldora16fa292018-11-20 14:07:01 +0200547 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
548 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
549 /*
550 * Write the residue in the current position, as an ASCII character.
551 */
552 if( r < 0xA )
553 *(--p_end) = (char)( '0' + r );
554 else
555 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Ron Eldora16fa292018-11-20 14:07:01 +0200557 length++;
558 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Ron Eldora16fa292018-11-20 14:07:01 +0200560 memmove( *p, p_end, length );
561 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563cleanup:
564
565 return( ret );
566}
567
568/*
569 * Export into an ASCII string
570 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
572 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573{
Paul Bakker23986e52011-04-24 08:57:21 +0000574 int ret = 0;
575 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000578 MPI_VALIDATE_RET( X != NULL );
579 MPI_VALIDATE_RET( olen != NULL );
580 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
582 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000583 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000585 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
586 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
587 * `n`. If radix > 4, this might be a strict
588 * overapproximation of the number of
589 * radix-adic digits needed to present `n`. */
590 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
591 * present `n`. */
592
Janos Follath870ed002019-03-06 13:43:02 +0000593 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000594 n += 1; /* Compensate for the divisions above, which round down `n`
595 * in case it's not even. */
596 n += 1; /* Potential '-'-sign. */
597 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
598 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100600 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100602 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 }
605
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100606 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
609 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000610 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000612 buflen--;
613 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 if( radix == 16 )
616 {
Paul Bakker23986e52011-04-24 08:57:21 +0000617 int c;
618 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
Paul Bakker23986e52011-04-24 08:57:21 +0000620 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 {
Paul Bakker23986e52011-04-24 08:57:21 +0000622 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 {
Paul Bakker23986e52011-04-24 08:57:21 +0000624 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
Paul Bakker6c343d72014-07-10 14:36:19 +0200626 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000627 continue;
628
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000629 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000630 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000631 k = 1;
632 }
633 }
634 }
635 else
636 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000638
639 if( T.s == -1 )
640 T.s = 1;
641
Ron Eldora16fa292018-11-20 14:07:01 +0200642 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 }
644
645 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100646 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
648cleanup:
649
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
652 return( ret );
653}
654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000656/*
657 * Read X from an opened file
658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000660{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000662 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000664 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000665 * Buffer should have space for (short) label and decimal formatted MPI,
666 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
Hanno Becker73d7d792018-12-11 10:35:51 +0000670 MPI_VALIDATE_RET( X != NULL );
671 MPI_VALIDATE_RET( fin != NULL );
672
673 if( radix < 2 || radix > 16 )
674 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
675
Paul Bakker5121ce52009-01-03 21:22:43 +0000676 memset( s, 0, sizeof( s ) );
677 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
680 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000681 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000683
Hanno Beckerb2034b72017-04-26 11:46:46 +0100684 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
685 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100688 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 if( mpi_get_digit( &d, radix, *p ) != 0 )
690 break;
691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693}
694
695/*
696 * Write X into an opened file (or stdout if fout == NULL)
697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000699{
Paul Bakker23986e52011-04-24 08:57:21 +0000700 int ret;
701 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000702 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000703 * Buffer should have space for (short) label and decimal formatted MPI,
704 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000705 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000707 MPI_VALIDATE_RET( X != NULL );
708
709 if( radix < 2 || radix > 16 )
710 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100712 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100714 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 if( p == NULL ) p = "";
717
718 plen = strlen( p );
719 slen = strlen( s );
720 s[slen++] = '\r';
721 s[slen++] = '\n';
722
723 if( fout != NULL )
724 {
725 if( fwrite( p, 1, plen, fout ) != plen ||
726 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000728 }
729 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000731
732cleanup:
733
734 return( ret );
735}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
Hanno Beckerda1655a2017-10-18 14:21:44 +0100738
739/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
740 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000741
742static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
743{
744 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100745 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000746 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100747
748 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
749 {
750 tmp <<= CHAR_BIT;
751 tmp |= (mbedtls_mpi_uint) *x_ptr;
752 }
753
Hanno Beckerf8720072018-11-08 11:53:49 +0000754 return( tmp );
755}
756
757static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
758{
759#if defined(__BYTE_ORDER__)
760
761/* Nothing to do on bigendian systems. */
762#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
763 return( x );
764#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
765
766#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
767
768/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000769#if defined(__GNUC__) && defined(__GNUC_PREREQ)
770#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000771#define have_bswap
772#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000773#endif
774
775#if defined(__clang__) && defined(__has_builtin)
776#if __has_builtin(__builtin_bswap32) && \
777 __has_builtin(__builtin_bswap64)
778#define have_bswap
779#endif
780#endif
781
Hanno Beckerf8720072018-11-08 11:53:49 +0000782#if defined(have_bswap)
783 /* The compiler is hopefully able to statically evaluate this! */
784 switch( sizeof(mbedtls_mpi_uint) )
785 {
786 case 4:
787 return( __builtin_bswap32(x) );
788 case 8:
789 return( __builtin_bswap64(x) );
790 }
791#endif
792#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
793#endif /* __BYTE_ORDER__ */
794
795 /* Fall back to C-based reordering if we don't know the byte order
796 * or we couldn't use a compiler-specific builtin. */
797 return( mpi_uint_bigendian_to_host_c( x ) );
798}
799
Hanno Becker2be8a552018-10-25 12:40:09 +0100800static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100801{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100802 mbedtls_mpi_uint *cur_limb_left;
803 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100804 if( limbs == 0 )
805 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100806
807 /*
808 * Traverse limbs and
809 * - adapt byte-order in each limb
810 * - swap the limbs themselves.
811 * For that, simultaneously traverse the limbs from left to right
812 * and from right to left, as long as the left index is not bigger
813 * than the right index (it's not a problem if limbs is odd and the
814 * indices coincide in the last iteration).
815 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100816 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
817 cur_limb_left <= cur_limb_right;
818 cur_limb_left++, cur_limb_right-- )
819 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000820 mbedtls_mpi_uint tmp;
821 /* Note that if cur_limb_left == cur_limb_right,
822 * this code effectively swaps the bytes only once. */
823 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
824 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
825 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100826 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100827}
828
Paul Bakker5121ce52009-01-03 21:22:43 +0000829/*
830 * Import X from unsigned binary data, big endian
831 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833{
Paul Bakker23986e52011-04-24 08:57:21 +0000834 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100835 size_t const limbs = CHARS_TO_LIMBS( buflen );
836 size_t const overhead = ( limbs * ciL ) - buflen;
837 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000838
Hanno Becker8ce11a32018-12-19 16:18:52 +0000839 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000840 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
841
Hanno Becker073c1992017-10-17 15:17:27 +0100842 /* Ensure that target MPI has exactly the necessary number of limbs */
843 if( X->n != limbs )
844 {
845 mbedtls_mpi_free( X );
846 mbedtls_mpi_init( X );
847 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
848 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
Hanno Becker0e810b92019-01-03 17:13:11 +0000851 /* Avoid calling `memcpy` with NULL source argument,
852 * even if buflen is 0. */
853 if( buf != NULL )
854 {
855 Xp = (unsigned char*) X->p;
856 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100857
Hanno Becker0e810b92019-01-03 17:13:11 +0000858 mpi_bigendian_to_host( X->p, limbs );
859 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000860
861cleanup:
862
863 return( ret );
864}
865
866/*
867 * Export X into unsigned binary data, big endian
868 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100869int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
870 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000871{
Hanno Becker73d7d792018-12-11 10:35:51 +0000872 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100873 size_t bytes_to_copy;
874 unsigned char *p;
875 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000876
Hanno Becker73d7d792018-12-11 10:35:51 +0000877 MPI_VALIDATE_RET( X != NULL );
878 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
879
880 stored_bytes = X->n * ciL;
881
Gilles Peskine11cdb052018-11-20 16:47:47 +0100882 if( stored_bytes < buflen )
883 {
884 /* There is enough space in the output buffer. Write initial
885 * null bytes and record the position at which to start
886 * writing the significant bytes. In this case, the execution
887 * trace of this function does not depend on the value of the
888 * number. */
889 bytes_to_copy = stored_bytes;
890 p = buf + buflen - stored_bytes;
891 memset( buf, 0, buflen - stored_bytes );
892 }
893 else
894 {
895 /* The output buffer is smaller than the allocated size of X.
896 * However X may fit if its leading bytes are zero. */
897 bytes_to_copy = buflen;
898 p = buf;
899 for( i = bytes_to_copy; i < stored_bytes; i++ )
900 {
901 if( GET_BYTE( X, i ) != 0 )
902 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
903 }
904 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
Gilles Peskine11cdb052018-11-20 16:47:47 +0100906 for( i = 0; i < bytes_to_copy; i++ )
907 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000908
909 return( 0 );
910}
911
912/*
913 * Left-shift: X <<= count
914 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000916{
Paul Bakker23986e52011-04-24 08:57:21 +0000917 int ret;
918 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000920 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000921
922 v0 = count / (biL );
923 t1 = count & (biL - 1);
924
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200925 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
Paul Bakkerf9688572011-05-05 10:00:45 +0000927 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
930 ret = 0;
931
932 /*
933 * shift by count / limb_size
934 */
935 if( v0 > 0 )
936 {
Paul Bakker23986e52011-04-24 08:57:21 +0000937 for( i = X->n; i > v0; i-- )
938 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
Paul Bakker23986e52011-04-24 08:57:21 +0000940 for( ; i > 0; i-- )
941 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 }
943
944 /*
945 * shift by count % limb_size
946 */
947 if( t1 > 0 )
948 {
949 for( i = v0; i < X->n; i++ )
950 {
951 r1 = X->p[i] >> (biL - t1);
952 X->p[i] <<= t1;
953 X->p[i] |= r0;
954 r0 = r1;
955 }
956 }
957
958cleanup:
959
960 return( ret );
961}
962
963/*
964 * Right-shift: X >>= count
965 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000967{
Paul Bakker23986e52011-04-24 08:57:21 +0000968 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000970 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000971
972 v0 = count / biL;
973 v1 = count & (biL - 1);
974
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100975 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200976 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100977
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 /*
979 * shift by count / limb_size
980 */
981 if( v0 > 0 )
982 {
983 for( i = 0; i < X->n - v0; i++ )
984 X->p[i] = X->p[i + v0];
985
986 for( ; i < X->n; i++ )
987 X->p[i] = 0;
988 }
989
990 /*
991 * shift by count % limb_size
992 */
993 if( v1 > 0 )
994 {
Paul Bakker23986e52011-04-24 08:57:21 +0000995 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000996 {
Paul Bakker23986e52011-04-24 08:57:21 +0000997 r1 = X->p[i - 1] << (biL - v1);
998 X->p[i - 1] >>= v1;
999 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 r0 = r1;
1001 }
1002 }
1003
1004 return( 0 );
1005}
1006
1007/*
1008 * Compare unsigned values
1009 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001011{
Paul Bakker23986e52011-04-24 08:57:21 +00001012 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001013 MPI_VALIDATE_RET( X != NULL );
1014 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001015
Paul Bakker23986e52011-04-24 08:57:21 +00001016 for( i = X->n; i > 0; i-- )
1017 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 break;
1019
Paul Bakker23986e52011-04-24 08:57:21 +00001020 for( j = Y->n; j > 0; j-- )
1021 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 break;
1023
Paul Bakker23986e52011-04-24 08:57:21 +00001024 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 return( 0 );
1026
1027 if( i > j ) return( 1 );
1028 if( j > i ) return( -1 );
1029
Paul Bakker23986e52011-04-24 08:57:21 +00001030 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 {
Paul Bakker23986e52011-04-24 08:57:21 +00001032 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1033 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034 }
1035
1036 return( 0 );
1037}
1038
1039/*
1040 * Compare signed values
1041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001043{
Paul Bakker23986e52011-04-24 08:57:21 +00001044 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001045 MPI_VALIDATE_RET( X != NULL );
1046 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047
Paul Bakker23986e52011-04-24 08:57:21 +00001048 for( i = X->n; i > 0; i-- )
1049 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 break;
1051
Paul Bakker23986e52011-04-24 08:57:21 +00001052 for( j = Y->n; j > 0; j-- )
1053 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001054 break;
1055
Paul Bakker23986e52011-04-24 08:57:21 +00001056 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 return( 0 );
1058
1059 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001060 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061
1062 if( X->s > 0 && Y->s < 0 ) return( 1 );
1063 if( Y->s > 0 && X->s < 0 ) return( -1 );
1064
Paul Bakker23986e52011-04-24 08:57:21 +00001065 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001066 {
Paul Bakker23986e52011-04-24 08:57:21 +00001067 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1068 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 }
1070
1071 return( 0 );
1072}
1073
1074/*
1075 * Compare signed values
1076 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001077int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001078{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079 mbedtls_mpi Y;
1080 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001081 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001082
1083 *p = ( z < 0 ) ? -z : z;
1084 Y.s = ( z < 0 ) ? -1 : 1;
1085 Y.n = 1;
1086 Y.p = p;
1087
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001089}
1090
1091/*
1092 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1093 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001095{
Paul Bakker23986e52011-04-24 08:57:21 +00001096 int ret;
1097 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001098 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001099 MPI_VALIDATE_RET( X != NULL );
1100 MPI_VALIDATE_RET( A != NULL );
1101 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001102
1103 if( X == B )
1104 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001105 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001106 }
1107
1108 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001110
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001111 /*
1112 * X should always be positive as a result of unsigned additions.
1113 */
1114 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001115
Paul Bakker23986e52011-04-24 08:57:21 +00001116 for( j = B->n; j > 0; j-- )
1117 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001118 break;
1119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001121
1122 o = B->p; p = X->p; c = 0;
1123
Janos Follath6c922682015-10-30 17:43:11 +01001124 /*
1125 * tmp is used because it might happen that p == o
1126 */
Paul Bakker23986e52011-04-24 08:57:21 +00001127 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001128 {
Janos Follath6c922682015-10-30 17:43:11 +01001129 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001131 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001132 }
1133
1134 while( c != 0 )
1135 {
1136 if( i >= X->n )
1137 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001138 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001139 p = X->p + i;
1140 }
1141
Paul Bakker2d319fd2012-09-16 21:34:26 +00001142 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001143 }
1144
1145cleanup:
1146
1147 return( ret );
1148}
1149
1150/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001152 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001153static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001154{
Paul Bakker23986e52011-04-24 08:57:21 +00001155 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001156 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001157
1158 for( i = c = 0; i < n; i++, s++, d++ )
1159 {
1160 z = ( *d < c ); *d -= c;
1161 c = ( *d < *s ) + z; *d -= *s;
1162 }
1163
1164 while( c != 0 )
1165 {
1166 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001167 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 }
1169}
1170
1171/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001172 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001173 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001174int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001175{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001176 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001177 int ret;
1178 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001179 MPI_VALIDATE_RET( X != NULL );
1180 MPI_VALIDATE_RET( A != NULL );
1181 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1184 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001186 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001187
1188 if( X == B )
1189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001191 B = &TB;
1192 }
1193
1194 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
Paul Bakker1ef7a532009-06-20 10:50:55 +00001197 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001198 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001199 */
1200 X->s = 1;
1201
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 ret = 0;
1203
Paul Bakker23986e52011-04-24 08:57:21 +00001204 for( n = B->n; n > 0; n-- )
1205 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 break;
1207
Paul Bakker23986e52011-04-24 08:57:21 +00001208 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
1210cleanup:
1211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001212 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001213
1214 return( ret );
1215}
1216
1217/*
1218 * Signed addition: X = A + B
1219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001221{
Hanno Becker73d7d792018-12-11 10:35:51 +00001222 int ret, s;
1223 MPI_VALIDATE_RET( X != NULL );
1224 MPI_VALIDATE_RET( A != NULL );
1225 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001226
Hanno Becker73d7d792018-12-11 10:35:51 +00001227 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001228 if( A->s * B->s < 0 )
1229 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001233 X->s = s;
1234 }
1235 else
1236 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001237 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 X->s = -s;
1239 }
1240 }
1241 else
1242 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001243 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001244 X->s = s;
1245 }
1246
1247cleanup:
1248
1249 return( ret );
1250}
1251
1252/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001253 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001256{
Hanno Becker73d7d792018-12-11 10:35:51 +00001257 int ret, s;
1258 MPI_VALIDATE_RET( X != NULL );
1259 MPI_VALIDATE_RET( A != NULL );
1260 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
Hanno Becker73d7d792018-12-11 10:35:51 +00001262 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001263 if( A->s * B->s > 0 )
1264 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001266 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001268 X->s = s;
1269 }
1270 else
1271 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001272 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001273 X->s = -s;
1274 }
1275 }
1276 else
1277 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001279 X->s = s;
1280 }
1281
1282cleanup:
1283
1284 return( ret );
1285}
1286
1287/*
1288 * Signed addition: X = A + b
1289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001291{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292 mbedtls_mpi _B;
1293 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001294 MPI_VALIDATE_RET( X != NULL );
1295 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001296
1297 p[0] = ( b < 0 ) ? -b : b;
1298 _B.s = ( b < 0 ) ? -1 : 1;
1299 _B.n = 1;
1300 _B.p = p;
1301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001302 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001303}
1304
1305/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001306 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001308int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001309{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001310 mbedtls_mpi _B;
1311 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001312 MPI_VALIDATE_RET( X != NULL );
1313 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001314
1315 p[0] = ( b < 0 ) ? -b : b;
1316 _B.s = ( b < 0 ) ? -1 : 1;
1317 _B.n = 1;
1318 _B.p = p;
1319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001320 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001321}
1322
1323/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001325 */
1326static
1327#if defined(__APPLE__) && defined(__arm__)
1328/*
1329 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1330 * appears to need this to prevent bad ARM code generation at -O3.
1331 */
1332__attribute__ ((noinline))
1333#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334void 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 +00001335{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001337
1338#if defined(MULADDC_HUIT)
1339 for( ; i >= 8; i -= 8 )
1340 {
1341 MULADDC_INIT
1342 MULADDC_HUIT
1343 MULADDC_STOP
1344 }
1345
1346 for( ; i > 0; i-- )
1347 {
1348 MULADDC_INIT
1349 MULADDC_CORE
1350 MULADDC_STOP
1351 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001352#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001353 for( ; i >= 16; i -= 16 )
1354 {
1355 MULADDC_INIT
1356 MULADDC_CORE MULADDC_CORE
1357 MULADDC_CORE MULADDC_CORE
1358 MULADDC_CORE MULADDC_CORE
1359 MULADDC_CORE MULADDC_CORE
1360
1361 MULADDC_CORE MULADDC_CORE
1362 MULADDC_CORE MULADDC_CORE
1363 MULADDC_CORE MULADDC_CORE
1364 MULADDC_CORE MULADDC_CORE
1365 MULADDC_STOP
1366 }
1367
1368 for( ; i >= 8; i -= 8 )
1369 {
1370 MULADDC_INIT
1371 MULADDC_CORE MULADDC_CORE
1372 MULADDC_CORE MULADDC_CORE
1373
1374 MULADDC_CORE MULADDC_CORE
1375 MULADDC_CORE MULADDC_CORE
1376 MULADDC_STOP
1377 }
1378
1379 for( ; i > 0; i-- )
1380 {
1381 MULADDC_INIT
1382 MULADDC_CORE
1383 MULADDC_STOP
1384 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001385#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
1387 t++;
1388
1389 do {
1390 *d += c; c = ( *d < c ); d++;
1391 }
1392 while( c != 0 );
1393}
1394
1395/*
1396 * Baseline multiplication: X = A * B (HAC 14.12)
1397 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001399{
Paul Bakker23986e52011-04-24 08:57:21 +00001400 int ret;
1401 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001402 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001403 MPI_VALIDATE_RET( X != NULL );
1404 MPI_VALIDATE_RET( A != NULL );
1405 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1410 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001411
Paul Bakker23986e52011-04-24 08:57:21 +00001412 for( i = A->n; i > 0; i-- )
1413 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001414 break;
1415
Paul Bakker23986e52011-04-24 08:57:21 +00001416 for( j = B->n; j > 0; j-- )
1417 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001418 break;
1419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1421 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001422
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001423 for( ; j > 0; j-- )
1424 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425
1426 X->s = A->s * B->s;
1427
1428cleanup:
1429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001431
1432 return( ret );
1433}
1434
1435/*
1436 * Baseline multiplication: X = A * b
1437 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001439{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440 mbedtls_mpi _B;
1441 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001442 MPI_VALIDATE_RET( X != NULL );
1443 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001444
1445 _B.s = 1;
1446 _B.n = 1;
1447 _B.p = p;
1448 p[0] = b;
1449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001450 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001451}
1452
1453/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001454 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1455 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001456 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001457static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1458 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001459{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001460#if defined(MBEDTLS_HAVE_UDBL)
1461 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001462#else
Simon Butcher9803d072016-01-03 00:24:34 +00001463 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1464 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001465 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1466 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001467 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001468#endif
1469
Simon Butcher15b15d12015-11-26 19:35:03 +00001470 /*
1471 * Check for overflow
1472 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001473 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001474 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001475 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001476
Simon Butcherf5ba0452015-12-27 23:01:55 +00001477 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001478 }
1479
1480#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001481 dividend = (mbedtls_t_udbl) u1 << biL;
1482 dividend |= (mbedtls_t_udbl) u0;
1483 quotient = dividend / d;
1484 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1485 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1486
1487 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001488 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001489
1490 return (mbedtls_mpi_uint) quotient;
1491#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001492
1493 /*
1494 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1495 * Vol. 2 - Seminumerical Algorithms, Knuth
1496 */
1497
1498 /*
1499 * Normalize the divisor, d, and dividend, u0, u1
1500 */
1501 s = mbedtls_clz( d );
1502 d = d << s;
1503
1504 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001505 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001506 u0 = u0 << s;
1507
1508 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001509 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001510
1511 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001512 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001513
1514 /*
1515 * Find the first quotient and remainder
1516 */
1517 q1 = u1 / d1;
1518 r0 = u1 - d1 * q1;
1519
1520 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1521 {
1522 q1 -= 1;
1523 r0 += d1;
1524
1525 if ( r0 >= radix ) break;
1526 }
1527
Simon Butcherf5ba0452015-12-27 23:01:55 +00001528 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001529 q0 = rAX / d1;
1530 r0 = rAX - q0 * d1;
1531
1532 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1533 {
1534 q0 -= 1;
1535 r0 += d1;
1536
1537 if ( r0 >= radix ) break;
1538 }
1539
1540 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001541 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001542
1543 quotient = q1 * radix + q0;
1544
1545 return quotient;
1546#endif
1547}
1548
1549/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001551 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001552int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1553 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001554{
Paul Bakker23986e52011-04-24 08:57:21 +00001555 int ret;
1556 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001557 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001558 MPI_VALIDATE_RET( A != NULL );
1559 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001561 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1562 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001564 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1565 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001568 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001569 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1570 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001571 return( 0 );
1572 }
1573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1575 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 X.s = Y.s = 1;
1577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001578 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1579 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1580 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1581 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001582
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001583 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001584 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001585 {
1586 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001587 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1588 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001589 }
1590 else k = 0;
1591
1592 n = X.n - 1;
1593 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001594 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001596 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001597 {
1598 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001600 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001601 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001602
1603 for( i = n; i > t ; i-- )
1604 {
1605 if( X.p[i] >= Y.p[t] )
1606 Z.p[i - t - 1] = ~0;
1607 else
1608 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001609 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1610 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001611 }
1612
1613 Z.p[i - t - 1]++;
1614 do
1615 {
1616 Z.p[i - t - 1]--;
1617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001619 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001620 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001622
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001624 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1625 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001626 T2.p[2] = X.p[i];
1627 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1631 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1632 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001635 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1637 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1638 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001639 Z.p[i - t - 1]--;
1640 }
1641 }
1642
1643 if( Q != NULL )
1644 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001645 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001646 Q->s = A->s * B->s;
1647 }
1648
1649 if( R != NULL )
1650 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001652 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001656 R->s = 1;
1657 }
1658
1659cleanup:
1660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1662 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001663
1664 return( ret );
1665}
1666
1667/*
1668 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001669 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001670int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1671 const mbedtls_mpi *A,
1672 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001673{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 mbedtls_mpi _B;
1675 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001676 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001677
1678 p[0] = ( b < 0 ) ? -b : b;
1679 _B.s = ( b < 0 ) ? -1 : 1;
1680 _B.n = 1;
1681 _B.p = p;
1682
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001684}
1685
1686/*
1687 * Modulo: R = A mod B
1688 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001689int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001690{
1691 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001692 MPI_VALIDATE_RET( R != NULL );
1693 MPI_VALIDATE_RET( A != NULL );
1694 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1697 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001698
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001701 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1702 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1705 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
1707cleanup:
1708
1709 return( ret );
1710}
1711
1712/*
1713 * Modulo: r = A mod b
1714 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001716{
Paul Bakker23986e52011-04-24 08:57:21 +00001717 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001719 MPI_VALIDATE_RET( r != NULL );
1720 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001721
1722 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001724
1725 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001726 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727
1728 /*
1729 * handle trivial cases
1730 */
1731 if( b == 1 )
1732 {
1733 *r = 0;
1734 return( 0 );
1735 }
1736
1737 if( b == 2 )
1738 {
1739 *r = A->p[0] & 1;
1740 return( 0 );
1741 }
1742
1743 /*
1744 * general case
1745 */
Paul Bakker23986e52011-04-24 08:57:21 +00001746 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001747 {
Paul Bakker23986e52011-04-24 08:57:21 +00001748 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 y = ( y << biH ) | ( x >> biH );
1750 z = y / b;
1751 y -= z * b;
1752
1753 x <<= biH;
1754 y = ( y << biH ) | ( x >> biH );
1755 z = y / b;
1756 y -= z * b;
1757 }
1758
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001759 /*
1760 * If A is negative, then the current y represents a negative value.
1761 * Flipping it to the positive side.
1762 */
1763 if( A->s < 0 && y != 0 )
1764 y = b - y;
1765
Paul Bakker5121ce52009-01-03 21:22:43 +00001766 *r = y;
1767
1768 return( 0 );
1769}
1770
1771/*
1772 * Fast Montgomery initialization (thanks to Tom St Denis)
1773 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001775{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001777 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
1779 x = m0;
1780 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001781
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001782 for( i = biL; i >= 8; i /= 2 )
1783 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001784
1785 *mm = ~x + 1;
1786}
1787
1788/*
1789 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1790 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001791static 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 +02001792 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001793{
Paul Bakker23986e52011-04-24 08:57:21 +00001794 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001797 if( T->n < N->n + 1 || T->p == NULL )
1798 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1799
Paul Bakker5121ce52009-01-03 21:22:43 +00001800 memset( T->p, 0, T->n * ciL );
1801
1802 d = T->p;
1803 n = N->n;
1804 m = ( B->n < n ) ? B->n : n;
1805
1806 for( i = 0; i < n; i++ )
1807 {
1808 /*
1809 * T = (T + u0*B + u1*N) / 2^biL
1810 */
1811 u0 = A->p[i];
1812 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1813
1814 mpi_mul_hlp( m, B->p, d, u0 );
1815 mpi_mul_hlp( n, N->p, d, u1 );
1816
1817 *d++ = u0; d[n + 1] = 0;
1818 }
1819
Paul Bakker66d5d072014-06-17 16:39:18 +02001820 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001823 mpi_sub_hlp( n, N->p, A->p );
1824 else
1825 /* prevent timing attacks */
1826 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001827
1828 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001829}
1830
1831/*
1832 * Montgomery reduction: A = A * R^-1 mod N
1833 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001834static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1835 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001836{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 mbedtls_mpi_uint z = 1;
1838 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001839
Paul Bakker8ddb6452013-02-27 14:56:33 +01001840 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 U.p = &z;
1842
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001843 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001844}
1845
1846/*
1847 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1848 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001849int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1850 const mbedtls_mpi *E, const mbedtls_mpi *N,
1851 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001852{
Paul Bakker23986e52011-04-24 08:57:21 +00001853 int ret;
1854 size_t wbits, wsize, one = 1;
1855 size_t i, j, nblimbs;
1856 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 mbedtls_mpi_uint ei, mm, state;
1858 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001859 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
Hanno Becker73d7d792018-12-11 10:35:51 +00001861 MPI_VALIDATE_RET( X != NULL );
1862 MPI_VALIDATE_RET( A != NULL );
1863 MPI_VALIDATE_RET( E != NULL );
1864 MPI_VALIDATE_RET( N != NULL );
1865
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001866 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1870 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001871
1872 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001873 * Init temps and window size
1874 */
1875 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1877 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878 memset( W, 0, sizeof( W ) );
1879
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001880 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001881
1882 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1883 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1884
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001885#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1887 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001888#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001889
Paul Bakker5121ce52009-01-03 21:22:43 +00001890 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1892 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1893 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001894
1895 /*
Paul Bakker50546922012-05-19 08:40:49 +00001896 * Compensate for negative A (and correct at the end)
1897 */
1898 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001899 if( neg )
1900 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001902 Apos.s = 1;
1903 A = &Apos;
1904 }
1905
1906 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001907 * If 1st call, pre-compute R^2 mod N
1908 */
1909 if( _RR == NULL || _RR->p == NULL )
1910 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1912 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1913 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001914
1915 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 }
1918 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001920
1921 /*
1922 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1923 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1925 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001926 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001928
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001929 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930
1931 /*
1932 * X = R^2 * R^-1 mod N = R mod N
1933 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001935 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001936
1937 if( wsize > 1 )
1938 {
1939 /*
1940 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1941 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001942 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1945 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001946
1947 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001948 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01001949
Paul Bakker5121ce52009-01-03 21:22:43 +00001950 /*
1951 * W[i] = W[i - 1] * W[1]
1952 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001953 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001954 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001955 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001957
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001958 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001959 }
1960 }
1961
1962 nblimbs = E->n;
1963 bufsize = 0;
1964 nbits = 0;
1965 wbits = 0;
1966 state = 0;
1967
1968 while( 1 )
1969 {
1970 if( bufsize == 0 )
1971 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01001972 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001973 break;
1974
Paul Bakker0d7702c2013-10-29 16:18:35 +01001975 nblimbs--;
1976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001978 }
1979
1980 bufsize--;
1981
1982 ei = (E->p[nblimbs] >> bufsize) & 1;
1983
1984 /*
1985 * skip leading 0s
1986 */
1987 if( ei == 0 && state == 0 )
1988 continue;
1989
1990 if( ei == 0 && state == 1 )
1991 {
1992 /*
1993 * out of window, square X
1994 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001995 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001996 continue;
1997 }
1998
1999 /*
2000 * add ei to current window
2001 */
2002 state = 2;
2003
2004 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002005 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002006
2007 if( nbits == wsize )
2008 {
2009 /*
2010 * X = X^wsize R^-1 mod N
2011 */
2012 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002013 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
2015 /*
2016 * X = X * W[wbits] R^-1 mod N
2017 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002018 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
2020 state--;
2021 nbits = 0;
2022 wbits = 0;
2023 }
2024 }
2025
2026 /*
2027 * process the remaining bits
2028 */
2029 for( i = 0; i < nbits; i++ )
2030 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002031 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
2033 wbits <<= 1;
2034
Paul Bakker66d5d072014-06-17 16:39:18 +02002035 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002036 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002037 }
2038
2039 /*
2040 * X = A^E * R * R^-1 mod N = A^E mod N
2041 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002042 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002043
Hanno Beckera4af1c42017-04-18 09:07:45 +01002044 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002045 {
2046 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002048 }
2049
Paul Bakker5121ce52009-01-03 21:22:43 +00002050cleanup:
2051
Paul Bakker66d5d072014-06-17 16:39:18 +02002052 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002053 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002056
Paul Bakker75a28602014-03-31 12:08:17 +02002057 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002059
2060 return( ret );
2061}
2062
Paul Bakker5121ce52009-01-03 21:22:43 +00002063/*
2064 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002067{
Paul Bakker23986e52011-04-24 08:57:21 +00002068 int ret;
2069 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002071
Hanno Becker73d7d792018-12-11 10:35:51 +00002072 MPI_VALIDATE_RET( G != NULL );
2073 MPI_VALIDATE_RET( A != NULL );
2074 MPI_VALIDATE_RET( B != NULL );
2075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2079 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 lz = mbedtls_mpi_lsb( &TA );
2082 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002083
Paul Bakker66d5d072014-06-17 16:39:18 +02002084 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002085 lz = lzt;
2086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2088 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002089
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 TA.s = TB.s = 1;
2091
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002093 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2095 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002098 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2100 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002101 }
2102 else
2103 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002104 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2105 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002106 }
2107 }
2108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2110 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
2112cleanup:
2113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002114 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002115
2116 return( ret );
2117}
2118
Paul Bakker33dc46b2014-04-30 16:11:39 +02002119/*
2120 * Fill X with size bytes of random.
2121 *
2122 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002123 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002124 * deterministic, eg for tests).
2125 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002126int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002127 int (*f_rng)(void *, unsigned char *, size_t),
2128 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002129{
Paul Bakker23986e52011-04-24 08:57:21 +00002130 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002131 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002132 size_t const overhead = ( limbs * ciL ) - size;
2133 unsigned char *Xp;
2134
Hanno Becker8ce11a32018-12-19 16:18:52 +00002135 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002136 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002137
Hanno Beckerda1655a2017-10-18 14:21:44 +01002138 /* Ensure that target MPI has exactly the necessary number of limbs */
2139 if( X->n != limbs )
2140 {
2141 mbedtls_mpi_free( X );
2142 mbedtls_mpi_init( X );
2143 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2144 }
2145 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002146
Hanno Beckerda1655a2017-10-18 14:21:44 +01002147 Xp = (unsigned char*) X->p;
2148 f_rng( p_rng, Xp + overhead, size );
2149
Hanno Becker2be8a552018-10-25 12:40:09 +01002150 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002151
2152cleanup:
2153 return( ret );
2154}
2155
Paul Bakker5121ce52009-01-03 21:22:43 +00002156/*
2157 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2158 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002160{
2161 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002163 MPI_VALIDATE_RET( X != NULL );
2164 MPI_VALIDATE_RET( A != NULL );
2165 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002166
Hanno Becker4bcb4912017-04-18 15:49:39 +01002167 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2171 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2172 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002177 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002178 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002179 goto cleanup;
2180 }
2181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2183 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2184 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2185 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2188 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2189 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2190 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002191
2192 do
2193 {
2194 while( ( TU.p[0] & 1 ) == 0 )
2195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
2198 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2199 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2201 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002202 }
2203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2205 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002206 }
2207
2208 while( ( TV.p[0] & 1 ) == 0 )
2209 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002211
2212 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2213 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2215 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002216 }
2217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2219 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002220 }
2221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002222 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002223 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2225 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2226 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002227 }
2228 else
2229 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2231 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2232 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002233 }
2234 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002235 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002236
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2238 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2241 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002244
2245cleanup:
2246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2248 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2249 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002250
2251 return( ret );
2252}
2253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002255
Paul Bakker5121ce52009-01-03 21:22:43 +00002256static const int small_prime[] =
2257{
2258 3, 5, 7, 11, 13, 17, 19, 23,
2259 29, 31, 37, 41, 43, 47, 53, 59,
2260 61, 67, 71, 73, 79, 83, 89, 97,
2261 101, 103, 107, 109, 113, 127, 131, 137,
2262 139, 149, 151, 157, 163, 167, 173, 179,
2263 181, 191, 193, 197, 199, 211, 223, 227,
2264 229, 233, 239, 241, 251, 257, 263, 269,
2265 271, 277, 281, 283, 293, 307, 311, 313,
2266 317, 331, 337, 347, 349, 353, 359, 367,
2267 373, 379, 383, 389, 397, 401, 409, 419,
2268 421, 431, 433, 439, 443, 449, 457, 461,
2269 463, 467, 479, 487, 491, 499, 503, 509,
2270 521, 523, 541, 547, 557, 563, 569, 571,
2271 577, 587, 593, 599, 601, 607, 613, 617,
2272 619, 631, 641, 643, 647, 653, 659, 661,
2273 673, 677, 683, 691, 701, 709, 719, 727,
2274 733, 739, 743, 751, 757, 761, 769, 773,
2275 787, 797, 809, 811, 821, 823, 827, 829,
2276 839, 853, 857, 859, 863, 877, 881, 883,
2277 887, 907, 911, 919, 929, 937, 941, 947,
2278 953, 967, 971, 977, 983, 991, 997, -103
2279};
2280
2281/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002282 * Small divisors test (X must be positive)
2283 *
2284 * Return values:
2285 * 0: no small factor (possible prime, more tests needed)
2286 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002287 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002288 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002291{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002292 int ret = 0;
2293 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002295
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
2299 for( i = 0; small_prime[i] > 0; i++ )
2300 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002302 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002305
2306 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308 }
2309
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002310cleanup:
2311 return( ret );
2312}
2313
2314/*
2315 * Miller-Rabin pseudo-primality test (HAC 4.24)
2316 */
Janos Follathda31fa12018-09-03 14:45:23 +01002317static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002318 int (*f_rng)(void *, unsigned char *, size_t),
2319 void *p_rng )
2320{
Pascal Junodb99183d2015-03-11 16:49:45 +01002321 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002322 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002324
Hanno Becker8ce11a32018-12-19 16:18:52 +00002325 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002326 MPI_VALIDATE_RET( f_rng != NULL );
2327
2328 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2329 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002331
Paul Bakker5121ce52009-01-03 21:22:43 +00002332 /*
2333 * W = |X| - 1
2334 * R = W >> lsb( W )
2335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2337 s = mbedtls_mpi_lsb( &W );
2338 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2339 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002341 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002342
Janos Follathda31fa12018-09-03 14:45:23 +01002343 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002344 {
2345 /*
2346 * pick a random A, 1 < A < |X| - 1
2347 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002348 count = 0;
2349 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002350 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002351
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002352 j = mbedtls_mpi_bitlen( &A );
2353 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002354 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002355 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002356 }
2357
2358 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002359 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002360 }
2361
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002362 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2363 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002364
2365 /*
2366 * A = A^R mod |X|
2367 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2371 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002372 continue;
2373
2374 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002376 {
2377 /*
2378 * A = A * A mod |X|
2379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2381 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002384 break;
2385
2386 j++;
2387 }
2388
2389 /*
2390 * not prime if A != |X| - 1 or A == 1
2391 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2393 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002396 break;
2397 }
2398 }
2399
2400cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002401 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2402 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
2405 return( ret );
2406}
2407
2408/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002409 * Pseudo-primality test: small factors, then Miller-Rabin
2410 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002411int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2412 int (*f_rng)(void *, unsigned char *, size_t),
2413 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002414{
2415 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002417 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002418 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002419
2420 XX.s = 1;
2421 XX.n = X->n;
2422 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2425 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2426 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002428 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002429 return( 0 );
2430
2431 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2432 {
2433 if( ret == 1 )
2434 return( 0 );
2435
2436 return( ret );
2437 }
2438
Janos Follathda31fa12018-09-03 14:45:23 +01002439 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002440}
2441
Janos Follatha0b67c22018-09-18 14:48:23 +01002442#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002443/*
2444 * Pseudo-primality test, error probability 2^-80
2445 */
2446int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2447 int (*f_rng)(void *, unsigned char *, size_t),
2448 void *p_rng )
2449{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002450 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002451 MPI_VALIDATE_RET( f_rng != NULL );
2452
Janos Follatha0b67c22018-09-18 14:48:23 +01002453 /*
2454 * In the past our key generation aimed for an error rate of at most
2455 * 2^-80. Since this function is deprecated, aim for the same certainty
2456 * here as well.
2457 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002458 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002459}
Janos Follatha0b67c22018-09-18 14:48:23 +01002460#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002461
2462/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002463 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002464 *
Janos Follathf301d232018-08-14 13:34:01 +01002465 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2466 * be either 1024 bits or 1536 bits long, and flags must contain
2467 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002468 */
Janos Follath7c025a92018-08-14 11:08:41 +01002469int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002470 int (*f_rng)(void *, unsigned char *, size_t),
2471 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002472{
Jethro Beekman66689272018-02-14 19:24:10 -08002473#ifdef MBEDTLS_HAVE_INT64
2474// ceil(2^63.5)
2475#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2476#else
2477// ceil(2^31.5)
2478#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2479#endif
2480 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002481 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002482 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 mbedtls_mpi_uint r;
2484 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002485
Hanno Becker8ce11a32018-12-19 16:18:52 +00002486 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002487 MPI_VALIDATE_RET( f_rng != NULL );
2488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2490 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002493
2494 n = BITS_TO_LIMBS( nbits );
2495
Janos Follathda31fa12018-09-03 14:45:23 +01002496 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2497 {
2498 /*
2499 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2500 */
2501 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2502 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2503 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2504 }
2505 else
2506 {
2507 /*
2508 * 2^-100 error probability, number of rounds computed based on HAC,
2509 * fact 4.48
2510 */
2511 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2512 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2513 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2514 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2515 }
2516
Jethro Beekman66689272018-02-14 19:24:10 -08002517 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002518 {
Jethro Beekman66689272018-02-14 19:24:10 -08002519 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2520 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2521 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2522
2523 k = n * biL;
2524 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2525 X->p[0] |= 1;
2526
Janos Follath7c025a92018-08-14 11:08:41 +01002527 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002528 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002529 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002531 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002532 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002533 }
Jethro Beekman66689272018-02-14 19:24:10 -08002534 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002535 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002536 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002537 * An necessary condition for Y and X = 2Y + 1 to be prime
2538 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2539 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002540 */
Jethro Beekman66689272018-02-14 19:24:10 -08002541
2542 X->p[0] |= 2;
2543
2544 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2545 if( r == 0 )
2546 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2547 else if( r == 1 )
2548 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2549
2550 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2551 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2552 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2553
2554 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002555 {
Jethro Beekman66689272018-02-14 19:24:10 -08002556 /*
2557 * First, check small factors for X and Y
2558 * before doing Miller-Rabin on any of them
2559 */
2560 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2561 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002562 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002563 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002564 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002565 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002566 goto cleanup;
2567
2568 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2569 goto cleanup;
2570
2571 /*
2572 * Next candidates. We want to preserve Y = (X-1) / 2 and
2573 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2574 * so up Y by 6 and X by 12.
2575 */
2576 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2577 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002578 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002579 }
2580 }
2581
2582cleanup:
2583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
2586 return( ret );
2587}
2588
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002592
Paul Bakker23986e52011-04-24 08:57:21 +00002593#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002594
2595static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2596{
2597 { 693, 609, 21 },
2598 { 1764, 868, 28 },
2599 { 768454923, 542167814, 1 }
2600};
2601
Paul Bakker5121ce52009-01-03 21:22:43 +00002602/*
2603 * Checkup routine
2604 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002606{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002607 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002608 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2611 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002613 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002614 "EFE021C2645FD1DC586E69184AF4A31E" \
2615 "D5F53E93B5F123FA41680867BA110131" \
2616 "944FE7952E2517337780CB0DB80E61AA" \
2617 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002620 "B2E7EFD37075B9F03FF989C7C5051C20" \
2621 "34D2A323810251127E7BF8625A4F49A5" \
2622 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2623 "5B5C25763222FEFCCFC38B832366C29E" ) );
2624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002625 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002626 "0066A198186C18C10B2F5ED9B522752A" \
2627 "9830B69916E535C8F047518A889A43A5" \
2628 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2634 "9E857EA95A03512E2BAE7391688D264A" \
2635 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2636 "8001B72E848A38CAE1C65F78E56ABDEF" \
2637 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2638 "ECF677152EF804370C1A305CAF3B5BF1" \
2639 "30879B56C61DE584A0F53A2447A51E" ) );
2640
2641 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002642 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002644 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002645 {
2646 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002648
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002649 ret = 1;
2650 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002651 }
2652
2653 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002656 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002658 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002659 "256567336059E52CAE22925474705F39A94" ) );
2660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002662 "6613F26162223DF488E9CD48CC132C7A" \
2663 "0AC93C701B001B092E4E5B9F73BCD27B" \
2664 "9EE50D0657C77F374E903CDFA4C642" ) );
2665
2666 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002669 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2670 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002671 {
2672 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002674
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002675 ret = 1;
2676 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002677 }
2678
2679 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002680 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002685 "36E139AEA55215609D2816998ED020BB" \
2686 "BD96C37890F65171D948E9BC7CBAA4D9" \
2687 "325D24D6A3C12710F10A09FA08AB87" ) );
2688
2689 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002690 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002692 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002693 {
2694 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002695 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002696
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002697 ret = 1;
2698 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002699 }
2700
2701 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002705
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002706 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002707 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2708 "C3DBA76456363A10869622EAC2DD84EC" \
2709 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2710
2711 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002712 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002714 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002715 {
2716 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002717 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002718
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002719 ret = 1;
2720 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002721 }
2722
2723 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002724 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002725
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002726 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002727 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002728
Paul Bakker66d5d072014-06-17 16:39:18 +02002729 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002730 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2732 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002734 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002735
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002736 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002737 {
2738 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002739 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002740
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002741 ret = 1;
2742 goto cleanup;
2743 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002744 }
2745
2746 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002748
Paul Bakker5121ce52009-01-03 21:22:43 +00002749cleanup:
2750
2751 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002753
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2755 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002756
2757 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002758 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002759
2760 return( ret );
2761}
2762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002763#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002765#endif /* MBEDTLS_BIGNUM_C */