blob: e7275333f28ee9a55f065473381b4befa075053f [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 Follath867a3ab2019-10-11 14:21:53 +01001074static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1075 const mbedtls_mpi_uint y )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001076{
1077 mbedtls_mpi_uint ret;
1078 mbedtls_mpi_uint cond;
1079
1080 /*
1081 * Check if the most significant bits (MSB) of the operands are different.
1082 */
1083 cond = ( x ^ y );
1084 /*
1085 * If the MSB are the same then the difference x-y will be negative (and
1086 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1087 */
1088 ret = ( x - y ) & ~cond;
1089 /*
1090 * If the MSB are different, then the operand with the MSB of 1 is the
1091 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1092 * the MSB of y is 0.)
1093 */
1094 ret |= y & cond;
1095
1096
Janos Follath7a34bcf2019-10-14 08:59:14 +01001097 ret = ret >> ( biL - 1 );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001098
1099 return ret;
1100}
1101
1102/*
1103 * Compare signed values in constant time
1104 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001105int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1106 unsigned *ret )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001107{
1108 size_t i;
Janos Follath4ea23192019-09-23 09:19:14 +01001109 unsigned int cond, done, sign_X, sign_Y;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001110
1111 MPI_VALIDATE_RET( X != NULL );
1112 MPI_VALIDATE_RET( Y != NULL );
1113 MPI_VALIDATE_RET( ret != NULL );
1114
1115 if( X->n != Y->n )
1116 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1117
1118 /*
Janos Follath867a3ab2019-10-11 14:21:53 +01001119 * Get sign bits of the signs.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001120 */
Janos Follath4ea23192019-09-23 09:19:14 +01001121 sign_X = X->s;
Janos Follath867a3ab2019-10-11 14:21:53 +01001122 sign_X = sign_X >> ( sizeof( unsigned int ) * 8 - 1 );
Janos Follath4ea23192019-09-23 09:19:14 +01001123 sign_Y = Y->s;
Janos Follath867a3ab2019-10-11 14:21:53 +01001124 sign_Y = sign_Y >> ( sizeof( unsigned int ) * 8 - 1 );
1125
1126 /*
1127 * If the signs are different, then the positive operand is the bigger.
1128 * That is if X is negative (sign bit 1), then X < Y is true and it is false
1129 * if X is positive (sign bit 0).
1130 */
1131 cond = ( sign_X ^ sign_Y );
1132 *ret = cond & sign_X;
1133
1134 /*
1135 * This is a constant time function, we might have the result, but we still
1136 * need to go through the loop. Record if we have the result already.
1137 */
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001138 done = cond;
1139
1140 for( i = X->n; i > 0; i-- )
1141 {
1142 /*
Janos Follath867a3ab2019-10-11 14:21:53 +01001143 * If Y->p[i - 1] < X->p[i - 1] and both X and Y are negative, then
1144 * X < Y.
1145 *
1146 * Again even if we can make a decision, we just mark the result and
1147 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001148 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001149 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ) & sign_X;
1150 *ret |= cond & ( 1 - done );
Janos Follath4f6cf382019-10-11 10:43:40 +01001151 done |= cond & ( 1 - done );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001152
1153 /*
Janos Follath867a3ab2019-10-11 14:21:53 +01001154 * If X->p[i - 1] < Y->p[i - 1] and both X and Y are positive, then
1155 * X < Y.
1156 *
1157 * Again even if we can make a decision, we just mark the result and
1158 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001159 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001160 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ) & ( 1 - sign_X );
1161 *ret |= cond & ( 1 - done );
Janos Follath4f6cf382019-10-11 10:43:40 +01001162 done |= cond & ( 1 - done );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001163 }
1164
1165 return( 0 );
1166}
1167
Paul Bakker5121ce52009-01-03 21:22:43 +00001168/*
1169 * Compare signed values
1170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001171int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001172{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173 mbedtls_mpi Y;
1174 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001175 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001176
1177 *p = ( z < 0 ) ? -z : z;
1178 Y.s = ( z < 0 ) ? -1 : 1;
1179 Y.n = 1;
1180 Y.p = p;
1181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183}
1184
1185/*
1186 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001189{
Paul Bakker23986e52011-04-24 08:57:21 +00001190 int ret;
1191 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001192 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001193 MPI_VALIDATE_RET( X != NULL );
1194 MPI_VALIDATE_RET( A != NULL );
1195 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
1197 if( X == B )
1198 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001199 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001200 }
1201
1202 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001203 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001204
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001205 /*
1206 * X should always be positive as a result of unsigned additions.
1207 */
1208 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001209
Paul Bakker23986e52011-04-24 08:57:21 +00001210 for( j = B->n; j > 0; j-- )
1211 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001212 break;
1213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
1216 o = B->p; p = X->p; c = 0;
1217
Janos Follath6c922682015-10-30 17:43:11 +01001218 /*
1219 * tmp is used because it might happen that p == o
1220 */
Paul Bakker23986e52011-04-24 08:57:21 +00001221 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001222 {
Janos Follath6c922682015-10-30 17:43:11 +01001223 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001224 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001225 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001226 }
1227
1228 while( c != 0 )
1229 {
1230 if( i >= X->n )
1231 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001233 p = X->p + i;
1234 }
1235
Paul Bakker2d319fd2012-09-16 21:34:26 +00001236 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001237 }
1238
1239cleanup:
1240
1241 return( ret );
1242}
1243
1244/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001248{
Paul Bakker23986e52011-04-24 08:57:21 +00001249 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001251
1252 for( i = c = 0; i < n; i++, s++, d++ )
1253 {
1254 z = ( *d < c ); *d -= c;
1255 c = ( *d < *s ) + z; *d -= *s;
1256 }
1257
1258 while( c != 0 )
1259 {
1260 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001261 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001262 }
1263}
1264
1265/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001266 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001267 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001268int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001269{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001270 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001271 int ret;
1272 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001273 MPI_VALIDATE_RET( X != NULL );
1274 MPI_VALIDATE_RET( A != NULL );
1275 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1278 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001281
1282 if( X == B )
1283 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001285 B = &TB;
1286 }
1287
1288 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001290
Paul Bakker1ef7a532009-06-20 10:50:55 +00001291 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001292 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001293 */
1294 X->s = 1;
1295
Paul Bakker5121ce52009-01-03 21:22:43 +00001296 ret = 0;
1297
Paul Bakker23986e52011-04-24 08:57:21 +00001298 for( n = B->n; n > 0; n-- )
1299 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001300 break;
1301
Paul Bakker23986e52011-04-24 08:57:21 +00001302 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001303
1304cleanup:
1305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001307
1308 return( ret );
1309}
1310
1311/*
1312 * Signed addition: X = A + B
1313 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001315{
Hanno Becker73d7d792018-12-11 10:35:51 +00001316 int ret, s;
1317 MPI_VALIDATE_RET( X != NULL );
1318 MPI_VALIDATE_RET( A != NULL );
1319 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001320
Hanno Becker73d7d792018-12-11 10:35:51 +00001321 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001322 if( A->s * B->s < 0 )
1323 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001325 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001326 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 X->s = s;
1328 }
1329 else
1330 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 X->s = -s;
1333 }
1334 }
1335 else
1336 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 X->s = s;
1339 }
1340
1341cleanup:
1342
1343 return( ret );
1344}
1345
1346/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001347 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001350{
Hanno Becker73d7d792018-12-11 10:35:51 +00001351 int ret, s;
1352 MPI_VALIDATE_RET( X != NULL );
1353 MPI_VALIDATE_RET( A != NULL );
1354 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
Hanno Becker73d7d792018-12-11 10:35:51 +00001356 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001357 if( A->s * B->s > 0 )
1358 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001360 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362 X->s = s;
1363 }
1364 else
1365 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 X->s = -s;
1368 }
1369 }
1370 else
1371 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001373 X->s = s;
1374 }
1375
1376cleanup:
1377
1378 return( ret );
1379}
1380
1381/*
1382 * Signed addition: X = A + b
1383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001385{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001386 mbedtls_mpi _B;
1387 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001388 MPI_VALIDATE_RET( X != NULL );
1389 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001390
1391 p[0] = ( b < 0 ) ? -b : b;
1392 _B.s = ( b < 0 ) ? -1 : 1;
1393 _B.n = 1;
1394 _B.p = p;
1395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001397}
1398
1399/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001400 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001401 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001402int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001403{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001404 mbedtls_mpi _B;
1405 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001406 MPI_VALIDATE_RET( X != NULL );
1407 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001408
1409 p[0] = ( b < 0 ) ? -b : b;
1410 _B.s = ( b < 0 ) ? -1 : 1;
1411 _B.n = 1;
1412 _B.p = p;
1413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415}
1416
1417/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001419 */
1420static
1421#if defined(__APPLE__) && defined(__arm__)
1422/*
1423 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1424 * appears to need this to prevent bad ARM code generation at -O3.
1425 */
1426__attribute__ ((noinline))
1427#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428void 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 +00001429{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001431
1432#if defined(MULADDC_HUIT)
1433 for( ; i >= 8; i -= 8 )
1434 {
1435 MULADDC_INIT
1436 MULADDC_HUIT
1437 MULADDC_STOP
1438 }
1439
1440 for( ; i > 0; i-- )
1441 {
1442 MULADDC_INIT
1443 MULADDC_CORE
1444 MULADDC_STOP
1445 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001446#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001447 for( ; i >= 16; i -= 16 )
1448 {
1449 MULADDC_INIT
1450 MULADDC_CORE MULADDC_CORE
1451 MULADDC_CORE MULADDC_CORE
1452 MULADDC_CORE MULADDC_CORE
1453 MULADDC_CORE MULADDC_CORE
1454
1455 MULADDC_CORE MULADDC_CORE
1456 MULADDC_CORE MULADDC_CORE
1457 MULADDC_CORE MULADDC_CORE
1458 MULADDC_CORE MULADDC_CORE
1459 MULADDC_STOP
1460 }
1461
1462 for( ; i >= 8; i -= 8 )
1463 {
1464 MULADDC_INIT
1465 MULADDC_CORE MULADDC_CORE
1466 MULADDC_CORE MULADDC_CORE
1467
1468 MULADDC_CORE MULADDC_CORE
1469 MULADDC_CORE MULADDC_CORE
1470 MULADDC_STOP
1471 }
1472
1473 for( ; i > 0; i-- )
1474 {
1475 MULADDC_INIT
1476 MULADDC_CORE
1477 MULADDC_STOP
1478 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001479#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
1481 t++;
1482
1483 do {
1484 *d += c; c = ( *d < c ); d++;
1485 }
1486 while( c != 0 );
1487}
1488
1489/*
1490 * Baseline multiplication: X = A * B (HAC 14.12)
1491 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001493{
Paul Bakker23986e52011-04-24 08:57:21 +00001494 int ret;
1495 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001497 MPI_VALIDATE_RET( X != NULL );
1498 MPI_VALIDATE_RET( A != NULL );
1499 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1504 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001505
Paul Bakker23986e52011-04-24 08:57:21 +00001506 for( i = A->n; i > 0; i-- )
1507 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001508 break;
1509
Paul Bakker23986e52011-04-24 08:57:21 +00001510 for( j = B->n; j > 0; j-- )
1511 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001512 break;
1513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1515 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001517 for( ; j > 0; j-- )
1518 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001519
1520 X->s = A->s * B->s;
1521
1522cleanup:
1523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001525
1526 return( ret );
1527}
1528
1529/*
1530 * Baseline multiplication: X = A * b
1531 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001532int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001533{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 mbedtls_mpi _B;
1535 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001536 MPI_VALIDATE_RET( X != NULL );
1537 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001538
1539 _B.s = 1;
1540 _B.n = 1;
1541 _B.p = p;
1542 p[0] = b;
1543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001545}
1546
1547/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001548 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1549 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001550 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001551static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1552 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001553{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001554#if defined(MBEDTLS_HAVE_UDBL)
1555 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001556#else
Simon Butcher9803d072016-01-03 00:24:34 +00001557 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1558 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001559 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1560 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001561 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001562#endif
1563
Simon Butcher15b15d12015-11-26 19:35:03 +00001564 /*
1565 * Check for overflow
1566 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001567 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001568 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001569 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001570
Simon Butcherf5ba0452015-12-27 23:01:55 +00001571 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001572 }
1573
1574#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001575 dividend = (mbedtls_t_udbl) u1 << biL;
1576 dividend |= (mbedtls_t_udbl) u0;
1577 quotient = dividend / d;
1578 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1579 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1580
1581 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001582 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001583
1584 return (mbedtls_mpi_uint) quotient;
1585#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001586
1587 /*
1588 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1589 * Vol. 2 - Seminumerical Algorithms, Knuth
1590 */
1591
1592 /*
1593 * Normalize the divisor, d, and dividend, u0, u1
1594 */
1595 s = mbedtls_clz( d );
1596 d = d << s;
1597
1598 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001599 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001600 u0 = u0 << s;
1601
1602 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001603 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001604
1605 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001606 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001607
1608 /*
1609 * Find the first quotient and remainder
1610 */
1611 q1 = u1 / d1;
1612 r0 = u1 - d1 * q1;
1613
1614 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1615 {
1616 q1 -= 1;
1617 r0 += d1;
1618
1619 if ( r0 >= radix ) break;
1620 }
1621
Simon Butcherf5ba0452015-12-27 23:01:55 +00001622 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001623 q0 = rAX / d1;
1624 r0 = rAX - q0 * d1;
1625
1626 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1627 {
1628 q0 -= 1;
1629 r0 += d1;
1630
1631 if ( r0 >= radix ) break;
1632 }
1633
1634 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001635 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001636
1637 quotient = q1 * radix + q0;
1638
1639 return quotient;
1640#endif
1641}
1642
1643/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001645 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001646int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1647 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001648{
Paul Bakker23986e52011-04-24 08:57:21 +00001649 int ret;
1650 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001652 MPI_VALIDATE_RET( A != NULL );
1653 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1656 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1659 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001662 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1664 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001665 return( 0 );
1666 }
1667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670 X.s = Y.s = 1;
1671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001672 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1674 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001676
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001677 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001678 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001679 {
1680 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001681 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1682 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683 }
1684 else k = 0;
1685
1686 n = X.n - 1;
1687 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001691 {
1692 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001695 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
1697 for( i = n; i > t ; i-- )
1698 {
1699 if( X.p[i] >= Y.p[t] )
1700 Z.p[i - t - 1] = ~0;
1701 else
1702 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001703 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1704 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001705 }
1706
1707 Z.p[i - t - 1]++;
1708 do
1709 {
1710 Z.p[i - t - 1]--;
1711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001712 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001713 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001714 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001718 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1719 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 T2.p[2] = X.p[i];
1721 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1725 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1726 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001729 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1731 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1732 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 Z.p[i - t - 1]--;
1734 }
1735 }
1736
1737 if( Q != NULL )
1738 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001740 Q->s = A->s * B->s;
1741 }
1742
1743 if( R != NULL )
1744 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001746 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001750 R->s = 1;
1751 }
1752
1753cleanup:
1754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1756 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001757
1758 return( ret );
1759}
1760
1761/*
1762 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001763 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001764int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1765 const mbedtls_mpi *A,
1766 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001767{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 mbedtls_mpi _B;
1769 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001770 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001771
1772 p[0] = ( b < 0 ) ? -b : b;
1773 _B.s = ( b < 0 ) ? -1 : 1;
1774 _B.n = 1;
1775 _B.p = p;
1776
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001777 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001778}
1779
1780/*
1781 * Modulo: R = A mod B
1782 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001783int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001784{
1785 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001786 MPI_VALIDATE_RET( R != NULL );
1787 MPI_VALIDATE_RET( A != NULL );
1788 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1791 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001792
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1796 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001798 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1799 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001800
1801cleanup:
1802
1803 return( ret );
1804}
1805
1806/*
1807 * Modulo: r = A mod b
1808 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001809int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001810{
Paul Bakker23986e52011-04-24 08:57:21 +00001811 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001813 MPI_VALIDATE_RET( r != NULL );
1814 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001815
1816 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001818
1819 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001821
1822 /*
1823 * handle trivial cases
1824 */
1825 if( b == 1 )
1826 {
1827 *r = 0;
1828 return( 0 );
1829 }
1830
1831 if( b == 2 )
1832 {
1833 *r = A->p[0] & 1;
1834 return( 0 );
1835 }
1836
1837 /*
1838 * general case
1839 */
Paul Bakker23986e52011-04-24 08:57:21 +00001840 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001841 {
Paul Bakker23986e52011-04-24 08:57:21 +00001842 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001843 y = ( y << biH ) | ( x >> biH );
1844 z = y / b;
1845 y -= z * b;
1846
1847 x <<= biH;
1848 y = ( y << biH ) | ( x >> biH );
1849 z = y / b;
1850 y -= z * b;
1851 }
1852
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001853 /*
1854 * If A is negative, then the current y represents a negative value.
1855 * Flipping it to the positive side.
1856 */
1857 if( A->s < 0 && y != 0 )
1858 y = b - y;
1859
Paul Bakker5121ce52009-01-03 21:22:43 +00001860 *r = y;
1861
1862 return( 0 );
1863}
1864
1865/*
1866 * Fast Montgomery initialization (thanks to Tom St Denis)
1867 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001869{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001871 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001872
1873 x = m0;
1874 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001875
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001876 for( i = biL; i >= 8; i /= 2 )
1877 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
1879 *mm = ~x + 1;
1880}
1881
1882/*
1883 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1884 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001885static 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 +02001886 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001887{
Paul Bakker23986e52011-04-24 08:57:21 +00001888 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001889 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001890
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001891 if( T->n < N->n + 1 || T->p == NULL )
1892 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1893
Paul Bakker5121ce52009-01-03 21:22:43 +00001894 memset( T->p, 0, T->n * ciL );
1895
1896 d = T->p;
1897 n = N->n;
1898 m = ( B->n < n ) ? B->n : n;
1899
1900 for( i = 0; i < n; i++ )
1901 {
1902 /*
1903 * T = (T + u0*B + u1*N) / 2^biL
1904 */
1905 u0 = A->p[i];
1906 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1907
1908 mpi_mul_hlp( m, B->p, d, u0 );
1909 mpi_mul_hlp( n, N->p, d, u1 );
1910
1911 *d++ = u0; d[n + 1] = 0;
1912 }
1913
Paul Bakker66d5d072014-06-17 16:39:18 +02001914 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001917 mpi_sub_hlp( n, N->p, A->p );
1918 else
1919 /* prevent timing attacks */
1920 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001921
1922 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001923}
1924
1925/*
1926 * Montgomery reduction: A = A * R^-1 mod N
1927 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001928static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1929 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001930{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 mbedtls_mpi_uint z = 1;
1932 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
Paul Bakker8ddb6452013-02-27 14:56:33 +01001934 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001935 U.p = &z;
1936
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001937 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001938}
1939
1940/*
1941 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1942 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001943int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1944 const mbedtls_mpi *E, const mbedtls_mpi *N,
1945 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001946{
Paul Bakker23986e52011-04-24 08:57:21 +00001947 int ret;
1948 size_t wbits, wsize, one = 1;
1949 size_t i, j, nblimbs;
1950 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 mbedtls_mpi_uint ei, mm, state;
1952 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001953 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001954
Hanno Becker73d7d792018-12-11 10:35:51 +00001955 MPI_VALIDATE_RET( X != NULL );
1956 MPI_VALIDATE_RET( A != NULL );
1957 MPI_VALIDATE_RET( E != NULL );
1958 MPI_VALIDATE_RET( N != NULL );
1959
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001960 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001962
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1964 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001965
1966 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001967 * Init temps and window size
1968 */
1969 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1971 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972 memset( W, 0, sizeof( W ) );
1973
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001974 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001975
1976 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1977 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1978
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001979#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1981 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001982#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001983
Paul Bakker5121ce52009-01-03 21:22:43 +00001984 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001985 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1986 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1987 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001988
1989 /*
Paul Bakker50546922012-05-19 08:40:49 +00001990 * Compensate for negative A (and correct at the end)
1991 */
1992 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001993 if( neg )
1994 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001996 Apos.s = 1;
1997 A = &Apos;
1998 }
1999
2000 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002001 * If 1st call, pre-compute R^2 mod N
2002 */
2003 if( _RR == NULL || _RR->p == NULL )
2004 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2006 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2007 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
2009 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002010 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002011 }
2012 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002013 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002014
2015 /*
2016 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2017 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2019 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002020 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002022
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002023 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002024
2025 /*
2026 * X = R^2 * R^-1 mod N = R mod N
2027 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002029 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002030
2031 if( wsize > 1 )
2032 {
2033 /*
2034 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2035 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002036 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2039 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002040
2041 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002042 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002043
Paul Bakker5121ce52009-01-03 21:22:43 +00002044 /*
2045 * W[i] = W[i - 1] * W[1]
2046 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002047 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002048 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2050 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002051
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002052 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002053 }
2054 }
2055
2056 nblimbs = E->n;
2057 bufsize = 0;
2058 nbits = 0;
2059 wbits = 0;
2060 state = 0;
2061
2062 while( 1 )
2063 {
2064 if( bufsize == 0 )
2065 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002066 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002067 break;
2068
Paul Bakker0d7702c2013-10-29 16:18:35 +01002069 nblimbs--;
2070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002071 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002072 }
2073
2074 bufsize--;
2075
2076 ei = (E->p[nblimbs] >> bufsize) & 1;
2077
2078 /*
2079 * skip leading 0s
2080 */
2081 if( ei == 0 && state == 0 )
2082 continue;
2083
2084 if( ei == 0 && state == 1 )
2085 {
2086 /*
2087 * out of window, square X
2088 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002089 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002090 continue;
2091 }
2092
2093 /*
2094 * add ei to current window
2095 */
2096 state = 2;
2097
2098 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002099 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002100
2101 if( nbits == wsize )
2102 {
2103 /*
2104 * X = X^wsize R^-1 mod N
2105 */
2106 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002107 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002108
2109 /*
2110 * X = X * W[wbits] R^-1 mod N
2111 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002112 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002113
2114 state--;
2115 nbits = 0;
2116 wbits = 0;
2117 }
2118 }
2119
2120 /*
2121 * process the remaining bits
2122 */
2123 for( i = 0; i < nbits; i++ )
2124 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002125 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126
2127 wbits <<= 1;
2128
Paul Bakker66d5d072014-06-17 16:39:18 +02002129 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002130 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002131 }
2132
2133 /*
2134 * X = A^E * R * R^-1 mod N = A^E mod N
2135 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002136 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002137
Hanno Beckera4af1c42017-04-18 09:07:45 +01002138 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002139 {
2140 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002142 }
2143
Paul Bakker5121ce52009-01-03 21:22:43 +00002144cleanup:
2145
Paul Bakker66d5d072014-06-17 16:39:18 +02002146 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002147 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002150
Paul Bakker75a28602014-03-31 12:08:17 +02002151 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002152 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002153
2154 return( ret );
2155}
2156
Paul Bakker5121ce52009-01-03 21:22:43 +00002157/*
2158 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2159 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002161{
Paul Bakker23986e52011-04-24 08:57:21 +00002162 int ret;
2163 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002164 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002165
Hanno Becker73d7d792018-12-11 10:35:51 +00002166 MPI_VALIDATE_RET( G != NULL );
2167 MPI_VALIDATE_RET( A != NULL );
2168 MPI_VALIDATE_RET( B != NULL );
2169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2173 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 lz = mbedtls_mpi_lsb( &TA );
2176 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002177
Paul Bakker66d5d072014-06-17 16:39:18 +02002178 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002179 lz = lzt;
2180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2182 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002183
Paul Bakker5121ce52009-01-03 21:22:43 +00002184 TA.s = TB.s = 1;
2185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002187 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2189 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002192 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2194 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002195 }
2196 else
2197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200 }
2201 }
2202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2204 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205
2206cleanup:
2207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002209
2210 return( ret );
2211}
2212
Paul Bakker33dc46b2014-04-30 16:11:39 +02002213/*
2214 * Fill X with size bytes of random.
2215 *
2216 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002217 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002218 * deterministic, eg for tests).
2219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002221 int (*f_rng)(void *, unsigned char *, size_t),
2222 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002223{
Paul Bakker23986e52011-04-24 08:57:21 +00002224 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002225 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002226 size_t const overhead = ( limbs * ciL ) - size;
2227 unsigned char *Xp;
2228
Hanno Becker8ce11a32018-12-19 16:18:52 +00002229 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002230 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002231
Hanno Beckerda1655a2017-10-18 14:21:44 +01002232 /* Ensure that target MPI has exactly the necessary number of limbs */
2233 if( X->n != limbs )
2234 {
2235 mbedtls_mpi_free( X );
2236 mbedtls_mpi_init( X );
2237 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2238 }
2239 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002240
Hanno Beckerda1655a2017-10-18 14:21:44 +01002241 Xp = (unsigned char*) X->p;
2242 f_rng( p_rng, Xp + overhead, size );
2243
Hanno Becker2be8a552018-10-25 12:40:09 +01002244 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002245
2246cleanup:
2247 return( ret );
2248}
2249
Paul Bakker5121ce52009-01-03 21:22:43 +00002250/*
2251 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002254{
2255 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002256 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002257 MPI_VALIDATE_RET( X != NULL );
2258 MPI_VALIDATE_RET( A != NULL );
2259 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002260
Hanno Becker4bcb4912017-04-18 15:49:39 +01002261 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2265 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2266 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002271 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002273 goto cleanup;
2274 }
2275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2277 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2278 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2279 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002281 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2282 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2283 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2284 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002285
2286 do
2287 {
2288 while( ( TU.p[0] & 1 ) == 0 )
2289 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
2292 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2293 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2295 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002296 }
2297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002298 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2299 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002300 }
2301
2302 while( ( TV.p[0] & 1 ) == 0 )
2303 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002305
2306 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2307 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2309 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310 }
2311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2313 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 }
2315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2319 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2320 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002321 }
2322 else
2323 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002324 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2325 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2326 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 }
2328 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002329 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2332 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2335 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002337 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
2339cleanup:
2340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2342 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2343 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002344
2345 return( ret );
2346}
2347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002349
Paul Bakker5121ce52009-01-03 21:22:43 +00002350static const int small_prime[] =
2351{
2352 3, 5, 7, 11, 13, 17, 19, 23,
2353 29, 31, 37, 41, 43, 47, 53, 59,
2354 61, 67, 71, 73, 79, 83, 89, 97,
2355 101, 103, 107, 109, 113, 127, 131, 137,
2356 139, 149, 151, 157, 163, 167, 173, 179,
2357 181, 191, 193, 197, 199, 211, 223, 227,
2358 229, 233, 239, 241, 251, 257, 263, 269,
2359 271, 277, 281, 283, 293, 307, 311, 313,
2360 317, 331, 337, 347, 349, 353, 359, 367,
2361 373, 379, 383, 389, 397, 401, 409, 419,
2362 421, 431, 433, 439, 443, 449, 457, 461,
2363 463, 467, 479, 487, 491, 499, 503, 509,
2364 521, 523, 541, 547, 557, 563, 569, 571,
2365 577, 587, 593, 599, 601, 607, 613, 617,
2366 619, 631, 641, 643, 647, 653, 659, 661,
2367 673, 677, 683, 691, 701, 709, 719, 727,
2368 733, 739, 743, 751, 757, 761, 769, 773,
2369 787, 797, 809, 811, 821, 823, 827, 829,
2370 839, 853, 857, 859, 863, 877, 881, 883,
2371 887, 907, 911, 919, 929, 937, 941, 947,
2372 953, 967, 971, 977, 983, 991, 997, -103
2373};
2374
2375/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002376 * Small divisors test (X must be positive)
2377 *
2378 * Return values:
2379 * 0: no small factor (possible prime, more tests needed)
2380 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002382 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002384static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002385{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002386 int ret = 0;
2387 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002389
Paul Bakker5121ce52009-01-03 21:22:43 +00002390 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002392
2393 for( i = 0; small_prime[i] > 0; i++ )
2394 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002396 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002397
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
2400 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402 }
2403
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002404cleanup:
2405 return( ret );
2406}
2407
2408/*
2409 * Miller-Rabin pseudo-primality test (HAC 4.24)
2410 */
Janos Follathda31fa12018-09-03 14:45:23 +01002411static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002412 int (*f_rng)(void *, unsigned char *, size_t),
2413 void *p_rng )
2414{
Pascal Junodb99183d2015-03-11 16:49:45 +01002415 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002416 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002417 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002418
Hanno Becker8ce11a32018-12-19 16:18:52 +00002419 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002420 MPI_VALIDATE_RET( f_rng != NULL );
2421
2422 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2423 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002425
Paul Bakker5121ce52009-01-03 21:22:43 +00002426 /*
2427 * W = |X| - 1
2428 * R = W >> lsb( W )
2429 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2431 s = mbedtls_mpi_lsb( &W );
2432 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2433 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002434
Janos Follathda31fa12018-09-03 14:45:23 +01002435 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002436 {
2437 /*
2438 * pick a random A, 1 < A < |X| - 1
2439 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002440 count = 0;
2441 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002442 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002443
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002444 j = mbedtls_mpi_bitlen( &A );
2445 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002446 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002447 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002448 }
2449
2450 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002451 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2452 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002453 }
2454
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002455 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2456 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002457
2458 /*
2459 * A = A^R mod |X|
2460 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002461 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002463 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2464 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002465 continue;
2466
2467 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002469 {
2470 /*
2471 * A = A * A mod |X|
2472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2474 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002476 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002477 break;
2478
2479 j++;
2480 }
2481
2482 /*
2483 * not prime if A != |X| - 1 or A == 1
2484 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2486 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002487 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002489 break;
2490 }
2491 }
2492
2493cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002494 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2495 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002497
2498 return( ret );
2499}
2500
2501/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002502 * Pseudo-primality test: small factors, then Miller-Rabin
2503 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002504int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2505 int (*f_rng)(void *, unsigned char *, size_t),
2506 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002507{
2508 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002509 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002510 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002511 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002512
2513 XX.s = 1;
2514 XX.n = X->n;
2515 XX.p = X->p;
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, 0 ) == 0 ||
2518 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2519 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002522 return( 0 );
2523
2524 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2525 {
2526 if( ret == 1 )
2527 return( 0 );
2528
2529 return( ret );
2530 }
2531
Janos Follathda31fa12018-09-03 14:45:23 +01002532 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002533}
2534
Janos Follatha0b67c22018-09-18 14:48:23 +01002535#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002536/*
2537 * Pseudo-primality test, error probability 2^-80
2538 */
2539int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2540 int (*f_rng)(void *, unsigned char *, size_t),
2541 void *p_rng )
2542{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002543 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002544 MPI_VALIDATE_RET( f_rng != NULL );
2545
Janos Follatha0b67c22018-09-18 14:48:23 +01002546 /*
2547 * In the past our key generation aimed for an error rate of at most
2548 * 2^-80. Since this function is deprecated, aim for the same certainty
2549 * here as well.
2550 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002551 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002552}
Janos Follatha0b67c22018-09-18 14:48:23 +01002553#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002554
2555/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002556 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002557 *
Janos Follathf301d232018-08-14 13:34:01 +01002558 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2559 * be either 1024 bits or 1536 bits long, and flags must contain
2560 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002561 */
Janos Follath7c025a92018-08-14 11:08:41 +01002562int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002563 int (*f_rng)(void *, unsigned char *, size_t),
2564 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002565{
Jethro Beekman66689272018-02-14 19:24:10 -08002566#ifdef MBEDTLS_HAVE_INT64
2567// ceil(2^63.5)
2568#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2569#else
2570// ceil(2^31.5)
2571#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2572#endif
2573 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002574 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002575 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002576 mbedtls_mpi_uint r;
2577 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002578
Hanno Becker8ce11a32018-12-19 16:18:52 +00002579 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002580 MPI_VALIDATE_RET( f_rng != NULL );
2581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2583 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002586
2587 n = BITS_TO_LIMBS( nbits );
2588
Janos Follathda31fa12018-09-03 14:45:23 +01002589 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2590 {
2591 /*
2592 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2593 */
2594 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2595 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2596 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2597 }
2598 else
2599 {
2600 /*
2601 * 2^-100 error probability, number of rounds computed based on HAC,
2602 * fact 4.48
2603 */
2604 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2605 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2606 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2607 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2608 }
2609
Jethro Beekman66689272018-02-14 19:24:10 -08002610 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002611 {
Jethro Beekman66689272018-02-14 19:24:10 -08002612 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2613 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2614 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2615
2616 k = n * biL;
2617 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2618 X->p[0] |= 1;
2619
Janos Follath7c025a92018-08-14 11:08:41 +01002620 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002621 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002622 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002623
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002625 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002626 }
Jethro Beekman66689272018-02-14 19:24:10 -08002627 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002628 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002629 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002630 * An necessary condition for Y and X = 2Y + 1 to be prime
2631 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2632 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002633 */
Jethro Beekman66689272018-02-14 19:24:10 -08002634
2635 X->p[0] |= 2;
2636
2637 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2638 if( r == 0 )
2639 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2640 else if( r == 1 )
2641 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2642
2643 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2644 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2645 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2646
2647 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002648 {
Jethro Beekman66689272018-02-14 19:24:10 -08002649 /*
2650 * First, check small factors for X and Y
2651 * before doing Miller-Rabin on any of them
2652 */
2653 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2654 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002655 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002656 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002657 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002658 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002659 goto cleanup;
2660
2661 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2662 goto cleanup;
2663
2664 /*
2665 * Next candidates. We want to preserve Y = (X-1) / 2 and
2666 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2667 * so up Y by 6 and X by 12.
2668 */
2669 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2670 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002671 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002672 }
2673 }
2674
2675cleanup:
2676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002678
2679 return( ret );
2680}
2681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002685
Paul Bakker23986e52011-04-24 08:57:21 +00002686#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002687
2688static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2689{
2690 { 693, 609, 21 },
2691 { 1764, 868, 28 },
2692 { 768454923, 542167814, 1 }
2693};
2694
Paul Bakker5121ce52009-01-03 21:22:43 +00002695/*
2696 * Checkup routine
2697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002699{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002700 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002701 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002703 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2704 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002705
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002706 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002707 "EFE021C2645FD1DC586E69184AF4A31E" \
2708 "D5F53E93B5F123FA41680867BA110131" \
2709 "944FE7952E2517337780CB0DB80E61AA" \
2710 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002712 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002713 "B2E7EFD37075B9F03FF989C7C5051C20" \
2714 "34D2A323810251127E7BF8625A4F49A5" \
2715 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2716 "5B5C25763222FEFCCFC38B832366C29E" ) );
2717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002718 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002719 "0066A198186C18C10B2F5ED9B522752A" \
2720 "9830B69916E535C8F047518A889A43A5" \
2721 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002723 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002726 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2727 "9E857EA95A03512E2BAE7391688D264A" \
2728 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2729 "8001B72E848A38CAE1C65F78E56ABDEF" \
2730 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2731 "ECF677152EF804370C1A305CAF3B5BF1" \
2732 "30879B56C61DE584A0F53A2447A51E" ) );
2733
2734 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002735 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002737 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002738 {
2739 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002740 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002741
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002742 ret = 1;
2743 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002744 }
2745
2746 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002749 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002751 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002752 "256567336059E52CAE22925474705F39A94" ) );
2753
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002755 "6613F26162223DF488E9CD48CC132C7A" \
2756 "0AC93C701B001B092E4E5B9F73BCD27B" \
2757 "9EE50D0657C77F374E903CDFA4C642" ) );
2758
2759 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002760 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002761
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002762 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2763 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002764 {
2765 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002766 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002767
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002768 ret = 1;
2769 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002770 }
2771
2772 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002773 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002774
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002775 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002776
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002777 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002778 "36E139AEA55215609D2816998ED020BB" \
2779 "BD96C37890F65171D948E9BC7CBAA4D9" \
2780 "325D24D6A3C12710F10A09FA08AB87" ) );
2781
2782 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002786 {
2787 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002788 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002789
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002790 ret = 1;
2791 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002792 }
2793
2794 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002797 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002799 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002800 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2801 "C3DBA76456363A10869622EAC2DD84EC" \
2802 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2803
2804 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002805 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002808 {
2809 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002810 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002811
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002812 ret = 1;
2813 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002814 }
2815
2816 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002818
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002819 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002820 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002821
Paul Bakker66d5d072014-06-17 16:39:18 +02002822 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002823 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002824 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2825 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002827 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002828
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002829 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002830 {
2831 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002832 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002833
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002834 ret = 1;
2835 goto cleanup;
2836 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002837 }
2838
2839 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002840 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002841
Paul Bakker5121ce52009-01-03 21:22:43 +00002842cleanup:
2843
2844 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002845 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002847 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2848 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002849
2850 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002851 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002852
2853 return( ret );
2854}
2855
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002856#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002858#endif /* MBEDTLS_BIGNUM_C */