blob: c54a1fe4d0f5b347dc28eff094d05279e6665f36 [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
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001074static int ct_lt_mpi_uint( const mbedtls_mpi_uint x, const mbedtls_mpi_uint y )
1075{
1076 mbedtls_mpi_uint ret;
1077 mbedtls_mpi_uint cond;
1078
1079 /*
1080 * Check if the most significant bits (MSB) of the operands are different.
1081 */
1082 cond = ( x ^ y );
1083 /*
1084 * If the MSB are the same then the difference x-y will be negative (and
1085 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1086 */
1087 ret = ( x - y ) & ~cond;
1088 /*
1089 * If the MSB are different, then the operand with the MSB of 1 is the
1090 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1091 * the MSB of y is 0.)
1092 */
1093 ret |= y & cond;
1094
1095
1096 ret = ret >> ( sizeof( mbedtls_mpi_uint ) * 8 - 1 );
1097
1098 return ret;
1099}
1100
1101/*
1102 * Compare signed values in constant time
1103 */
1104int mbedtls_mpi_cmp_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1105 int *ret )
1106{
1107 size_t i;
1108 unsigned int cond, done;
1109
1110 MPI_VALIDATE_RET( X != NULL );
1111 MPI_VALIDATE_RET( Y != NULL );
1112 MPI_VALIDATE_RET( ret != NULL );
1113
1114 if( X->n != Y->n )
1115 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1116
1117 /*
1118 * if( X->s > 0 && Y->s < 0 )
1119 * {
1120 * *ret = 1;
1121 * done = 1;
1122 * }
1123 * else if( Y->s > 0 && X->s < 0 )
1124 * {
1125 * *ret = -1;
1126 * done = 1;
1127 * }
1128 */
1129 unsigned int sign_X = X->s;
1130 unsigned int sign_Y = Y->s;
1131 cond = ( ( sign_X ^ sign_Y ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
1132 *ret = cond * X->s;
1133 done = cond;
1134
1135 for( i = X->n; i > 0; i-- )
1136 {
1137 /*
1138 * if( ( X->p[i - 1] > Y->p[i - 1] ) && !done )
1139 * {
1140 * done = 1;
1141 * *ret = X->s;
1142 * }
1143 */
1144 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1145 *ret |= ( cond * ( 1 - done ) ) * X->s;
1146 done |= cond * ( 1 - done );
1147
1148 /*
1149 * if( ( X->p[i - 1] < Y->p[i - 1] ) && !done )
1150 * {
1151 * done = 1;
1152 * *ret = -X->s;
1153 * }
1154 */
1155 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1156 *ret |= ( cond * ( 1 - done ) ) * -X->s;
1157 done |= cond * ( 1 - done );
1158
1159 }
1160
1161 return( 0 );
1162}
1163
Paul Bakker5121ce52009-01-03 21:22:43 +00001164/*
1165 * Compare signed values
1166 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001168{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 mbedtls_mpi Y;
1170 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001171 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001172
1173 *p = ( z < 0 ) ? -z : z;
1174 Y.s = ( z < 0 ) ? -1 : 1;
1175 Y.n = 1;
1176 Y.p = p;
1177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001178 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001179}
1180
1181/*
1182 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1183 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001184int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001185{
Paul Bakker23986e52011-04-24 08:57:21 +00001186 int ret;
1187 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001188 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001189 MPI_VALIDATE_RET( X != NULL );
1190 MPI_VALIDATE_RET( A != NULL );
1191 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001192
1193 if( X == B )
1194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001196 }
1197
1198 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001199 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001200
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001201 /*
1202 * X should always be positive as a result of unsigned additions.
1203 */
1204 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001205
Paul Bakker23986e52011-04-24 08:57:21 +00001206 for( j = B->n; j > 0; j-- )
1207 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001208 break;
1209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001211
1212 o = B->p; p = X->p; c = 0;
1213
Janos Follath6c922682015-10-30 17:43:11 +01001214 /*
1215 * tmp is used because it might happen that p == o
1216 */
Paul Bakker23986e52011-04-24 08:57:21 +00001217 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001218 {
Janos Follath6c922682015-10-30 17:43:11 +01001219 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001221 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001222 }
1223
1224 while( c != 0 )
1225 {
1226 if( i >= X->n )
1227 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001228 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001229 p = X->p + i;
1230 }
1231
Paul Bakker2d319fd2012-09-16 21:34:26 +00001232 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001233 }
1234
1235cleanup:
1236
1237 return( ret );
1238}
1239
1240/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001242 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001243static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001244{
Paul Bakker23986e52011-04-24 08:57:21 +00001245 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001247
1248 for( i = c = 0; i < n; i++, s++, d++ )
1249 {
1250 z = ( *d < c ); *d -= c;
1251 c = ( *d < *s ) + z; *d -= *s;
1252 }
1253
1254 while( c != 0 )
1255 {
1256 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001257 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001258 }
1259}
1260
1261/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001262 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001265{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001267 int ret;
1268 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001269 MPI_VALIDATE_RET( X != NULL );
1270 MPI_VALIDATE_RET( A != NULL );
1271 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1274 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001276 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
1278 if( X == B )
1279 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001281 B = &TB;
1282 }
1283
1284 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001286
Paul Bakker1ef7a532009-06-20 10:50:55 +00001287 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001288 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001289 */
1290 X->s = 1;
1291
Paul Bakker5121ce52009-01-03 21:22:43 +00001292 ret = 0;
1293
Paul Bakker23986e52011-04-24 08:57:21 +00001294 for( n = B->n; n > 0; n-- )
1295 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001296 break;
1297
Paul Bakker23986e52011-04-24 08:57:21 +00001298 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001299
1300cleanup:
1301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001302 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001303
1304 return( ret );
1305}
1306
1307/*
1308 * Signed addition: X = A + B
1309 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001310int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001311{
Hanno Becker73d7d792018-12-11 10:35:51 +00001312 int ret, s;
1313 MPI_VALIDATE_RET( X != NULL );
1314 MPI_VALIDATE_RET( A != NULL );
1315 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001316
Hanno Becker73d7d792018-12-11 10:35:51 +00001317 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001318 if( A->s * B->s < 0 )
1319 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001320 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001321 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001323 X->s = s;
1324 }
1325 else
1326 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001328 X->s = -s;
1329 }
1330 }
1331 else
1332 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001333 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334 X->s = s;
1335 }
1336
1337cleanup:
1338
1339 return( ret );
1340}
1341
1342/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001343 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001344 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001346{
Hanno Becker73d7d792018-12-11 10:35:51 +00001347 int ret, s;
1348 MPI_VALIDATE_RET( X != NULL );
1349 MPI_VALIDATE_RET( A != NULL );
1350 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351
Hanno Becker73d7d792018-12-11 10:35:51 +00001352 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001353 if( A->s * B->s > 0 )
1354 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001356 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 X->s = s;
1359 }
1360 else
1361 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001363 X->s = -s;
1364 }
1365 }
1366 else
1367 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001369 X->s = s;
1370 }
1371
1372cleanup:
1373
1374 return( ret );
1375}
1376
1377/*
1378 * Signed addition: X = A + b
1379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001381{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 mbedtls_mpi _B;
1383 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001384 MPI_VALIDATE_RET( X != NULL );
1385 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
1387 p[0] = ( b < 0 ) ? -b : b;
1388 _B.s = ( b < 0 ) ? -1 : 1;
1389 _B.n = 1;
1390 _B.p = p;
1391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393}
1394
1395/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001396 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001397 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001399{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 mbedtls_mpi _B;
1401 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001402 MPI_VALIDATE_RET( X != NULL );
1403 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404
1405 p[0] = ( b < 0 ) ? -b : b;
1406 _B.s = ( b < 0 ) ? -1 : 1;
1407 _B.n = 1;
1408 _B.p = p;
1409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001411}
1412
1413/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001415 */
1416static
1417#if defined(__APPLE__) && defined(__arm__)
1418/*
1419 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1420 * appears to need this to prevent bad ARM code generation at -O3.
1421 */
1422__attribute__ ((noinline))
1423#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424void 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 +00001425{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001426 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001427
1428#if defined(MULADDC_HUIT)
1429 for( ; i >= 8; i -= 8 )
1430 {
1431 MULADDC_INIT
1432 MULADDC_HUIT
1433 MULADDC_STOP
1434 }
1435
1436 for( ; i > 0; i-- )
1437 {
1438 MULADDC_INIT
1439 MULADDC_CORE
1440 MULADDC_STOP
1441 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001442#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001443 for( ; i >= 16; i -= 16 )
1444 {
1445 MULADDC_INIT
1446 MULADDC_CORE MULADDC_CORE
1447 MULADDC_CORE MULADDC_CORE
1448 MULADDC_CORE MULADDC_CORE
1449 MULADDC_CORE MULADDC_CORE
1450
1451 MULADDC_CORE MULADDC_CORE
1452 MULADDC_CORE MULADDC_CORE
1453 MULADDC_CORE MULADDC_CORE
1454 MULADDC_CORE MULADDC_CORE
1455 MULADDC_STOP
1456 }
1457
1458 for( ; i >= 8; i -= 8 )
1459 {
1460 MULADDC_INIT
1461 MULADDC_CORE MULADDC_CORE
1462 MULADDC_CORE MULADDC_CORE
1463
1464 MULADDC_CORE MULADDC_CORE
1465 MULADDC_CORE MULADDC_CORE
1466 MULADDC_STOP
1467 }
1468
1469 for( ; i > 0; i-- )
1470 {
1471 MULADDC_INIT
1472 MULADDC_CORE
1473 MULADDC_STOP
1474 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001475#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001476
1477 t++;
1478
1479 do {
1480 *d += c; c = ( *d < c ); d++;
1481 }
1482 while( c != 0 );
1483}
1484
1485/*
1486 * Baseline multiplication: X = A * B (HAC 14.12)
1487 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001489{
Paul Bakker23986e52011-04-24 08:57:21 +00001490 int ret;
1491 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001493 MPI_VALIDATE_RET( X != NULL );
1494 MPI_VALIDATE_RET( A != NULL );
1495 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1500 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001501
Paul Bakker23986e52011-04-24 08:57:21 +00001502 for( i = A->n; i > 0; i-- )
1503 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001504 break;
1505
Paul Bakker23986e52011-04-24 08:57:21 +00001506 for( j = B->n; j > 0; j-- )
1507 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 break;
1509
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1511 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001513 for( ; j > 0; j-- )
1514 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001515
1516 X->s = A->s * B->s;
1517
1518cleanup:
1519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001521
1522 return( ret );
1523}
1524
1525/*
1526 * Baseline multiplication: X = A * b
1527 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001529{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001530 mbedtls_mpi _B;
1531 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001532 MPI_VALIDATE_RET( X != NULL );
1533 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001534
1535 _B.s = 1;
1536 _B.n = 1;
1537 _B.p = p;
1538 p[0] = b;
1539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001541}
1542
1543/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001544 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1545 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001546 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001547static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1548 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001549{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001550#if defined(MBEDTLS_HAVE_UDBL)
1551 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001552#else
Simon Butcher9803d072016-01-03 00:24:34 +00001553 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1554 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001555 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1556 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001557 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001558#endif
1559
Simon Butcher15b15d12015-11-26 19:35:03 +00001560 /*
1561 * Check for overflow
1562 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001563 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001564 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001565 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001566
Simon Butcherf5ba0452015-12-27 23:01:55 +00001567 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001568 }
1569
1570#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001571 dividend = (mbedtls_t_udbl) u1 << biL;
1572 dividend |= (mbedtls_t_udbl) u0;
1573 quotient = dividend / d;
1574 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1575 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1576
1577 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001578 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001579
1580 return (mbedtls_mpi_uint) quotient;
1581#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001582
1583 /*
1584 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1585 * Vol. 2 - Seminumerical Algorithms, Knuth
1586 */
1587
1588 /*
1589 * Normalize the divisor, d, and dividend, u0, u1
1590 */
1591 s = mbedtls_clz( d );
1592 d = d << s;
1593
1594 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001595 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001596 u0 = u0 << s;
1597
1598 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001599 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001600
1601 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001602 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001603
1604 /*
1605 * Find the first quotient and remainder
1606 */
1607 q1 = u1 / d1;
1608 r0 = u1 - d1 * q1;
1609
1610 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1611 {
1612 q1 -= 1;
1613 r0 += d1;
1614
1615 if ( r0 >= radix ) break;
1616 }
1617
Simon Butcherf5ba0452015-12-27 23:01:55 +00001618 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001619 q0 = rAX / d1;
1620 r0 = rAX - q0 * d1;
1621
1622 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1623 {
1624 q0 -= 1;
1625 r0 += d1;
1626
1627 if ( r0 >= radix ) break;
1628 }
1629
1630 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001631 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001632
1633 quotient = q1 * radix + q0;
1634
1635 return quotient;
1636#endif
1637}
1638
1639/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001641 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001642int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1643 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001644{
Paul Bakker23986e52011-04-24 08:57:21 +00001645 int ret;
1646 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001647 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001648 MPI_VALIDATE_RET( A != NULL );
1649 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1652 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1655 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001658 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1660 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 return( 0 );
1662 }
1663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1665 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666 X.s = Y.s = 1;
1667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1670 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1671 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001673 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001674 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 {
1676 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1678 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001679 }
1680 else k = 0;
1681
1682 n = X.n - 1;
1683 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001685
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001687 {
1688 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001689 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001692
1693 for( i = n; i > t ; i-- )
1694 {
1695 if( X.p[i] >= Y.p[t] )
1696 Z.p[i - t - 1] = ~0;
1697 else
1698 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001699 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1700 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001701 }
1702
1703 Z.p[i - t - 1]++;
1704 do
1705 {
1706 Z.p[i - t - 1]--;
1707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001709 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001710 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001711 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001712
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001713 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001714 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1715 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001716 T2.p[2] = X.p[i];
1717 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001720 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1721 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1722 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001725 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001726 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1727 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1728 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001729 Z.p[i - t - 1]--;
1730 }
1731 }
1732
1733 if( Q != NULL )
1734 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001735 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001736 Q->s = A->s * B->s;
1737 }
1738
1739 if( R != NULL )
1740 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001742 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001743 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001746 R->s = 1;
1747 }
1748
1749cleanup:
1750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001751 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1752 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
1754 return( ret );
1755}
1756
1757/*
1758 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001759 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001760int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1761 const mbedtls_mpi *A,
1762 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001763{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001764 mbedtls_mpi _B;
1765 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001766 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
1768 p[0] = ( b < 0 ) ? -b : b;
1769 _B.s = ( b < 0 ) ? -1 : 1;
1770 _B.n = 1;
1771 _B.p = p;
1772
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001773 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001774}
1775
1776/*
1777 * Modulo: R = A mod B
1778 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001779int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001780{
1781 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001782 MPI_VALIDATE_RET( R != NULL );
1783 MPI_VALIDATE_RET( A != NULL );
1784 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1787 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001788
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001790
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1792 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1795 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
1797cleanup:
1798
1799 return( ret );
1800}
1801
1802/*
1803 * Modulo: r = A mod b
1804 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001806{
Paul Bakker23986e52011-04-24 08:57:21 +00001807 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001809 MPI_VALIDATE_RET( r != NULL );
1810 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001811
1812 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001814
1815 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001817
1818 /*
1819 * handle trivial cases
1820 */
1821 if( b == 1 )
1822 {
1823 *r = 0;
1824 return( 0 );
1825 }
1826
1827 if( b == 2 )
1828 {
1829 *r = A->p[0] & 1;
1830 return( 0 );
1831 }
1832
1833 /*
1834 * general case
1835 */
Paul Bakker23986e52011-04-24 08:57:21 +00001836 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 {
Paul Bakker23986e52011-04-24 08:57:21 +00001838 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001839 y = ( y << biH ) | ( x >> biH );
1840 z = y / b;
1841 y -= z * b;
1842
1843 x <<= biH;
1844 y = ( y << biH ) | ( x >> biH );
1845 z = y / b;
1846 y -= z * b;
1847 }
1848
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001849 /*
1850 * If A is negative, then the current y represents a negative value.
1851 * Flipping it to the positive side.
1852 */
1853 if( A->s < 0 && y != 0 )
1854 y = b - y;
1855
Paul Bakker5121ce52009-01-03 21:22:43 +00001856 *r = y;
1857
1858 return( 0 );
1859}
1860
1861/*
1862 * Fast Montgomery initialization (thanks to Tom St Denis)
1863 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001864static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001865{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001867 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001868
1869 x = m0;
1870 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001871
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001872 for( i = biL; i >= 8; i /= 2 )
1873 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001874
1875 *mm = ~x + 1;
1876}
1877
1878/*
1879 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1880 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001881static 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 +02001882 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001883{
Paul Bakker23986e52011-04-24 08:57:21 +00001884 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001885 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001886
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001887 if( T->n < N->n + 1 || T->p == NULL )
1888 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1889
Paul Bakker5121ce52009-01-03 21:22:43 +00001890 memset( T->p, 0, T->n * ciL );
1891
1892 d = T->p;
1893 n = N->n;
1894 m = ( B->n < n ) ? B->n : n;
1895
1896 for( i = 0; i < n; i++ )
1897 {
1898 /*
1899 * T = (T + u0*B + u1*N) / 2^biL
1900 */
1901 u0 = A->p[i];
1902 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1903
1904 mpi_mul_hlp( m, B->p, d, u0 );
1905 mpi_mul_hlp( n, N->p, d, u1 );
1906
1907 *d++ = u0; d[n + 1] = 0;
1908 }
1909
Paul Bakker66d5d072014-06-17 16:39:18 +02001910 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 mpi_sub_hlp( n, N->p, A->p );
1914 else
1915 /* prevent timing attacks */
1916 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001917
1918 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001919}
1920
1921/*
1922 * Montgomery reduction: A = A * R^-1 mod N
1923 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001924static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1925 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001926{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 mbedtls_mpi_uint z = 1;
1928 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001929
Paul Bakker8ddb6452013-02-27 14:56:33 +01001930 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001931 U.p = &z;
1932
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001933 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001934}
1935
1936/*
1937 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1938 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001939int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1940 const mbedtls_mpi *E, const mbedtls_mpi *N,
1941 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001942{
Paul Bakker23986e52011-04-24 08:57:21 +00001943 int ret;
1944 size_t wbits, wsize, one = 1;
1945 size_t i, j, nblimbs;
1946 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 mbedtls_mpi_uint ei, mm, state;
1948 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001949 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001950
Hanno Becker73d7d792018-12-11 10:35:51 +00001951 MPI_VALIDATE_RET( X != NULL );
1952 MPI_VALIDATE_RET( A != NULL );
1953 MPI_VALIDATE_RET( E != NULL );
1954 MPI_VALIDATE_RET( N != NULL );
1955
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001956 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001958
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1960 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001961
1962 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001963 * Init temps and window size
1964 */
1965 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1967 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001968 memset( W, 0, sizeof( W ) );
1969
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001970 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001971
1972 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1973 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1974
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001975#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1977 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001978#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001979
Paul Bakker5121ce52009-01-03 21:22:43 +00001980 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1982 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1983 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001984
1985 /*
Paul Bakker50546922012-05-19 08:40:49 +00001986 * Compensate for negative A (and correct at the end)
1987 */
1988 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001989 if( neg )
1990 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001992 Apos.s = 1;
1993 A = &Apos;
1994 }
1995
1996 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001997 * If 1st call, pre-compute R^2 mod N
1998 */
1999 if( _RR == NULL || _RR->p == NULL )
2000 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002001 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2002 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2003 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002004
2005 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002007 }
2008 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002009 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002010
2011 /*
2012 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2013 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002014 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2015 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002016 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002019 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002020
2021 /*
2022 * X = R^2 * R^-1 mod N = R mod N
2023 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002025 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002026
2027 if( wsize > 1 )
2028 {
2029 /*
2030 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2031 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002032 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2035 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002036
2037 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002038 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002039
Paul Bakker5121ce52009-01-03 21:22:43 +00002040 /*
2041 * W[i] = W[i - 1] * W[1]
2042 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002043 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002044 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2046 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002048 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002049 }
2050 }
2051
2052 nblimbs = E->n;
2053 bufsize = 0;
2054 nbits = 0;
2055 wbits = 0;
2056 state = 0;
2057
2058 while( 1 )
2059 {
2060 if( bufsize == 0 )
2061 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002062 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002063 break;
2064
Paul Bakker0d7702c2013-10-29 16:18:35 +01002065 nblimbs--;
2066
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002068 }
2069
2070 bufsize--;
2071
2072 ei = (E->p[nblimbs] >> bufsize) & 1;
2073
2074 /*
2075 * skip leading 0s
2076 */
2077 if( ei == 0 && state == 0 )
2078 continue;
2079
2080 if( ei == 0 && state == 1 )
2081 {
2082 /*
2083 * out of window, square X
2084 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002085 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086 continue;
2087 }
2088
2089 /*
2090 * add ei to current window
2091 */
2092 state = 2;
2093
2094 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002095 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
2097 if( nbits == wsize )
2098 {
2099 /*
2100 * X = X^wsize R^-1 mod N
2101 */
2102 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002103 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
2105 /*
2106 * X = X * W[wbits] R^-1 mod N
2107 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002108 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002109
2110 state--;
2111 nbits = 0;
2112 wbits = 0;
2113 }
2114 }
2115
2116 /*
2117 * process the remaining bits
2118 */
2119 for( i = 0; i < nbits; i++ )
2120 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002121 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002122
2123 wbits <<= 1;
2124
Paul Bakker66d5d072014-06-17 16:39:18 +02002125 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002126 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002127 }
2128
2129 /*
2130 * X = A^E * R * R^-1 mod N = A^E mod N
2131 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002132 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
Hanno Beckera4af1c42017-04-18 09:07:45 +01002134 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002135 {
2136 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002137 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002138 }
2139
Paul Bakker5121ce52009-01-03 21:22:43 +00002140cleanup:
2141
Paul Bakker66d5d072014-06-17 16:39:18 +02002142 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002143 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002146
Paul Bakker75a28602014-03-31 12:08:17 +02002147 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
2150 return( ret );
2151}
2152
Paul Bakker5121ce52009-01-03 21:22:43 +00002153/*
2154 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2155 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002157{
Paul Bakker23986e52011-04-24 08:57:21 +00002158 int ret;
2159 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002161
Hanno Becker73d7d792018-12-11 10:35:51 +00002162 MPI_VALIDATE_RET( G != NULL );
2163 MPI_VALIDATE_RET( A != NULL );
2164 MPI_VALIDATE_RET( B != NULL );
2165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2169 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 lz = mbedtls_mpi_lsb( &TA );
2172 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002173
Paul Bakker66d5d072014-06-17 16:39:18 +02002174 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002175 lz = lzt;
2176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2178 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002179
Paul Bakker5121ce52009-01-03 21:22:43 +00002180 TA.s = TB.s = 1;
2181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002183 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2185 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002188 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2190 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002191 }
2192 else
2193 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002194 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2195 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002196 }
2197 }
2198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2200 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
2202cleanup:
2203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002204 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
2206 return( ret );
2207}
2208
Paul Bakker33dc46b2014-04-30 16:11:39 +02002209/*
2210 * Fill X with size bytes of random.
2211 *
2212 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002213 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002214 * deterministic, eg for tests).
2215 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002216int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002217 int (*f_rng)(void *, unsigned char *, size_t),
2218 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002219{
Paul Bakker23986e52011-04-24 08:57:21 +00002220 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002221 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002222 size_t const overhead = ( limbs * ciL ) - size;
2223 unsigned char *Xp;
2224
Hanno Becker8ce11a32018-12-19 16:18:52 +00002225 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002226 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002227
Hanno Beckerda1655a2017-10-18 14:21:44 +01002228 /* Ensure that target MPI has exactly the necessary number of limbs */
2229 if( X->n != limbs )
2230 {
2231 mbedtls_mpi_free( X );
2232 mbedtls_mpi_init( X );
2233 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2234 }
2235 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002236
Hanno Beckerda1655a2017-10-18 14:21:44 +01002237 Xp = (unsigned char*) X->p;
2238 f_rng( p_rng, Xp + overhead, size );
2239
Hanno Becker2be8a552018-10-25 12:40:09 +01002240 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002241
2242cleanup:
2243 return( ret );
2244}
2245
Paul Bakker5121ce52009-01-03 21:22:43 +00002246/*
2247 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002250{
2251 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002252 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002253 MPI_VALIDATE_RET( X != NULL );
2254 MPI_VALIDATE_RET( A != NULL );
2255 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002256
Hanno Becker4bcb4912017-04-18 15:49:39 +01002257 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2261 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2262 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002269 goto cleanup;
2270 }
2271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2273 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2274 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2275 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2278 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2279 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2280 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002281
2282 do
2283 {
2284 while( ( TU.p[0] & 1 ) == 0 )
2285 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002287
2288 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2289 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2291 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 }
2293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2295 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 }
2297
2298 while( ( TV.p[0] & 1 ) == 0 )
2299 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002301
2302 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2303 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2305 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 }
2307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2309 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310 }
2311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002313 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2315 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2316 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 }
2318 else
2319 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002320 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2321 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2322 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002323 }
2324 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2328 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2331 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334
2335cleanup:
2336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2338 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2339 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
2341 return( ret );
2342}
2343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002345
Paul Bakker5121ce52009-01-03 21:22:43 +00002346static const int small_prime[] =
2347{
2348 3, 5, 7, 11, 13, 17, 19, 23,
2349 29, 31, 37, 41, 43, 47, 53, 59,
2350 61, 67, 71, 73, 79, 83, 89, 97,
2351 101, 103, 107, 109, 113, 127, 131, 137,
2352 139, 149, 151, 157, 163, 167, 173, 179,
2353 181, 191, 193, 197, 199, 211, 223, 227,
2354 229, 233, 239, 241, 251, 257, 263, 269,
2355 271, 277, 281, 283, 293, 307, 311, 313,
2356 317, 331, 337, 347, 349, 353, 359, 367,
2357 373, 379, 383, 389, 397, 401, 409, 419,
2358 421, 431, 433, 439, 443, 449, 457, 461,
2359 463, 467, 479, 487, 491, 499, 503, 509,
2360 521, 523, 541, 547, 557, 563, 569, 571,
2361 577, 587, 593, 599, 601, 607, 613, 617,
2362 619, 631, 641, 643, 647, 653, 659, 661,
2363 673, 677, 683, 691, 701, 709, 719, 727,
2364 733, 739, 743, 751, 757, 761, 769, 773,
2365 787, 797, 809, 811, 821, 823, 827, 829,
2366 839, 853, 857, 859, 863, 877, 881, 883,
2367 887, 907, 911, 919, 929, 937, 941, 947,
2368 953, 967, 971, 977, 983, 991, 997, -103
2369};
2370
2371/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002372 * Small divisors test (X must be positive)
2373 *
2374 * Return values:
2375 * 0: no small factor (possible prime, more tests needed)
2376 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002377 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002378 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002381{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002382 int ret = 0;
2383 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
Paul Bakker5121ce52009-01-03 21:22:43 +00002386 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002388
2389 for( i = 0; small_prime[i] > 0; i++ )
2390 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002392 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002395
2396 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002398 }
2399
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002400cleanup:
2401 return( ret );
2402}
2403
2404/*
2405 * Miller-Rabin pseudo-primality test (HAC 4.24)
2406 */
Janos Follathda31fa12018-09-03 14:45:23 +01002407static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002408 int (*f_rng)(void *, unsigned char *, size_t),
2409 void *p_rng )
2410{
Pascal Junodb99183d2015-03-11 16:49:45 +01002411 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002412 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002413 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002414
Hanno Becker8ce11a32018-12-19 16:18:52 +00002415 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002416 MPI_VALIDATE_RET( f_rng != NULL );
2417
2418 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2419 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002420 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002421
Paul Bakker5121ce52009-01-03 21:22:43 +00002422 /*
2423 * W = |X| - 1
2424 * R = W >> lsb( W )
2425 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2427 s = mbedtls_mpi_lsb( &W );
2428 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2429 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002430
Janos Follathda31fa12018-09-03 14:45:23 +01002431 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002432 {
2433 /*
2434 * pick a random A, 1 < A < |X| - 1
2435 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002436 count = 0;
2437 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002438 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002439
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002440 j = mbedtls_mpi_bitlen( &A );
2441 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002442 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002443 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002444 }
2445
2446 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002447 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2448 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002449 }
2450
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002451 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2452 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002453
2454 /*
2455 * A = A^R mod |X|
2456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002459 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2460 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002461 continue;
2462
2463 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002464 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002465 {
2466 /*
2467 * A = A * A mod |X|
2468 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002469 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2470 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002473 break;
2474
2475 j++;
2476 }
2477
2478 /*
2479 * not prime if A != |X| - 1 or A == 1
2480 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2482 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002483 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002485 break;
2486 }
2487 }
2488
2489cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002490 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2491 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002493
2494 return( ret );
2495}
2496
2497/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002498 * Pseudo-primality test: small factors, then Miller-Rabin
2499 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002500int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2501 int (*f_rng)(void *, unsigned char *, size_t),
2502 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002503{
2504 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002506 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002507 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002508
2509 XX.s = 1;
2510 XX.n = X->n;
2511 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002513 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2514 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2515 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002517 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002518 return( 0 );
2519
2520 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2521 {
2522 if( ret == 1 )
2523 return( 0 );
2524
2525 return( ret );
2526 }
2527
Janos Follathda31fa12018-09-03 14:45:23 +01002528 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002529}
2530
Janos Follatha0b67c22018-09-18 14:48:23 +01002531#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002532/*
2533 * Pseudo-primality test, error probability 2^-80
2534 */
2535int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2536 int (*f_rng)(void *, unsigned char *, size_t),
2537 void *p_rng )
2538{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002539 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002540 MPI_VALIDATE_RET( f_rng != NULL );
2541
Janos Follatha0b67c22018-09-18 14:48:23 +01002542 /*
2543 * In the past our key generation aimed for an error rate of at most
2544 * 2^-80. Since this function is deprecated, aim for the same certainty
2545 * here as well.
2546 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002547 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002548}
Janos Follatha0b67c22018-09-18 14:48:23 +01002549#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002550
2551/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002552 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002553 *
Janos Follathf301d232018-08-14 13:34:01 +01002554 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2555 * be either 1024 bits or 1536 bits long, and flags must contain
2556 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002557 */
Janos Follath7c025a92018-08-14 11:08:41 +01002558int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002559 int (*f_rng)(void *, unsigned char *, size_t),
2560 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002561{
Jethro Beekman66689272018-02-14 19:24:10 -08002562#ifdef MBEDTLS_HAVE_INT64
2563// ceil(2^63.5)
2564#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2565#else
2566// ceil(2^31.5)
2567#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2568#endif
2569 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002570 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002571 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002572 mbedtls_mpi_uint r;
2573 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002574
Hanno Becker8ce11a32018-12-19 16:18:52 +00002575 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002576 MPI_VALIDATE_RET( f_rng != NULL );
2577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002578 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2579 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002582
2583 n = BITS_TO_LIMBS( nbits );
2584
Janos Follathda31fa12018-09-03 14:45:23 +01002585 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2586 {
2587 /*
2588 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2589 */
2590 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2591 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2592 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2593 }
2594 else
2595 {
2596 /*
2597 * 2^-100 error probability, number of rounds computed based on HAC,
2598 * fact 4.48
2599 */
2600 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2601 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2602 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2603 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2604 }
2605
Jethro Beekman66689272018-02-14 19:24:10 -08002606 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002607 {
Jethro Beekman66689272018-02-14 19:24:10 -08002608 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2609 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2610 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2611
2612 k = n * biL;
2613 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2614 X->p[0] |= 1;
2615
Janos Follath7c025a92018-08-14 11:08:41 +01002616 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002617 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002618 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002620 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002621 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002622 }
Jethro Beekman66689272018-02-14 19:24:10 -08002623 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002624 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002625 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002626 * An necessary condition for Y and X = 2Y + 1 to be prime
2627 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2628 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002629 */
Jethro Beekman66689272018-02-14 19:24:10 -08002630
2631 X->p[0] |= 2;
2632
2633 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2634 if( r == 0 )
2635 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2636 else if( r == 1 )
2637 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2638
2639 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2640 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2641 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2642
2643 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002644 {
Jethro Beekman66689272018-02-14 19:24:10 -08002645 /*
2646 * First, check small factors for X and Y
2647 * before doing Miller-Rabin on any of them
2648 */
2649 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2650 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002651 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002652 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002653 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002654 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002655 goto cleanup;
2656
2657 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2658 goto cleanup;
2659
2660 /*
2661 * Next candidates. We want to preserve Y = (X-1) / 2 and
2662 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2663 * so up Y by 6 and X by 12.
2664 */
2665 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2666 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002667 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002668 }
2669 }
2670
2671cleanup:
2672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002674
2675 return( ret );
2676}
2677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002678#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002679
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002680#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002681
Paul Bakker23986e52011-04-24 08:57:21 +00002682#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002683
2684static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2685{
2686 { 693, 609, 21 },
2687 { 1764, 868, 28 },
2688 { 768454923, 542167814, 1 }
2689};
2690
Paul Bakker5121ce52009-01-03 21:22:43 +00002691/*
2692 * Checkup routine
2693 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002695{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002696 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002698
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002699 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2700 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002703 "EFE021C2645FD1DC586E69184AF4A31E" \
2704 "D5F53E93B5F123FA41680867BA110131" \
2705 "944FE7952E2517337780CB0DB80E61AA" \
2706 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002709 "B2E7EFD37075B9F03FF989C7C5051C20" \
2710 "34D2A323810251127E7BF8625A4F49A5" \
2711 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2712 "5B5C25763222FEFCCFC38B832366C29E" ) );
2713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002714 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002715 "0066A198186C18C10B2F5ED9B522752A" \
2716 "9830B69916E535C8F047518A889A43A5" \
2717 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002719 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002721 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002722 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2723 "9E857EA95A03512E2BAE7391688D264A" \
2724 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2725 "8001B72E848A38CAE1C65F78E56ABDEF" \
2726 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2727 "ECF677152EF804370C1A305CAF3B5BF1" \
2728 "30879B56C61DE584A0F53A2447A51E" ) );
2729
2730 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002733 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002734 {
2735 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002736 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002737
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002738 ret = 1;
2739 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002740 }
2741
2742 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002743 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002745 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002748 "256567336059E52CAE22925474705F39A94" ) );
2749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002750 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002751 "6613F26162223DF488E9CD48CC132C7A" \
2752 "0AC93C701B001B092E4E5B9F73BCD27B" \
2753 "9EE50D0657C77F374E903CDFA4C642" ) );
2754
2755 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002757
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002758 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2759 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002760 {
2761 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002762 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002763
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002764 ret = 1;
2765 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002766 }
2767
2768 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002769 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002770
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002771 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002772
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002773 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002774 "36E139AEA55215609D2816998ED020BB" \
2775 "BD96C37890F65171D948E9BC7CBAA4D9" \
2776 "325D24D6A3C12710F10A09FA08AB87" ) );
2777
2778 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002779 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002780
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002781 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002782 {
2783 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002784 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002785
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002786 ret = 1;
2787 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002788 }
2789
2790 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002791 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002792
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002793 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002796 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2797 "C3DBA76456363A10869622EAC2DD84EC" \
2798 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2799
2800 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002801 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002804 {
2805 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002806 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002807
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002808 ret = 1;
2809 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002810 }
2811
2812 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002813 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002814
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002815 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002816 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002817
Paul Bakker66d5d072014-06-17 16:39:18 +02002818 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002819 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002820 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2821 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002823 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002826 {
2827 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002828 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002829
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002830 ret = 1;
2831 goto cleanup;
2832 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002833 }
2834
2835 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002836 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002837
Paul Bakker5121ce52009-01-03 21:22:43 +00002838cleanup:
2839
2840 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002841 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002842
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002843 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2844 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002845
2846 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002847 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002848
2849 return( ret );
2850}
2851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002852#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002854#endif /* MBEDTLS_BIGNUM_C */