blob: 2007662508aa44542b221404502073a89cd56466 [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 Becker23cfea02019-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 Follath80470622019-03-06 13:43:02 +0000593 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-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 Beckerc983c812019-02-01 16:41:30 +0000610 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 *p++ = '-';
Hanno Beckerc983c812019-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;
745 mbedtls_mpi_uint tmp = 0;
746 /* This works regardless of the endianness. */
747 for( i = 0; i < ciL; i++, x >>= 8 )
748 tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
749 return( tmp );
750}
751
752static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
753{
754#if defined(__BYTE_ORDER__)
755
756/* Nothing to do on bigendian systems. */
757#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
758 return( x );
759#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
760
761#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
762
763/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000764#if defined(__GNUC__) && defined(__GNUC_PREREQ)
765#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000766#define have_bswap
767#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000768#endif
769
770#if defined(__clang__) && defined(__has_builtin)
771#if __has_builtin(__builtin_bswap32) && \
772 __has_builtin(__builtin_bswap64)
773#define have_bswap
774#endif
775#endif
776
Hanno Beckerf8720072018-11-08 11:53:49 +0000777#if defined(have_bswap)
778 /* The compiler is hopefully able to statically evaluate this! */
779 switch( sizeof(mbedtls_mpi_uint) )
780 {
781 case 4:
782 return( __builtin_bswap32(x) );
783 case 8:
784 return( __builtin_bswap64(x) );
785 }
786#endif
787#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
788#endif /* __BYTE_ORDER__ */
789
790 /* Fall back to C-based reordering if we don't know the byte order
791 * or we couldn't use a compiler-specific builtin. */
792 return( mpi_uint_bigendian_to_host_c( x ) );
793}
794
Hanno Becker2be8a552018-10-25 12:40:09 +0100795static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100796{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100797 mbedtls_mpi_uint *cur_limb_left;
798 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100799 if( limbs == 0 )
800 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100801
802 /*
803 * Traverse limbs and
804 * - adapt byte-order in each limb
805 * - swap the limbs themselves.
806 * For that, simultaneously traverse the limbs from left to right
807 * and from right to left, as long as the left index is not bigger
808 * than the right index (it's not a problem if limbs is odd and the
809 * indices coincide in the last iteration).
810 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100811 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
812 cur_limb_left <= cur_limb_right;
813 cur_limb_left++, cur_limb_right-- )
814 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000815 mbedtls_mpi_uint tmp;
816 /* Note that if cur_limb_left == cur_limb_right,
817 * this code effectively swaps the bytes only once. */
818 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
819 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
820 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100821 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100822}
823
Paul Bakker5121ce52009-01-03 21:22:43 +0000824/*
Janos Follatha778a942019-02-13 10:28:28 +0000825 * Import X from unsigned binary data, little endian
826 */
827int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
828 const unsigned char *buf, size_t buflen )
829{
830 int ret;
831 size_t i;
832 size_t const limbs = CHARS_TO_LIMBS( buflen );
833
834 /* Ensure that target MPI has exactly the necessary number of limbs */
835 if( X->n != limbs )
836 {
837 mbedtls_mpi_free( X );
838 mbedtls_mpi_init( X );
839 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
840 }
841
842 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
843
844 for( i = 0; i < buflen; i++ )
845 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
846
847cleanup:
848
Janos Follath171a7ef2019-02-15 16:17:45 +0000849 /*
850 * This function is also used to import keys. However, wiping the buffers
851 * upon failure is not necessary because failure only can happen before any
852 * input is copied.
853 */
Janos Follatha778a942019-02-13 10:28:28 +0000854 return( ret );
855}
856
857/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000858 * Import X from unsigned binary data, big endian
859 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000861{
Paul Bakker23986e52011-04-24 08:57:21 +0000862 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100863 size_t const limbs = CHARS_TO_LIMBS( buflen );
864 size_t const overhead = ( limbs * ciL ) - buflen;
865 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000866
Hanno Becker8ce11a32018-12-19 16:18:52 +0000867 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000868 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
869
Hanno Becker073c1992017-10-17 15:17:27 +0100870 /* Ensure that target MPI has exactly the necessary number of limbs */
871 if( X->n != limbs )
872 {
873 mbedtls_mpi_free( X );
874 mbedtls_mpi_init( X );
875 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
876 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000878
Hanno Becker0e810b92019-01-03 17:13:11 +0000879 /* Avoid calling `memcpy` with NULL source argument,
880 * even if buflen is 0. */
881 if( buf != NULL )
882 {
883 Xp = (unsigned char*) X->p;
884 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100885
Hanno Becker0e810b92019-01-03 17:13:11 +0000886 mpi_bigendian_to_host( X->p, limbs );
887 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000888
889cleanup:
890
Janos Follath171a7ef2019-02-15 16:17:45 +0000891 /*
892 * This function is also used to import keys. However, wiping the buffers
893 * upon failure is not necessary because failure only can happen before any
894 * input is copied.
895 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000896 return( ret );
897}
898
899/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000900 * Export X into unsigned binary data, little endian
901 */
902int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
903 unsigned char *buf, size_t buflen )
904{
905 size_t stored_bytes = X->n * ciL;
906 size_t bytes_to_copy;
907 size_t i;
908
909 if( stored_bytes < buflen )
910 {
911 bytes_to_copy = stored_bytes;
912 }
913 else
914 {
915 bytes_to_copy = buflen;
916
917 /* The output buffer is smaller than the allocated size of X.
918 * However X may fit if its leading bytes are zero. */
919 for( i = bytes_to_copy; i < stored_bytes; i++ )
920 {
921 if( GET_BYTE( X, i ) != 0 )
922 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
923 }
924 }
925
926 for( i = 0; i < bytes_to_copy; i++ )
927 buf[i] = GET_BYTE( X, i );
928
929 if( stored_bytes < buflen )
930 {
931 /* Write trailing 0 bytes */
932 memset( buf + stored_bytes, 0, buflen - stored_bytes );
933 }
934
935 return( 0 );
936}
937
938/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 * Export X into unsigned binary data, big endian
940 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100941int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
942 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000943{
Hanno Becker73d7d792018-12-11 10:35:51 +0000944 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100945 size_t bytes_to_copy;
946 unsigned char *p;
947 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000948
Hanno Becker73d7d792018-12-11 10:35:51 +0000949 MPI_VALIDATE_RET( X != NULL );
950 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
951
952 stored_bytes = X->n * ciL;
953
Gilles Peskine11cdb052018-11-20 16:47:47 +0100954 if( stored_bytes < buflen )
955 {
956 /* There is enough space in the output buffer. Write initial
957 * null bytes and record the position at which to start
958 * writing the significant bytes. In this case, the execution
959 * trace of this function does not depend on the value of the
960 * number. */
961 bytes_to_copy = stored_bytes;
962 p = buf + buflen - stored_bytes;
963 memset( buf, 0, buflen - stored_bytes );
964 }
965 else
966 {
967 /* The output buffer is smaller than the allocated size of X.
968 * However X may fit if its leading bytes are zero. */
969 bytes_to_copy = buflen;
970 p = buf;
971 for( i = bytes_to_copy; i < stored_bytes; i++ )
972 {
973 if( GET_BYTE( X, i ) != 0 )
974 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
975 }
976 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000977
Gilles Peskine11cdb052018-11-20 16:47:47 +0100978 for( i = 0; i < bytes_to_copy; i++ )
979 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000980
981 return( 0 );
982}
983
984/*
985 * Left-shift: X <<= count
986 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000988{
Paul Bakker23986e52011-04-24 08:57:21 +0000989 int ret;
990 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000992 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000993
994 v0 = count / (biL );
995 t1 = count & (biL - 1);
996
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200997 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000998
Paul Bakkerf9688572011-05-05 10:00:45 +0000999 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001000 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001001
1002 ret = 0;
1003
1004 /*
1005 * shift by count / limb_size
1006 */
1007 if( v0 > 0 )
1008 {
Paul Bakker23986e52011-04-24 08:57:21 +00001009 for( i = X->n; i > v0; i-- )
1010 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001011
Paul Bakker23986e52011-04-24 08:57:21 +00001012 for( ; i > 0; i-- )
1013 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001014 }
1015
1016 /*
1017 * shift by count % limb_size
1018 */
1019 if( t1 > 0 )
1020 {
1021 for( i = v0; i < X->n; i++ )
1022 {
1023 r1 = X->p[i] >> (biL - t1);
1024 X->p[i] <<= t1;
1025 X->p[i] |= r0;
1026 r0 = r1;
1027 }
1028 }
1029
1030cleanup:
1031
1032 return( ret );
1033}
1034
1035/*
1036 * Right-shift: X >>= count
1037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001039{
Paul Bakker23986e52011-04-24 08:57:21 +00001040 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001042 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001043
1044 v0 = count / biL;
1045 v1 = count & (biL - 1);
1046
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001047 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001049
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 /*
1051 * shift by count / limb_size
1052 */
1053 if( v0 > 0 )
1054 {
1055 for( i = 0; i < X->n - v0; i++ )
1056 X->p[i] = X->p[i + v0];
1057
1058 for( ; i < X->n; i++ )
1059 X->p[i] = 0;
1060 }
1061
1062 /*
1063 * shift by count % limb_size
1064 */
1065 if( v1 > 0 )
1066 {
Paul Bakker23986e52011-04-24 08:57:21 +00001067 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001068 {
Paul Bakker23986e52011-04-24 08:57:21 +00001069 r1 = X->p[i - 1] << (biL - v1);
1070 X->p[i - 1] >>= v1;
1071 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001072 r0 = r1;
1073 }
1074 }
1075
1076 return( 0 );
1077}
1078
1079/*
1080 * Compare unsigned values
1081 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001083{
Paul Bakker23986e52011-04-24 08:57:21 +00001084 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001085 MPI_VALIDATE_RET( X != NULL );
1086 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001087
Paul Bakker23986e52011-04-24 08:57:21 +00001088 for( i = X->n; i > 0; i-- )
1089 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001090 break;
1091
Paul Bakker23986e52011-04-24 08:57:21 +00001092 for( j = Y->n; j > 0; j-- )
1093 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001094 break;
1095
Paul Bakker23986e52011-04-24 08:57:21 +00001096 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001097 return( 0 );
1098
1099 if( i > j ) return( 1 );
1100 if( j > i ) return( -1 );
1101
Paul Bakker23986e52011-04-24 08:57:21 +00001102 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001103 {
Paul Bakker23986e52011-04-24 08:57:21 +00001104 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1105 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001106 }
1107
1108 return( 0 );
1109}
1110
1111/*
1112 * Compare signed values
1113 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001115{
Paul Bakker23986e52011-04-24 08:57:21 +00001116 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001117 MPI_VALIDATE_RET( X != NULL );
1118 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001119
Paul Bakker23986e52011-04-24 08:57:21 +00001120 for( i = X->n; i > 0; i-- )
1121 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001122 break;
1123
Paul Bakker23986e52011-04-24 08:57:21 +00001124 for( j = Y->n; j > 0; j-- )
1125 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001126 break;
1127
Paul Bakker23986e52011-04-24 08:57:21 +00001128 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001129 return( 0 );
1130
1131 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001132 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133
1134 if( X->s > 0 && Y->s < 0 ) return( 1 );
1135 if( Y->s > 0 && X->s < 0 ) return( -1 );
1136
Paul Bakker23986e52011-04-24 08:57:21 +00001137 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001138 {
Paul Bakker23986e52011-04-24 08:57:21 +00001139 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1140 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001141 }
1142
1143 return( 0 );
1144}
1145
1146/*
1147 * Compare signed values
1148 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001150{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 mbedtls_mpi Y;
1152 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001153 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001154
1155 *p = ( z < 0 ) ? -z : z;
1156 Y.s = ( z < 0 ) ? -1 : 1;
1157 Y.n = 1;
1158 Y.p = p;
1159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001161}
1162
1163/*
1164 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1165 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001167{
Paul Bakker23986e52011-04-24 08:57:21 +00001168 int ret;
1169 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001170 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001171 MPI_VALIDATE_RET( X != NULL );
1172 MPI_VALIDATE_RET( A != NULL );
1173 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001174
1175 if( X == B )
1176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001177 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001178 }
1179
1180 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001182
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001183 /*
1184 * X should always be positive as a result of unsigned additions.
1185 */
1186 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001187
Paul Bakker23986e52011-04-24 08:57:21 +00001188 for( j = B->n; j > 0; j-- )
1189 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001190 break;
1191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001193
1194 o = B->p; p = X->p; c = 0;
1195
Janos Follath6c922682015-10-30 17:43:11 +01001196 /*
1197 * tmp is used because it might happen that p == o
1198 */
Paul Bakker23986e52011-04-24 08:57:21 +00001199 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001200 {
Janos Follath6c922682015-10-30 17:43:11 +01001201 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001202 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001203 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204 }
1205
1206 while( c != 0 )
1207 {
1208 if( i >= X->n )
1209 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001211 p = X->p + i;
1212 }
1213
Paul Bakker2d319fd2012-09-16 21:34:26 +00001214 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001215 }
1216
1217cleanup:
1218
1219 return( ret );
1220}
1221
1222/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001224 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001225static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001226{
Paul Bakker23986e52011-04-24 08:57:21 +00001227 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001228 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001229
1230 for( i = c = 0; i < n; i++, s++, d++ )
1231 {
1232 z = ( *d < c ); *d -= c;
1233 c = ( *d < *s ) + z; *d -= *s;
1234 }
1235
1236 while( c != 0 )
1237 {
1238 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001239 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001240 }
1241}
1242
1243/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001244 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001245 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001247{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001249 int ret;
1250 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001251 MPI_VALIDATE_RET( X != NULL );
1252 MPI_VALIDATE_RET( A != NULL );
1253 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001254
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1256 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001259
1260 if( X == B )
1261 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001263 B = &TB;
1264 }
1265
1266 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001268
Paul Bakker1ef7a532009-06-20 10:50:55 +00001269 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001270 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001271 */
1272 X->s = 1;
1273
Paul Bakker5121ce52009-01-03 21:22:43 +00001274 ret = 0;
1275
Paul Bakker23986e52011-04-24 08:57:21 +00001276 for( n = B->n; n > 0; n-- )
1277 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001278 break;
1279
Paul Bakker23986e52011-04-24 08:57:21 +00001280 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001281
1282cleanup:
1283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001285
1286 return( ret );
1287}
1288
1289/*
1290 * Signed addition: X = A + B
1291 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001293{
Hanno Becker73d7d792018-12-11 10:35:51 +00001294 int ret, s;
1295 MPI_VALIDATE_RET( X != NULL );
1296 MPI_VALIDATE_RET( A != NULL );
1297 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001298
Hanno Becker73d7d792018-12-11 10:35:51 +00001299 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001300 if( A->s * B->s < 0 )
1301 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001302 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001303 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001304 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001305 X->s = s;
1306 }
1307 else
1308 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001309 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001310 X->s = -s;
1311 }
1312 }
1313 else
1314 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001316 X->s = s;
1317 }
1318
1319cleanup:
1320
1321 return( ret );
1322}
1323
1324/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001325 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001328{
Hanno Becker73d7d792018-12-11 10:35:51 +00001329 int ret, s;
1330 MPI_VALIDATE_RET( X != NULL );
1331 MPI_VALIDATE_RET( A != NULL );
1332 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001333
Hanno Becker73d7d792018-12-11 10:35:51 +00001334 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001335 if( A->s * B->s > 0 )
1336 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001338 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 X->s = s;
1341 }
1342 else
1343 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345 X->s = -s;
1346 }
1347 }
1348 else
1349 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001351 X->s = s;
1352 }
1353
1354cleanup:
1355
1356 return( ret );
1357}
1358
1359/*
1360 * Signed addition: X = A + b
1361 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001363{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364 mbedtls_mpi _B;
1365 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001366 MPI_VALIDATE_RET( X != NULL );
1367 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001368
1369 p[0] = ( b < 0 ) ? -b : b;
1370 _B.s = ( b < 0 ) ? -1 : 1;
1371 _B.n = 1;
1372 _B.p = p;
1373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001375}
1376
1377/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001378 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001381{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 mbedtls_mpi _B;
1383 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001384 MPI_VALIDATE_RET( X != NULL );
1385 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001386
1387 p[0] = ( b < 0 ) ? -b : b;
1388 _B.s = ( b < 0 ) ? -1 : 1;
1389 _B.n = 1;
1390 _B.p = p;
1391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001393}
1394
1395/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001397 */
1398static
1399#if defined(__APPLE__) && defined(__arm__)
1400/*
1401 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1402 * appears to need this to prevent bad ARM code generation at -O3.
1403 */
1404__attribute__ ((noinline))
1405#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406void 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 +00001407{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001409
1410#if defined(MULADDC_HUIT)
1411 for( ; i >= 8; i -= 8 )
1412 {
1413 MULADDC_INIT
1414 MULADDC_HUIT
1415 MULADDC_STOP
1416 }
1417
1418 for( ; i > 0; i-- )
1419 {
1420 MULADDC_INIT
1421 MULADDC_CORE
1422 MULADDC_STOP
1423 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001424#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001425 for( ; i >= 16; i -= 16 )
1426 {
1427 MULADDC_INIT
1428 MULADDC_CORE MULADDC_CORE
1429 MULADDC_CORE MULADDC_CORE
1430 MULADDC_CORE MULADDC_CORE
1431 MULADDC_CORE MULADDC_CORE
1432
1433 MULADDC_CORE MULADDC_CORE
1434 MULADDC_CORE MULADDC_CORE
1435 MULADDC_CORE MULADDC_CORE
1436 MULADDC_CORE MULADDC_CORE
1437 MULADDC_STOP
1438 }
1439
1440 for( ; i >= 8; i -= 8 )
1441 {
1442 MULADDC_INIT
1443 MULADDC_CORE MULADDC_CORE
1444 MULADDC_CORE MULADDC_CORE
1445
1446 MULADDC_CORE MULADDC_CORE
1447 MULADDC_CORE MULADDC_CORE
1448 MULADDC_STOP
1449 }
1450
1451 for( ; i > 0; i-- )
1452 {
1453 MULADDC_INIT
1454 MULADDC_CORE
1455 MULADDC_STOP
1456 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001457#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001458
1459 t++;
1460
1461 do {
1462 *d += c; c = ( *d < c ); d++;
1463 }
1464 while( c != 0 );
1465}
1466
1467/*
1468 * Baseline multiplication: X = A * B (HAC 14.12)
1469 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001470int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001471{
Paul Bakker23986e52011-04-24 08:57:21 +00001472 int ret;
1473 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001475 MPI_VALIDATE_RET( X != NULL );
1476 MPI_VALIDATE_RET( A != NULL );
1477 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001479 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1482 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001483
Paul Bakker23986e52011-04-24 08:57:21 +00001484 for( i = A->n; i > 0; i-- )
1485 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001486 break;
1487
Paul Bakker23986e52011-04-24 08:57:21 +00001488 for( j = B->n; j > 0; j-- )
1489 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001490 break;
1491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1493 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001494
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001495 for( ; j > 0; j-- )
1496 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001497
1498 X->s = A->s * B->s;
1499
1500cleanup:
1501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001503
1504 return( ret );
1505}
1506
1507/*
1508 * Baseline multiplication: X = A * b
1509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001511{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 mbedtls_mpi _B;
1513 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001514 MPI_VALIDATE_RET( X != NULL );
1515 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001516
1517 _B.s = 1;
1518 _B.n = 1;
1519 _B.p = p;
1520 p[0] = b;
1521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001523}
1524
1525/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001526 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1527 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001528 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001529static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1530 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001531{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001532#if defined(MBEDTLS_HAVE_UDBL)
1533 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001534#else
Simon Butcher9803d072016-01-03 00:24:34 +00001535 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1536 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001537 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1538 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001539 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001540#endif
1541
Simon Butcher15b15d12015-11-26 19:35:03 +00001542 /*
1543 * Check for overflow
1544 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001545 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001546 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001547 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001548
Simon Butcherf5ba0452015-12-27 23:01:55 +00001549 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001550 }
1551
1552#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001553 dividend = (mbedtls_t_udbl) u1 << biL;
1554 dividend |= (mbedtls_t_udbl) u0;
1555 quotient = dividend / d;
1556 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1557 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1558
1559 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001560 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001561
1562 return (mbedtls_mpi_uint) quotient;
1563#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001564
1565 /*
1566 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1567 * Vol. 2 - Seminumerical Algorithms, Knuth
1568 */
1569
1570 /*
1571 * Normalize the divisor, d, and dividend, u0, u1
1572 */
1573 s = mbedtls_clz( d );
1574 d = d << s;
1575
1576 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001577 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001578 u0 = u0 << s;
1579
1580 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001581 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001582
1583 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001584 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001585
1586 /*
1587 * Find the first quotient and remainder
1588 */
1589 q1 = u1 / d1;
1590 r0 = u1 - d1 * q1;
1591
1592 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1593 {
1594 q1 -= 1;
1595 r0 += d1;
1596
1597 if ( r0 >= radix ) break;
1598 }
1599
Simon Butcherf5ba0452015-12-27 23:01:55 +00001600 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001601 q0 = rAX / d1;
1602 r0 = rAX - q0 * d1;
1603
1604 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1605 {
1606 q0 -= 1;
1607 r0 += d1;
1608
1609 if ( r0 >= radix ) break;
1610 }
1611
1612 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001613 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001614
1615 quotient = q1 * radix + q0;
1616
1617 return quotient;
1618#endif
1619}
1620
1621/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001623 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001624int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1625 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001626{
Paul Bakker23986e52011-04-24 08:57:21 +00001627 int ret;
1628 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001630 MPI_VALIDATE_RET( A != NULL );
1631 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001632
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1634 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1637 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1642 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001643 return( 0 );
1644 }
1645
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001646 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1647 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001648 X.s = Y.s = 1;
1649
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001650 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1651 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1652 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1653 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001655 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001656 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001657 {
1658 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1660 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 }
1662 else k = 0;
1663
1664 n = X.n - 1;
1665 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001669 {
1670 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001674
1675 for( i = n; i > t ; i-- )
1676 {
1677 if( X.p[i] >= Y.p[t] )
1678 Z.p[i - t - 1] = ~0;
1679 else
1680 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001681 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1682 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001683 }
1684
1685 Z.p[i - t - 1]++;
1686 do
1687 {
1688 Z.p[i - t - 1]--;
1689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001691 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001692 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001694
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001695 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001696 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1697 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 T2.p[2] = X.p[i];
1699 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1703 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1704 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001705
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001706 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001707 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1709 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1710 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001711 Z.p[i - t - 1]--;
1712 }
1713 }
1714
1715 if( Q != NULL )
1716 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001718 Q->s = A->s * B->s;
1719 }
1720
1721 if( R != NULL )
1722 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001724 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001728 R->s = 1;
1729 }
1730
1731cleanup:
1732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1734 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001735
1736 return( ret );
1737}
1738
1739/*
1740 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001741 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001742int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1743 const mbedtls_mpi *A,
1744 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001745{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001746 mbedtls_mpi _B;
1747 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001748 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001749
1750 p[0] = ( b < 0 ) ? -b : b;
1751 _B.s = ( b < 0 ) ? -1 : 1;
1752 _B.n = 1;
1753 _B.p = p;
1754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001756}
1757
1758/*
1759 * Modulo: R = A mod B
1760 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001762{
1763 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001764 MPI_VALIDATE_RET( R != NULL );
1765 MPI_VALIDATE_RET( A != NULL );
1766 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1769 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001770
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001771 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001772
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001773 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1774 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001775
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1777 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
1779cleanup:
1780
1781 return( ret );
1782}
1783
1784/*
1785 * Modulo: r = A mod b
1786 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001788{
Paul Bakker23986e52011-04-24 08:57:21 +00001789 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001791 MPI_VALIDATE_RET( r != NULL );
1792 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001793
1794 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
1797 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001798 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001799
1800 /*
1801 * handle trivial cases
1802 */
1803 if( b == 1 )
1804 {
1805 *r = 0;
1806 return( 0 );
1807 }
1808
1809 if( b == 2 )
1810 {
1811 *r = A->p[0] & 1;
1812 return( 0 );
1813 }
1814
1815 /*
1816 * general case
1817 */
Paul Bakker23986e52011-04-24 08:57:21 +00001818 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001819 {
Paul Bakker23986e52011-04-24 08:57:21 +00001820 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001821 y = ( y << biH ) | ( x >> biH );
1822 z = y / b;
1823 y -= z * b;
1824
1825 x <<= biH;
1826 y = ( y << biH ) | ( x >> biH );
1827 z = y / b;
1828 y -= z * b;
1829 }
1830
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001831 /*
1832 * If A is negative, then the current y represents a negative value.
1833 * Flipping it to the positive side.
1834 */
1835 if( A->s < 0 && y != 0 )
1836 y = b - y;
1837
Paul Bakker5121ce52009-01-03 21:22:43 +00001838 *r = y;
1839
1840 return( 0 );
1841}
1842
1843/*
1844 * Fast Montgomery initialization (thanks to Tom St Denis)
1845 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001846static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001847{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001848 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001849 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001850
1851 x = m0;
1852 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001853
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001854 for( i = biL; i >= 8; i /= 2 )
1855 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001856
1857 *mm = ~x + 1;
1858}
1859
1860/*
1861 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1862 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001863static 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 +02001864 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001865{
Paul Bakker23986e52011-04-24 08:57:21 +00001866 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001868
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001869 if( T->n < N->n + 1 || T->p == NULL )
1870 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1871
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 memset( T->p, 0, T->n * ciL );
1873
1874 d = T->p;
1875 n = N->n;
1876 m = ( B->n < n ) ? B->n : n;
1877
1878 for( i = 0; i < n; i++ )
1879 {
1880 /*
1881 * T = (T + u0*B + u1*N) / 2^biL
1882 */
1883 u0 = A->p[i];
1884 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1885
1886 mpi_mul_hlp( m, B->p, d, u0 );
1887 mpi_mul_hlp( n, N->p, d, u1 );
1888
1889 *d++ = u0; d[n + 1] = 0;
1890 }
1891
Paul Bakker66d5d072014-06-17 16:39:18 +02001892 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001895 mpi_sub_hlp( n, N->p, A->p );
1896 else
1897 /* prevent timing attacks */
1898 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001899
1900 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001901}
1902
1903/*
1904 * Montgomery reduction: A = A * R^-1 mod N
1905 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001906static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1907 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001908{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 mbedtls_mpi_uint z = 1;
1910 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001911
Paul Bakker8ddb6452013-02-27 14:56:33 +01001912 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001913 U.p = &z;
1914
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001915 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001916}
1917
1918/*
1919 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1920 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001921int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1922 const mbedtls_mpi *E, const mbedtls_mpi *N,
1923 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001924{
Paul Bakker23986e52011-04-24 08:57:21 +00001925 int ret;
1926 size_t wbits, wsize, one = 1;
1927 size_t i, j, nblimbs;
1928 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 mbedtls_mpi_uint ei, mm, state;
1930 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001931 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
Hanno Becker73d7d792018-12-11 10:35:51 +00001933 MPI_VALIDATE_RET( X != NULL );
1934 MPI_VALIDATE_RET( A != NULL );
1935 MPI_VALIDATE_RET( E != NULL );
1936 MPI_VALIDATE_RET( N != NULL );
1937
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001938 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001939 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1942 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001943
1944 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001945 * Init temps and window size
1946 */
1947 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1949 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001950 memset( W, 0, sizeof( W ) );
1951
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001952 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001953
1954 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1955 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1956
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001957#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1959 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001960#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001961
Paul Bakker5121ce52009-01-03 21:22:43 +00001962 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1964 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1965 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001966
1967 /*
Paul Bakker50546922012-05-19 08:40:49 +00001968 * Compensate for negative A (and correct at the end)
1969 */
1970 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001971 if( neg )
1972 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001974 Apos.s = 1;
1975 A = &Apos;
1976 }
1977
1978 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001979 * If 1st call, pre-compute R^2 mod N
1980 */
1981 if( _RR == NULL || _RR->p == NULL )
1982 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1984 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1985 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001986
1987 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001989 }
1990 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001991 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
1993 /*
1994 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1995 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1997 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001998 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001999 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002000
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002001 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002002
2003 /*
2004 * X = R^2 * R^-1 mod N = R mod N
2005 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002007 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
2009 if( wsize > 1 )
2010 {
2011 /*
2012 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2013 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002014 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2017 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
2019 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002020 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002021
Paul Bakker5121ce52009-01-03 21:22:43 +00002022 /*
2023 * W[i] = W[i - 1] * W[1]
2024 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002025 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002026 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2028 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002029
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002030 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031 }
2032 }
2033
2034 nblimbs = E->n;
2035 bufsize = 0;
2036 nbits = 0;
2037 wbits = 0;
2038 state = 0;
2039
2040 while( 1 )
2041 {
2042 if( bufsize == 0 )
2043 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002044 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002045 break;
2046
Paul Bakker0d7702c2013-10-29 16:18:35 +01002047 nblimbs--;
2048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002050 }
2051
2052 bufsize--;
2053
2054 ei = (E->p[nblimbs] >> bufsize) & 1;
2055
2056 /*
2057 * skip leading 0s
2058 */
2059 if( ei == 0 && state == 0 )
2060 continue;
2061
2062 if( ei == 0 && state == 1 )
2063 {
2064 /*
2065 * out of window, square X
2066 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002067 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002068 continue;
2069 }
2070
2071 /*
2072 * add ei to current window
2073 */
2074 state = 2;
2075
2076 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002077 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
2079 if( nbits == wsize )
2080 {
2081 /*
2082 * X = X^wsize R^-1 mod N
2083 */
2084 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002085 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
2087 /*
2088 * X = X * W[wbits] R^-1 mod N
2089 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002090 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002091
2092 state--;
2093 nbits = 0;
2094 wbits = 0;
2095 }
2096 }
2097
2098 /*
2099 * process the remaining bits
2100 */
2101 for( i = 0; i < nbits; i++ )
2102 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002103 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002104
2105 wbits <<= 1;
2106
Paul Bakker66d5d072014-06-17 16:39:18 +02002107 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002108 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002109 }
2110
2111 /*
2112 * X = A^E * R * R^-1 mod N = A^E mod N
2113 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002114 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002115
Hanno Beckera4af1c42017-04-18 09:07:45 +01002116 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002117 {
2118 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002119 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002120 }
2121
Paul Bakker5121ce52009-01-03 21:22:43 +00002122cleanup:
2123
Paul Bakker66d5d072014-06-17 16:39:18 +02002124 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002127 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002128
Paul Bakker75a28602014-03-31 12:08:17 +02002129 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002131
2132 return( ret );
2133}
2134
Paul Bakker5121ce52009-01-03 21:22:43 +00002135/*
2136 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2137 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002139{
Paul Bakker23986e52011-04-24 08:57:21 +00002140 int ret;
2141 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002142 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002143
Hanno Becker73d7d792018-12-11 10:35:51 +00002144 MPI_VALIDATE_RET( G != NULL );
2145 MPI_VALIDATE_RET( A != NULL );
2146 MPI_VALIDATE_RET( B != NULL );
2147
Alexander Ke8ad49f2019-08-16 16:16:07 +03002148 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002150 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2151 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002153 lz = mbedtls_mpi_lsb( &TA );
2154 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002155
Paul Bakker66d5d072014-06-17 16:39:18 +02002156 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002157 lz = lzt;
2158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2160 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002161
Paul Bakker5121ce52009-01-03 21:22:43 +00002162 TA.s = TB.s = 1;
2163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002164 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2167 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002170 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2172 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002173 }
2174 else
2175 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2177 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002178 }
2179 }
2180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2182 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002183
2184cleanup:
2185
Alexander Ke8ad49f2019-08-16 16:16:07 +03002186 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002187
2188 return( ret );
2189}
2190
Paul Bakker33dc46b2014-04-30 16:11:39 +02002191/*
2192 * Fill X with size bytes of random.
2193 *
2194 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002195 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002196 * deterministic, eg for tests).
2197 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002199 int (*f_rng)(void *, unsigned char *, size_t),
2200 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002201{
Paul Bakker23986e52011-04-24 08:57:21 +00002202 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002203 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002204 size_t const overhead = ( limbs * ciL ) - size;
2205 unsigned char *Xp;
2206
Hanno Becker8ce11a32018-12-19 16:18:52 +00002207 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002208 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002209
Hanno Beckerda1655a2017-10-18 14:21:44 +01002210 /* Ensure that target MPI has exactly the necessary number of limbs */
2211 if( X->n != limbs )
2212 {
2213 mbedtls_mpi_free( X );
2214 mbedtls_mpi_init( X );
2215 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2216 }
2217 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002218
Hanno Beckerda1655a2017-10-18 14:21:44 +01002219 Xp = (unsigned char*) X->p;
2220 f_rng( p_rng, Xp + overhead, size );
2221
Hanno Becker2be8a552018-10-25 12:40:09 +01002222 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002223
2224cleanup:
2225 return( ret );
2226}
2227
Paul Bakker5121ce52009-01-03 21:22:43 +00002228/*
2229 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2230 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002232{
2233 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002235 MPI_VALIDATE_RET( X != NULL );
2236 MPI_VALIDATE_RET( A != NULL );
2237 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002238
Hanno Becker4bcb4912017-04-18 15:49:39 +01002239 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2243 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2244 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002249 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002250 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002251 goto cleanup;
2252 }
2253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2255 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2256 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2257 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2260 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2261 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2262 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002263
2264 do
2265 {
2266 while( ( TU.p[0] & 1 ) == 0 )
2267 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002268 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002269
2270 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2271 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2273 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274 }
2275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2277 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 }
2279
2280 while( ( TV.p[0] & 1 ) == 0 )
2281 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002283
2284 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2285 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2287 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002288 }
2289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002290 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2291 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292 }
2293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002295 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002296 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2297 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2298 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002299 }
2300 else
2301 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2303 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2304 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 }
2306 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2310 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002312 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2313 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002315 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002316
2317cleanup:
2318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2320 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2321 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002322
2323 return( ret );
2324}
2325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002327
Paul Bakker5121ce52009-01-03 21:22:43 +00002328static const int small_prime[] =
2329{
2330 3, 5, 7, 11, 13, 17, 19, 23,
2331 29, 31, 37, 41, 43, 47, 53, 59,
2332 61, 67, 71, 73, 79, 83, 89, 97,
2333 101, 103, 107, 109, 113, 127, 131, 137,
2334 139, 149, 151, 157, 163, 167, 173, 179,
2335 181, 191, 193, 197, 199, 211, 223, 227,
2336 229, 233, 239, 241, 251, 257, 263, 269,
2337 271, 277, 281, 283, 293, 307, 311, 313,
2338 317, 331, 337, 347, 349, 353, 359, 367,
2339 373, 379, 383, 389, 397, 401, 409, 419,
2340 421, 431, 433, 439, 443, 449, 457, 461,
2341 463, 467, 479, 487, 491, 499, 503, 509,
2342 521, 523, 541, 547, 557, 563, 569, 571,
2343 577, 587, 593, 599, 601, 607, 613, 617,
2344 619, 631, 641, 643, 647, 653, 659, 661,
2345 673, 677, 683, 691, 701, 709, 719, 727,
2346 733, 739, 743, 751, 757, 761, 769, 773,
2347 787, 797, 809, 811, 821, 823, 827, 829,
2348 839, 853, 857, 859, 863, 877, 881, 883,
2349 887, 907, 911, 919, 929, 937, 941, 947,
2350 953, 967, 971, 977, 983, 991, 997, -103
2351};
2352
2353/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002354 * Small divisors test (X must be positive)
2355 *
2356 * Return values:
2357 * 0: no small factor (possible prime, more tests needed)
2358 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002360 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002361 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002363{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002364 int ret = 0;
2365 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
Paul Bakker5121ce52009-01-03 21:22:43 +00002368 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002370
2371 for( i = 0; small_prime[i] > 0; i++ )
2372 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002374 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002377
2378 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002380 }
2381
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002382cleanup:
2383 return( ret );
2384}
2385
2386/*
2387 * Miller-Rabin pseudo-primality test (HAC 4.24)
2388 */
Janos Follathda31fa12018-09-03 14:45:23 +01002389static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002390 int (*f_rng)(void *, unsigned char *, size_t),
2391 void *p_rng )
2392{
Pascal Junodb99183d2015-03-11 16:49:45 +01002393 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002394 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002396
Hanno Becker8ce11a32018-12-19 16:18:52 +00002397 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002398 MPI_VALIDATE_RET( f_rng != NULL );
2399
2400 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2401 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002403
Paul Bakker5121ce52009-01-03 21:22:43 +00002404 /*
2405 * W = |X| - 1
2406 * R = W >> lsb( W )
2407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2409 s = mbedtls_mpi_lsb( &W );
2410 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2411 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002412
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002413 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002414
Janos Follathda31fa12018-09-03 14:45:23 +01002415 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002416 {
2417 /*
2418 * pick a random A, 1 < A < |X| - 1
2419 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002420 count = 0;
2421 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002422 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002423
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002424 j = mbedtls_mpi_bitlen( &A );
2425 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002426 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002427 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002428 }
2429
2430 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002431 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002432 }
2433
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002434 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2435 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002436
2437 /*
2438 * A = A^R mod |X|
2439 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2443 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002444 continue;
2445
2446 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002447 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002448 {
2449 /*
2450 * A = A * A mod |X|
2451 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2453 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002456 break;
2457
2458 j++;
2459 }
2460
2461 /*
2462 * not prime if A != |X| - 1 or A == 1
2463 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002464 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2465 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002466 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002467 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002468 break;
2469 }
2470 }
2471
2472cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002473 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2474 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002476
2477 return( ret );
2478}
2479
2480/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002481 * Pseudo-primality test: small factors, then Miller-Rabin
2482 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002483int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2484 int (*f_rng)(void *, unsigned char *, size_t),
2485 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002486{
2487 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002489 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002490 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002491
2492 XX.s = 1;
2493 XX.n = X->n;
2494 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2497 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2498 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002501 return( 0 );
2502
2503 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2504 {
2505 if( ret == 1 )
2506 return( 0 );
2507
2508 return( ret );
2509 }
2510
Janos Follathda31fa12018-09-03 14:45:23 +01002511 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002512}
2513
Janos Follatha0b67c22018-09-18 14:48:23 +01002514#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002515/*
2516 * Pseudo-primality test, error probability 2^-80
2517 */
2518int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2519 int (*f_rng)(void *, unsigned char *, size_t),
2520 void *p_rng )
2521{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002522 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002523 MPI_VALIDATE_RET( f_rng != NULL );
2524
Janos Follatha0b67c22018-09-18 14:48:23 +01002525 /*
2526 * In the past our key generation aimed for an error rate of at most
2527 * 2^-80. Since this function is deprecated, aim for the same certainty
2528 * here as well.
2529 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002530 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002531}
Janos Follatha0b67c22018-09-18 14:48:23 +01002532#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002533
2534/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002535 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002536 *
Janos Follathf301d232018-08-14 13:34:01 +01002537 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2538 * be either 1024 bits or 1536 bits long, and flags must contain
2539 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002540 */
Janos Follath7c025a92018-08-14 11:08:41 +01002541int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002542 int (*f_rng)(void *, unsigned char *, size_t),
2543 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002544{
Jethro Beekman66689272018-02-14 19:24:10 -08002545#ifdef MBEDTLS_HAVE_INT64
2546// ceil(2^63.5)
2547#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2548#else
2549// ceil(2^31.5)
2550#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2551#endif
2552 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002553 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002554 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002555 mbedtls_mpi_uint r;
2556 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002557
Hanno Becker8ce11a32018-12-19 16:18:52 +00002558 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002559 MPI_VALIDATE_RET( f_rng != NULL );
2560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002561 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2562 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002565
2566 n = BITS_TO_LIMBS( nbits );
2567
Janos Follathda31fa12018-09-03 14:45:23 +01002568 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2569 {
2570 /*
2571 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2572 */
2573 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2574 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2575 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2576 }
2577 else
2578 {
2579 /*
2580 * 2^-100 error probability, number of rounds computed based on HAC,
2581 * fact 4.48
2582 */
2583 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2584 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2585 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2586 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2587 }
2588
Jethro Beekman66689272018-02-14 19:24:10 -08002589 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002590 {
Jethro Beekman66689272018-02-14 19:24:10 -08002591 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2592 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2593 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2594
2595 k = n * biL;
2596 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2597 X->p[0] |= 1;
2598
Janos Follath7c025a92018-08-14 11:08:41 +01002599 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002600 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002601 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002604 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002605 }
Jethro Beekman66689272018-02-14 19:24:10 -08002606 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002607 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002608 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002609 * An necessary condition for Y and X = 2Y + 1 to be prime
2610 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2611 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002612 */
Jethro Beekman66689272018-02-14 19:24:10 -08002613
2614 X->p[0] |= 2;
2615
2616 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2617 if( r == 0 )
2618 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2619 else if( r == 1 )
2620 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2621
2622 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2624 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2625
2626 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002627 {
Jethro Beekman66689272018-02-14 19:24:10 -08002628 /*
2629 * First, check small factors for X and Y
2630 * before doing Miller-Rabin on any of them
2631 */
2632 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2633 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002634 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002635 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002636 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002637 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002638 goto cleanup;
2639
2640 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2641 goto cleanup;
2642
2643 /*
2644 * Next candidates. We want to preserve Y = (X-1) / 2 and
2645 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2646 * so up Y by 6 and X by 12.
2647 */
2648 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2649 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002650 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002651 }
2652 }
2653
2654cleanup:
2655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002656 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002657
2658 return( ret );
2659}
2660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002662
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002663#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002664
Paul Bakker23986e52011-04-24 08:57:21 +00002665#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002666
2667static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2668{
2669 { 693, 609, 21 },
2670 { 1764, 868, 28 },
2671 { 768454923, 542167814, 1 }
2672};
2673
Paul Bakker5121ce52009-01-03 21:22:43 +00002674/*
2675 * Checkup routine
2676 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002677int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002678{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002679 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002680 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002682 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2683 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002685 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002686 "EFE021C2645FD1DC586E69184AF4A31E" \
2687 "D5F53E93B5F123FA41680867BA110131" \
2688 "944FE7952E2517337780CB0DB80E61AA" \
2689 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002692 "B2E7EFD37075B9F03FF989C7C5051C20" \
2693 "34D2A323810251127E7BF8625A4F49A5" \
2694 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2695 "5B5C25763222FEFCCFC38B832366C29E" ) );
2696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002697 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002698 "0066A198186C18C10B2F5ED9B522752A" \
2699 "9830B69916E535C8F047518A889A43A5" \
2700 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002705 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2706 "9E857EA95A03512E2BAE7391688D264A" \
2707 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2708 "8001B72E848A38CAE1C65F78E56ABDEF" \
2709 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2710 "ECF677152EF804370C1A305CAF3B5BF1" \
2711 "30879B56C61DE584A0F53A2447A51E" ) );
2712
2713 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002714 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002715
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002716 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002717 {
2718 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002719 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002720
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002721 ret = 1;
2722 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002723 }
2724
2725 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002726 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002728 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002731 "256567336059E52CAE22925474705F39A94" ) );
2732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002733 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002734 "6613F26162223DF488E9CD48CC132C7A" \
2735 "0AC93C701B001B092E4E5B9F73BCD27B" \
2736 "9EE50D0657C77F374E903CDFA4C642" ) );
2737
2738 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002739 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002741 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2742 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002743 {
2744 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002745 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002746
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002747 ret = 1;
2748 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002749 }
2750
2751 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002753
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002757 "36E139AEA55215609D2816998ED020BB" \
2758 "BD96C37890F65171D948E9BC7CBAA4D9" \
2759 "325D24D6A3C12710F10A09FA08AB87" ) );
2760
2761 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002762 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002763
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002764 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002765 {
2766 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002767 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002768
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002769 ret = 1;
2770 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002771 }
2772
2773 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002775
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002776 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002777
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002778 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002779 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2780 "C3DBA76456363A10869622EAC2DD84EC" \
2781 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2782
2783 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002784 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002785
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002786 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002787 {
2788 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002790
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002791 ret = 1;
2792 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002793 }
2794
2795 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002796 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002797
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002798 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002799 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002800
Paul Bakker66d5d072014-06-17 16:39:18 +02002801 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002802 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2804 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002805
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002806 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002808 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002809 {
2810 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002812
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002813 ret = 1;
2814 goto cleanup;
2815 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002816 }
2817
2818 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002819 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002820
Paul Bakker5121ce52009-01-03 21:22:43 +00002821cleanup:
2822
2823 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002824 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002825
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002826 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2827 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002828
2829 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002830 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002831
2832 return( ret );
2833}
2834
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002835#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002837#endif /* MBEDTLS_BIGNUM_C */