blob: f0882db4bcada949414382d7556af06f0e4165e9 [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
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200585 n = mbedtls_mpi_bitlen( X );
Paul Bakker5121ce52009-01-03 21:22:43 +0000586 if( radix >= 4 ) n >>= 1;
587 if( radix >= 16 ) n >>= 1;
Andres AGd1cc7f62017-01-06 13:17:35 +0000588 /*
589 * Round up the buffer length to an even value to ensure that there is
590 * enough room for hexadecimal values that can be represented in an odd
591 * number of digits.
592 */
593 n += 3 + ( ( n + 1 ) & 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000594
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100595 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000596 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100597 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599 }
600
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100601 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603
604 if( X->s == -1 )
605 *p++ = '-';
606
607 if( radix == 16 )
608 {
Paul Bakker23986e52011-04-24 08:57:21 +0000609 int c;
610 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
Paul Bakker23986e52011-04-24 08:57:21 +0000612 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 {
Paul Bakker23986e52011-04-24 08:57:21 +0000614 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 {
Paul Bakker23986e52011-04-24 08:57:21 +0000616 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
Paul Bakker6c343d72014-07-10 14:36:19 +0200618 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 continue;
620
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000621 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000622 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 k = 1;
624 }
625 }
626 }
627 else
628 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000630
631 if( T.s == -1 )
632 T.s = 1;
633
Ron Eldora16fa292018-11-20 14:07:01 +0200634 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635 }
636
637 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100638 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
640cleanup:
641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
644 return( ret );
645}
646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000648/*
649 * Read X from an opened file
650 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000652{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000654 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000655 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000656 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000657 * Buffer should have space for (short) label and decimal formatted MPI,
658 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000659 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Hanno Becker73d7d792018-12-11 10:35:51 +0000662 MPI_VALIDATE_RET( X != NULL );
663 MPI_VALIDATE_RET( fin != NULL );
664
665 if( radix < 2 || radix > 16 )
666 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
667
Paul Bakker5121ce52009-01-03 21:22:43 +0000668 memset( s, 0, sizeof( s ) );
669 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
672 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000673 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000675
Hanno Beckerb2034b72017-04-26 11:46:46 +0100676 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
677 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000678
679 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100680 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681 if( mpi_get_digit( &d, radix, *p ) != 0 )
682 break;
683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000685}
686
687/*
688 * Write X into an opened file (or stdout if fout == NULL)
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Paul Bakker23986e52011-04-24 08:57:21 +0000692 int ret;
693 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000694 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000695 * Buffer should have space for (short) label and decimal formatted MPI,
696 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000699 MPI_VALIDATE_RET( X != NULL );
700
701 if( radix < 2 || radix > 16 )
702 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000703
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100704 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100706 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707
708 if( p == NULL ) p = "";
709
710 plen = strlen( p );
711 slen = strlen( s );
712 s[slen++] = '\r';
713 s[slen++] = '\n';
714
715 if( fout != NULL )
716 {
717 if( fwrite( p, 1, plen, fout ) != plen ||
718 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000720 }
721 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
724cleanup:
725
726 return( ret );
727}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Hanno Beckerda1655a2017-10-18 14:21:44 +0100730
731/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
732 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000733
734static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
735{
736 uint8_t i;
737 mbedtls_mpi_uint tmp = 0;
738 /* This works regardless of the endianness. */
739 for( i = 0; i < ciL; i++, x >>= 8 )
740 tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
741 return( tmp );
742}
743
744static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
745{
746#if defined(__BYTE_ORDER__)
747
748/* Nothing to do on bigendian systems. */
749#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
750 return( x );
751#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
752
753#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
754
755/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000756#if defined(__GNUC__) && defined(__GNUC_PREREQ)
757#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000758#define have_bswap
759#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000760#endif
761
762#if defined(__clang__) && defined(__has_builtin)
763#if __has_builtin(__builtin_bswap32) && \
764 __has_builtin(__builtin_bswap64)
765#define have_bswap
766#endif
767#endif
768
Hanno Beckerf8720072018-11-08 11:53:49 +0000769#if defined(have_bswap)
770 /* The compiler is hopefully able to statically evaluate this! */
771 switch( sizeof(mbedtls_mpi_uint) )
772 {
773 case 4:
774 return( __builtin_bswap32(x) );
775 case 8:
776 return( __builtin_bswap64(x) );
777 }
778#endif
779#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
780#endif /* __BYTE_ORDER__ */
781
782 /* Fall back to C-based reordering if we don't know the byte order
783 * or we couldn't use a compiler-specific builtin. */
784 return( mpi_uint_bigendian_to_host_c( x ) );
785}
786
Hanno Becker2be8a552018-10-25 12:40:09 +0100787static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100788{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100789 mbedtls_mpi_uint *cur_limb_left;
790 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100791 if( limbs == 0 )
792 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100793
794 /*
795 * Traverse limbs and
796 * - adapt byte-order in each limb
797 * - swap the limbs themselves.
798 * For that, simultaneously traverse the limbs from left to right
799 * and from right to left, as long as the left index is not bigger
800 * than the right index (it's not a problem if limbs is odd and the
801 * indices coincide in the last iteration).
802 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100803 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
804 cur_limb_left <= cur_limb_right;
805 cur_limb_left++, cur_limb_right-- )
806 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000807 mbedtls_mpi_uint tmp;
808 /* Note that if cur_limb_left == cur_limb_right,
809 * this code effectively swaps the bytes only once. */
810 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
811 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
812 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100813 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100814}
815
Paul Bakker5121ce52009-01-03 21:22:43 +0000816/*
Janos Follatha778a942019-02-13 10:28:28 +0000817 * Import X from unsigned binary data, little endian
818 */
819int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
820 const unsigned char *buf, size_t buflen )
821{
822 int ret;
823 size_t i;
824 size_t const limbs = CHARS_TO_LIMBS( buflen );
825
826 /* Ensure that target MPI has exactly the necessary number of limbs */
827 if( X->n != limbs )
828 {
829 mbedtls_mpi_free( X );
830 mbedtls_mpi_init( X );
831 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
832 }
833
834 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
835
836 for( i = 0; i < buflen; i++ )
837 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
838
839cleanup:
840
Janos Follath171a7ef2019-02-15 16:17:45 +0000841 /*
842 * This function is also used to import keys. However, wiping the buffers
843 * upon failure is not necessary because failure only can happen before any
844 * input is copied.
845 */
Janos Follatha778a942019-02-13 10:28:28 +0000846 return( ret );
847}
848
849/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000850 * Import X from unsigned binary data, big endian
851 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200852int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000853{
Paul Bakker23986e52011-04-24 08:57:21 +0000854 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100855 size_t const limbs = CHARS_TO_LIMBS( buflen );
856 size_t const overhead = ( limbs * ciL ) - buflen;
857 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000858
Hanno Becker8ce11a32018-12-19 16:18:52 +0000859 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000860 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
861
Hanno Becker073c1992017-10-17 15:17:27 +0100862 /* Ensure that target MPI has exactly the necessary number of limbs */
863 if( X->n != limbs )
864 {
865 mbedtls_mpi_free( X );
866 mbedtls_mpi_init( X );
867 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
868 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000870
Hanno Becker0e810b92019-01-03 17:13:11 +0000871 /* Avoid calling `memcpy` with NULL source argument,
872 * even if buflen is 0. */
873 if( buf != NULL )
874 {
875 Xp = (unsigned char*) X->p;
876 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100877
Hanno Becker0e810b92019-01-03 17:13:11 +0000878 mpi_bigendian_to_host( X->p, limbs );
879 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000880
881cleanup:
882
Janos Follath171a7ef2019-02-15 16:17:45 +0000883 /*
884 * This function is also used to import keys. However, wiping the buffers
885 * upon failure is not necessary because failure only can happen before any
886 * input is copied.
887 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000888 return( ret );
889}
890
891/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000892 * Export X into unsigned binary data, little endian
893 */
894int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
895 unsigned char *buf, size_t buflen )
896{
897 size_t stored_bytes = X->n * ciL;
898 size_t bytes_to_copy;
899 size_t i;
900
901 if( stored_bytes < buflen )
902 {
903 bytes_to_copy = stored_bytes;
904 }
905 else
906 {
907 bytes_to_copy = buflen;
908
909 /* The output buffer is smaller than the allocated size of X.
910 * However X may fit if its leading bytes are zero. */
911 for( i = bytes_to_copy; i < stored_bytes; i++ )
912 {
913 if( GET_BYTE( X, i ) != 0 )
914 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
915 }
916 }
917
918 for( i = 0; i < bytes_to_copy; i++ )
919 buf[i] = GET_BYTE( X, i );
920
921 if( stored_bytes < buflen )
922 {
923 /* Write trailing 0 bytes */
924 memset( buf + stored_bytes, 0, buflen - stored_bytes );
925 }
926
927 return( 0 );
928}
929
930/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000931 * Export X into unsigned binary data, big endian
932 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100933int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
934 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000935{
Hanno Becker73d7d792018-12-11 10:35:51 +0000936 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100937 size_t bytes_to_copy;
938 unsigned char *p;
939 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000940
Hanno Becker73d7d792018-12-11 10:35:51 +0000941 MPI_VALIDATE_RET( X != NULL );
942 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
943
944 stored_bytes = X->n * ciL;
945
Gilles Peskine11cdb052018-11-20 16:47:47 +0100946 if( stored_bytes < buflen )
947 {
948 /* There is enough space in the output buffer. Write initial
949 * null bytes and record the position at which to start
950 * writing the significant bytes. In this case, the execution
951 * trace of this function does not depend on the value of the
952 * number. */
953 bytes_to_copy = stored_bytes;
954 p = buf + buflen - stored_bytes;
955 memset( buf, 0, buflen - stored_bytes );
956 }
957 else
958 {
959 /* The output buffer is smaller than the allocated size of X.
960 * However X may fit if its leading bytes are zero. */
961 bytes_to_copy = buflen;
962 p = buf;
963 for( i = bytes_to_copy; i < stored_bytes; i++ )
964 {
965 if( GET_BYTE( X, i ) != 0 )
966 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
967 }
968 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
Gilles Peskine11cdb052018-11-20 16:47:47 +0100970 for( i = 0; i < bytes_to_copy; i++ )
971 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
973 return( 0 );
974}
975
976/*
977 * Left-shift: X <<= count
978 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200979int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000980{
Paul Bakker23986e52011-04-24 08:57:21 +0000981 int ret;
982 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000984 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000985
986 v0 = count / (biL );
987 t1 = count & (biL - 1);
988
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200989 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000990
Paul Bakkerf9688572011-05-05 10:00:45 +0000991 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000993
994 ret = 0;
995
996 /*
997 * shift by count / limb_size
998 */
999 if( v0 > 0 )
1000 {
Paul Bakker23986e52011-04-24 08:57:21 +00001001 for( i = X->n; i > v0; i-- )
1002 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001003
Paul Bakker23986e52011-04-24 08:57:21 +00001004 for( ; i > 0; i-- )
1005 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001006 }
1007
1008 /*
1009 * shift by count % limb_size
1010 */
1011 if( t1 > 0 )
1012 {
1013 for( i = v0; i < X->n; i++ )
1014 {
1015 r1 = X->p[i] >> (biL - t1);
1016 X->p[i] <<= t1;
1017 X->p[i] |= r0;
1018 r0 = r1;
1019 }
1020 }
1021
1022cleanup:
1023
1024 return( ret );
1025}
1026
1027/*
1028 * Right-shift: X >>= count
1029 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031{
Paul Bakker23986e52011-04-24 08:57:21 +00001032 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +00001034 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001035
1036 v0 = count / biL;
1037 v1 = count & (biL - 1);
1038
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001039 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001041
Paul Bakker5121ce52009-01-03 21:22:43 +00001042 /*
1043 * shift by count / limb_size
1044 */
1045 if( v0 > 0 )
1046 {
1047 for( i = 0; i < X->n - v0; i++ )
1048 X->p[i] = X->p[i + v0];
1049
1050 for( ; i < X->n; i++ )
1051 X->p[i] = 0;
1052 }
1053
1054 /*
1055 * shift by count % limb_size
1056 */
1057 if( v1 > 0 )
1058 {
Paul Bakker23986e52011-04-24 08:57:21 +00001059 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001060 {
Paul Bakker23986e52011-04-24 08:57:21 +00001061 r1 = X->p[i - 1] << (biL - v1);
1062 X->p[i - 1] >>= v1;
1063 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001064 r0 = r1;
1065 }
1066 }
1067
1068 return( 0 );
1069}
1070
1071/*
1072 * Compare unsigned values
1073 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001075{
Paul Bakker23986e52011-04-24 08:57:21 +00001076 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001077 MPI_VALIDATE_RET( X != NULL );
1078 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001079
Paul Bakker23986e52011-04-24 08:57:21 +00001080 for( i = X->n; i > 0; i-- )
1081 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 break;
1083
Paul Bakker23986e52011-04-24 08:57:21 +00001084 for( j = Y->n; j > 0; j-- )
1085 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001086 break;
1087
Paul Bakker23986e52011-04-24 08:57:21 +00001088 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001089 return( 0 );
1090
1091 if( i > j ) return( 1 );
1092 if( j > i ) return( -1 );
1093
Paul Bakker23986e52011-04-24 08:57:21 +00001094 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001095 {
Paul Bakker23986e52011-04-24 08:57:21 +00001096 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1097 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001098 }
1099
1100 return( 0 );
1101}
1102
1103/*
1104 * Compare signed values
1105 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001107{
Paul Bakker23986e52011-04-24 08:57:21 +00001108 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001109 MPI_VALIDATE_RET( X != NULL );
1110 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001111
Paul Bakker23986e52011-04-24 08:57:21 +00001112 for( i = X->n; i > 0; i-- )
1113 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001114 break;
1115
Paul Bakker23986e52011-04-24 08:57:21 +00001116 for( j = Y->n; j > 0; j-- )
1117 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001118 break;
1119
Paul Bakker23986e52011-04-24 08:57:21 +00001120 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001121 return( 0 );
1122
1123 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001124 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001125
1126 if( X->s > 0 && Y->s < 0 ) return( 1 );
1127 if( Y->s > 0 && X->s < 0 ) return( -1 );
1128
Paul Bakker23986e52011-04-24 08:57:21 +00001129 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001130 {
Paul Bakker23986e52011-04-24 08:57:21 +00001131 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1132 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001133 }
1134
1135 return( 0 );
1136}
1137
1138/*
1139 * Compare signed values
1140 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001142{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143 mbedtls_mpi Y;
1144 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001145 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001146
1147 *p = ( z < 0 ) ? -z : z;
1148 Y.s = ( z < 0 ) ? -1 : 1;
1149 Y.n = 1;
1150 Y.p = p;
1151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001153}
1154
1155/*
1156 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1157 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001158int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001159{
Paul Bakker23986e52011-04-24 08:57:21 +00001160 int ret;
1161 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001162 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001163 MPI_VALIDATE_RET( X != NULL );
1164 MPI_VALIDATE_RET( A != NULL );
1165 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001166
1167 if( X == B )
1168 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001170 }
1171
1172 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001174
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001175 /*
1176 * X should always be positive as a result of unsigned additions.
1177 */
1178 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001179
Paul Bakker23986e52011-04-24 08:57:21 +00001180 for( j = B->n; j > 0; j-- )
1181 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001182 break;
1183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001184 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001185
1186 o = B->p; p = X->p; c = 0;
1187
Janos Follath6c922682015-10-30 17:43:11 +01001188 /*
1189 * tmp is used because it might happen that p == o
1190 */
Paul Bakker23986e52011-04-24 08:57:21 +00001191 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 {
Janos Follath6c922682015-10-30 17:43:11 +01001193 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001194 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001195 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001196 }
1197
1198 while( c != 0 )
1199 {
1200 if( i >= X->n )
1201 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203 p = X->p + i;
1204 }
1205
Paul Bakker2d319fd2012-09-16 21:34:26 +00001206 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 }
1208
1209cleanup:
1210
1211 return( ret );
1212}
1213
1214/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001218{
Paul Bakker23986e52011-04-24 08:57:21 +00001219 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001221
1222 for( i = c = 0; i < n; i++, s++, d++ )
1223 {
1224 z = ( *d < c ); *d -= c;
1225 c = ( *d < *s ) + z; *d -= *s;
1226 }
1227
1228 while( c != 0 )
1229 {
1230 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001231 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001232 }
1233}
1234
1235/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001236 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001237 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001239{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001241 int ret;
1242 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001243 MPI_VALIDATE_RET( X != NULL );
1244 MPI_VALIDATE_RET( A != NULL );
1245 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1248 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001251
1252 if( X == B )
1253 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001255 B = &TB;
1256 }
1257
1258 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001260
Paul Bakker1ef7a532009-06-20 10:50:55 +00001261 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001262 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001263 */
1264 X->s = 1;
1265
Paul Bakker5121ce52009-01-03 21:22:43 +00001266 ret = 0;
1267
Paul Bakker23986e52011-04-24 08:57:21 +00001268 for( n = B->n; n > 0; n-- )
1269 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001270 break;
1271
Paul Bakker23986e52011-04-24 08:57:21 +00001272 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001273
1274cleanup:
1275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001276 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
1278 return( ret );
1279}
1280
1281/*
1282 * Signed addition: X = A + B
1283 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001285{
Hanno Becker73d7d792018-12-11 10:35:51 +00001286 int ret, s;
1287 MPI_VALIDATE_RET( X != NULL );
1288 MPI_VALIDATE_RET( A != NULL );
1289 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001290
Hanno Becker73d7d792018-12-11 10:35:51 +00001291 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001292 if( A->s * B->s < 0 )
1293 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001295 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001296 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001297 X->s = s;
1298 }
1299 else
1300 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001302 X->s = -s;
1303 }
1304 }
1305 else
1306 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001308 X->s = s;
1309 }
1310
1311cleanup:
1312
1313 return( ret );
1314}
1315
1316/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001317 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001320{
Hanno Becker73d7d792018-12-11 10:35:51 +00001321 int ret, s;
1322 MPI_VALIDATE_RET( X != NULL );
1323 MPI_VALIDATE_RET( A != NULL );
1324 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001325
Hanno Becker73d7d792018-12-11 10:35:51 +00001326 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001327 if( A->s * B->s > 0 )
1328 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001330 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 X->s = s;
1333 }
1334 else
1335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 X->s = -s;
1338 }
1339 }
1340 else
1341 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001343 X->s = s;
1344 }
1345
1346cleanup:
1347
1348 return( ret );
1349}
1350
1351/*
1352 * Signed addition: X = A + b
1353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001355{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356 mbedtls_mpi _B;
1357 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001358 MPI_VALIDATE_RET( X != NULL );
1359 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001360
1361 p[0] = ( b < 0 ) ? -b : b;
1362 _B.s = ( b < 0 ) ? -1 : 1;
1363 _B.n = 1;
1364 _B.p = p;
1365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001367}
1368
1369/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001370 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001371 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001373{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 mbedtls_mpi _B;
1375 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001376 MPI_VALIDATE_RET( X != NULL );
1377 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001378
1379 p[0] = ( b < 0 ) ? -b : b;
1380 _B.s = ( b < 0 ) ? -1 : 1;
1381 _B.n = 1;
1382 _B.p = p;
1383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001385}
1386
1387/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001389 */
1390static
1391#if defined(__APPLE__) && defined(__arm__)
1392/*
1393 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1394 * appears to need this to prevent bad ARM code generation at -O3.
1395 */
1396__attribute__ ((noinline))
1397#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398void 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 +00001399{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001401
1402#if defined(MULADDC_HUIT)
1403 for( ; i >= 8; i -= 8 )
1404 {
1405 MULADDC_INIT
1406 MULADDC_HUIT
1407 MULADDC_STOP
1408 }
1409
1410 for( ; i > 0; i-- )
1411 {
1412 MULADDC_INIT
1413 MULADDC_CORE
1414 MULADDC_STOP
1415 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001416#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001417 for( ; i >= 16; i -= 16 )
1418 {
1419 MULADDC_INIT
1420 MULADDC_CORE MULADDC_CORE
1421 MULADDC_CORE MULADDC_CORE
1422 MULADDC_CORE MULADDC_CORE
1423 MULADDC_CORE MULADDC_CORE
1424
1425 MULADDC_CORE MULADDC_CORE
1426 MULADDC_CORE MULADDC_CORE
1427 MULADDC_CORE MULADDC_CORE
1428 MULADDC_CORE MULADDC_CORE
1429 MULADDC_STOP
1430 }
1431
1432 for( ; i >= 8; i -= 8 )
1433 {
1434 MULADDC_INIT
1435 MULADDC_CORE MULADDC_CORE
1436 MULADDC_CORE MULADDC_CORE
1437
1438 MULADDC_CORE MULADDC_CORE
1439 MULADDC_CORE MULADDC_CORE
1440 MULADDC_STOP
1441 }
1442
1443 for( ; i > 0; i-- )
1444 {
1445 MULADDC_INIT
1446 MULADDC_CORE
1447 MULADDC_STOP
1448 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001449#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001450
1451 t++;
1452
1453 do {
1454 *d += c; c = ( *d < c ); d++;
1455 }
1456 while( c != 0 );
1457}
1458
1459/*
1460 * Baseline multiplication: X = A * B (HAC 14.12)
1461 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001463{
Paul Bakker23986e52011-04-24 08:57:21 +00001464 int ret;
1465 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001467 MPI_VALIDATE_RET( X != NULL );
1468 MPI_VALIDATE_RET( A != NULL );
1469 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1474 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
Paul Bakker23986e52011-04-24 08:57:21 +00001476 for( i = A->n; i > 0; i-- )
1477 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001478 break;
1479
Paul Bakker23986e52011-04-24 08:57:21 +00001480 for( j = B->n; j > 0; j-- )
1481 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001482 break;
1483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1485 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001486
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001487 for( ; j > 0; j-- )
1488 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
1490 X->s = A->s * B->s;
1491
1492cleanup:
1493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
1496 return( ret );
1497}
1498
1499/*
1500 * Baseline multiplication: X = A * b
1501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001503{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504 mbedtls_mpi _B;
1505 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001506 MPI_VALIDATE_RET( X != NULL );
1507 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001508
1509 _B.s = 1;
1510 _B.n = 1;
1511 _B.p = p;
1512 p[0] = b;
1513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001515}
1516
1517/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001518 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1519 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001520 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001521static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1522 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001523{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001524#if defined(MBEDTLS_HAVE_UDBL)
1525 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001526#else
Simon Butcher9803d072016-01-03 00:24:34 +00001527 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1528 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001529 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1530 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001531 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001532#endif
1533
Simon Butcher15b15d12015-11-26 19:35:03 +00001534 /*
1535 * Check for overflow
1536 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001537 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001538 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001539 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001540
Simon Butcherf5ba0452015-12-27 23:01:55 +00001541 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001542 }
1543
1544#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001545 dividend = (mbedtls_t_udbl) u1 << biL;
1546 dividend |= (mbedtls_t_udbl) u0;
1547 quotient = dividend / d;
1548 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1549 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1550
1551 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001552 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001553
1554 return (mbedtls_mpi_uint) quotient;
1555#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001556
1557 /*
1558 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1559 * Vol. 2 - Seminumerical Algorithms, Knuth
1560 */
1561
1562 /*
1563 * Normalize the divisor, d, and dividend, u0, u1
1564 */
1565 s = mbedtls_clz( d );
1566 d = d << s;
1567
1568 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001569 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001570 u0 = u0 << s;
1571
1572 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001573 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001574
1575 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001576 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001577
1578 /*
1579 * Find the first quotient and remainder
1580 */
1581 q1 = u1 / d1;
1582 r0 = u1 - d1 * q1;
1583
1584 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1585 {
1586 q1 -= 1;
1587 r0 += d1;
1588
1589 if ( r0 >= radix ) break;
1590 }
1591
Simon Butcherf5ba0452015-12-27 23:01:55 +00001592 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001593 q0 = rAX / d1;
1594 r0 = rAX - q0 * d1;
1595
1596 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1597 {
1598 q0 -= 1;
1599 r0 += d1;
1600
1601 if ( r0 >= radix ) break;
1602 }
1603
1604 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001605 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001606
1607 quotient = q1 * radix + q0;
1608
1609 return quotient;
1610#endif
1611}
1612
1613/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001615 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001616int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1617 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001618{
Paul Bakker23986e52011-04-24 08:57:21 +00001619 int ret;
1620 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001622 MPI_VALIDATE_RET( A != NULL );
1623 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001625 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1626 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001627
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1629 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001632 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1634 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001635 return( 0 );
1636 }
1637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1639 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001640 X.s = Y.s = 1;
1641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1643 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1644 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1645 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001646
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001647 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001648 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001649 {
1650 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1652 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001653 }
1654 else k = 0;
1655
1656 n = X.n - 1;
1657 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001661 {
1662 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001666
1667 for( i = n; i > t ; i-- )
1668 {
1669 if( X.p[i] >= Y.p[t] )
1670 Z.p[i - t - 1] = ~0;
1671 else
1672 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001673 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1674 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 }
1676
1677 Z.p[i - t - 1]++;
1678 do
1679 {
1680 Z.p[i - t - 1]--;
1681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001683 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001684 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001688 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1689 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 T2.p[2] = X.p[i];
1691 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1695 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1696 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001699 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1701 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1702 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703 Z.p[i - t - 1]--;
1704 }
1705 }
1706
1707 if( Q != NULL )
1708 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001709 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001710 Q->s = A->s * B->s;
1711 }
1712
1713 if( R != NULL )
1714 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001716 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001720 R->s = 1;
1721 }
1722
1723cleanup:
1724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1726 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001727
1728 return( ret );
1729}
1730
1731/*
1732 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001733 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001734int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1735 const mbedtls_mpi *A,
1736 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001737{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 mbedtls_mpi _B;
1739 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001740 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001741
1742 p[0] = ( b < 0 ) ? -b : b;
1743 _B.s = ( b < 0 ) ? -1 : 1;
1744 _B.n = 1;
1745 _B.p = p;
1746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001748}
1749
1750/*
1751 * Modulo: R = A mod B
1752 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001754{
1755 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001756 MPI_VALIDATE_RET( R != NULL );
1757 MPI_VALIDATE_RET( A != NULL );
1758 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1761 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1766 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1769 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001770
1771cleanup:
1772
1773 return( ret );
1774}
1775
1776/*
1777 * Modulo: r = A mod b
1778 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001779int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001780{
Paul Bakker23986e52011-04-24 08:57:21 +00001781 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001782 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001783 MPI_VALIDATE_RET( r != NULL );
1784 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785
1786 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001788
1789 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001791
1792 /*
1793 * handle trivial cases
1794 */
1795 if( b == 1 )
1796 {
1797 *r = 0;
1798 return( 0 );
1799 }
1800
1801 if( b == 2 )
1802 {
1803 *r = A->p[0] & 1;
1804 return( 0 );
1805 }
1806
1807 /*
1808 * general case
1809 */
Paul Bakker23986e52011-04-24 08:57:21 +00001810 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001811 {
Paul Bakker23986e52011-04-24 08:57:21 +00001812 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001813 y = ( y << biH ) | ( x >> biH );
1814 z = y / b;
1815 y -= z * b;
1816
1817 x <<= biH;
1818 y = ( y << biH ) | ( x >> biH );
1819 z = y / b;
1820 y -= z * b;
1821 }
1822
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001823 /*
1824 * If A is negative, then the current y represents a negative value.
1825 * Flipping it to the positive side.
1826 */
1827 if( A->s < 0 && y != 0 )
1828 y = b - y;
1829
Paul Bakker5121ce52009-01-03 21:22:43 +00001830 *r = y;
1831
1832 return( 0 );
1833}
1834
1835/*
1836 * Fast Montgomery initialization (thanks to Tom St Denis)
1837 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001839{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001841 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001842
1843 x = m0;
1844 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001846 for( i = biL; i >= 8; i /= 2 )
1847 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001848
1849 *mm = ~x + 1;
1850}
1851
1852/*
1853 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1854 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001855static 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 +02001856 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001857{
Paul Bakker23986e52011-04-24 08:57:21 +00001858 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001860
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001861 if( T->n < N->n + 1 || T->p == NULL )
1862 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1863
Paul Bakker5121ce52009-01-03 21:22:43 +00001864 memset( T->p, 0, T->n * ciL );
1865
1866 d = T->p;
1867 n = N->n;
1868 m = ( B->n < n ) ? B->n : n;
1869
1870 for( i = 0; i < n; i++ )
1871 {
1872 /*
1873 * T = (T + u0*B + u1*N) / 2^biL
1874 */
1875 u0 = A->p[i];
1876 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1877
1878 mpi_mul_hlp( m, B->p, d, u0 );
1879 mpi_mul_hlp( n, N->p, d, u1 );
1880
1881 *d++ = u0; d[n + 1] = 0;
1882 }
1883
Paul Bakker66d5d072014-06-17 16:39:18 +02001884 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001886 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001887 mpi_sub_hlp( n, N->p, A->p );
1888 else
1889 /* prevent timing attacks */
1890 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001891
1892 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001893}
1894
1895/*
1896 * Montgomery reduction: A = A * R^-1 mod N
1897 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001898static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1899 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001900{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 mbedtls_mpi_uint z = 1;
1902 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001903
Paul Bakker8ddb6452013-02-27 14:56:33 +01001904 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001905 U.p = &z;
1906
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001907 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001908}
1909
1910/*
1911 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1912 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001913int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1914 const mbedtls_mpi *E, const mbedtls_mpi *N,
1915 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001916{
Paul Bakker23986e52011-04-24 08:57:21 +00001917 int ret;
1918 size_t wbits, wsize, one = 1;
1919 size_t i, j, nblimbs;
1920 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 mbedtls_mpi_uint ei, mm, state;
1922 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001923 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
Hanno Becker73d7d792018-12-11 10:35:51 +00001925 MPI_VALIDATE_RET( X != NULL );
1926 MPI_VALIDATE_RET( A != NULL );
1927 MPI_VALIDATE_RET( E != NULL );
1928 MPI_VALIDATE_RET( N != NULL );
1929
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001930 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1934 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001935
1936 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001937 * Init temps and window size
1938 */
1939 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001940 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1941 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 memset( W, 0, sizeof( W ) );
1943
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001944 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945
1946 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1947 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1948
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1950 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001951
Paul Bakker5121ce52009-01-03 21:22:43 +00001952 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001953 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1954 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001956
1957 /*
Paul Bakker50546922012-05-19 08:40:49 +00001958 * Compensate for negative A (and correct at the end)
1959 */
1960 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00001961 if( neg )
1962 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00001964 Apos.s = 1;
1965 A = &Apos;
1966 }
1967
1968 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001969 * If 1st call, pre-compute R^2 mod N
1970 */
1971 if( _RR == NULL || _RR->p == NULL )
1972 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1974 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1975 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001976
1977 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979 }
1980 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
1983 /*
1984 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1985 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1987 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01001988 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001990
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001991 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001992
1993 /*
1994 * X = R^2 * R^-1 mod N = R mod N
1995 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001996 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001997 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
1999 if( wsize > 1 )
2000 {
2001 /*
2002 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2003 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002004 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002005
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2007 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002008
2009 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002010 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002011
Paul Bakker5121ce52009-01-03 21:22:43 +00002012 /*
2013 * W[i] = W[i - 1] * W[1]
2014 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002015 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002016 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2018 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002019
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002020 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002021 }
2022 }
2023
2024 nblimbs = E->n;
2025 bufsize = 0;
2026 nbits = 0;
2027 wbits = 0;
2028 state = 0;
2029
2030 while( 1 )
2031 {
2032 if( bufsize == 0 )
2033 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002034 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002035 break;
2036
Paul Bakker0d7702c2013-10-29 16:18:35 +01002037 nblimbs--;
2038
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002040 }
2041
2042 bufsize--;
2043
2044 ei = (E->p[nblimbs] >> bufsize) & 1;
2045
2046 /*
2047 * skip leading 0s
2048 */
2049 if( ei == 0 && state == 0 )
2050 continue;
2051
2052 if( ei == 0 && state == 1 )
2053 {
2054 /*
2055 * out of window, square X
2056 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002057 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 continue;
2059 }
2060
2061 /*
2062 * add ei to current window
2063 */
2064 state = 2;
2065
2066 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002067 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002068
2069 if( nbits == wsize )
2070 {
2071 /*
2072 * X = X^wsize R^-1 mod N
2073 */
2074 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002075 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002076
2077 /*
2078 * X = X * W[wbits] R^-1 mod N
2079 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002080 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002081
2082 state--;
2083 nbits = 0;
2084 wbits = 0;
2085 }
2086 }
2087
2088 /*
2089 * process the remaining bits
2090 */
2091 for( i = 0; i < nbits; i++ )
2092 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002093 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002094
2095 wbits <<= 1;
2096
Paul Bakker66d5d072014-06-17 16:39:18 +02002097 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002098 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002099 }
2100
2101 /*
2102 * X = A^E * R * R^-1 mod N = A^E mod N
2103 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002104 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002105
Hanno Beckera4af1c42017-04-18 09:07:45 +01002106 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002107 {
2108 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002109 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002110 }
2111
Paul Bakker5121ce52009-01-03 21:22:43 +00002112cleanup:
2113
Paul Bakker66d5d072014-06-17 16:39:18 +02002114 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002118
Paul Bakker75a28602014-03-31 12:08:17 +02002119 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002121
2122 return( ret );
2123}
2124
Paul Bakker5121ce52009-01-03 21:22:43 +00002125/*
2126 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2127 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002128int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002129{
Paul Bakker23986e52011-04-24 08:57:21 +00002130 int ret;
2131 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002132 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
Hanno Becker73d7d792018-12-11 10:35:51 +00002134 MPI_VALIDATE_RET( G != NULL );
2135 MPI_VALIDATE_RET( A != NULL );
2136 MPI_VALIDATE_RET( B != NULL );
2137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002140 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2141 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002142
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002143 lz = mbedtls_mpi_lsb( &TA );
2144 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002145
Paul Bakker66d5d072014-06-17 16:39:18 +02002146 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002147 lz = lzt;
2148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002149 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2150 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002151
Paul Bakker5121ce52009-01-03 21:22:43 +00002152 TA.s = TB.s = 1;
2153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002155 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2157 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002160 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002161 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2162 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002163 }
2164 else
2165 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002166 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2167 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002168 }
2169 }
2170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2172 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002173
2174cleanup:
2175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002176 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002177
2178 return( ret );
2179}
2180
Paul Bakker33dc46b2014-04-30 16:11:39 +02002181/*
2182 * Fill X with size bytes of random.
2183 *
2184 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002185 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002186 * deterministic, eg for tests).
2187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002189 int (*f_rng)(void *, unsigned char *, size_t),
2190 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002191{
Paul Bakker23986e52011-04-24 08:57:21 +00002192 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002193 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002194 size_t const overhead = ( limbs * ciL ) - size;
2195 unsigned char *Xp;
2196
Hanno Becker8ce11a32018-12-19 16:18:52 +00002197 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002198 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002199
Hanno Beckerda1655a2017-10-18 14:21:44 +01002200 /* Ensure that target MPI has exactly the necessary number of limbs */
2201 if( X->n != limbs )
2202 {
2203 mbedtls_mpi_free( X );
2204 mbedtls_mpi_init( X );
2205 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2206 }
2207 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002208
Hanno Beckerda1655a2017-10-18 14:21:44 +01002209 Xp = (unsigned char*) X->p;
2210 f_rng( p_rng, Xp + overhead, size );
2211
Hanno Becker2be8a552018-10-25 12:40:09 +01002212 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002213
2214cleanup:
2215 return( ret );
2216}
2217
Paul Bakker5121ce52009-01-03 21:22:43 +00002218/*
2219 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002221int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002222{
2223 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002224 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002225 MPI_VALIDATE_RET( X != NULL );
2226 MPI_VALIDATE_RET( A != NULL );
2227 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002228
Hanno Becker4bcb4912017-04-18 15:49:39 +01002229 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2233 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2234 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002241 goto cleanup;
2242 }
2243
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2245 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2246 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2247 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2250 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2251 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2252 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002253
2254 do
2255 {
2256 while( ( TU.p[0] & 1 ) == 0 )
2257 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002259
2260 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2261 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002262 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2263 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 }
2265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2267 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002268 }
2269
2270 while( ( TV.p[0] & 1 ) == 0 )
2271 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2275 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2277 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 }
2279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2281 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002282 }
2283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002285 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2287 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2288 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002289 }
2290 else
2291 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002292 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2293 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2294 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002295 }
2296 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2300 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2303 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306
2307cleanup:
2308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002309 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2310 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2311 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002312
2313 return( ret );
2314}
2315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002316#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002317
Paul Bakker5121ce52009-01-03 21:22:43 +00002318static const int small_prime[] =
2319{
2320 3, 5, 7, 11, 13, 17, 19, 23,
2321 29, 31, 37, 41, 43, 47, 53, 59,
2322 61, 67, 71, 73, 79, 83, 89, 97,
2323 101, 103, 107, 109, 113, 127, 131, 137,
2324 139, 149, 151, 157, 163, 167, 173, 179,
2325 181, 191, 193, 197, 199, 211, 223, 227,
2326 229, 233, 239, 241, 251, 257, 263, 269,
2327 271, 277, 281, 283, 293, 307, 311, 313,
2328 317, 331, 337, 347, 349, 353, 359, 367,
2329 373, 379, 383, 389, 397, 401, 409, 419,
2330 421, 431, 433, 439, 443, 449, 457, 461,
2331 463, 467, 479, 487, 491, 499, 503, 509,
2332 521, 523, 541, 547, 557, 563, 569, 571,
2333 577, 587, 593, 599, 601, 607, 613, 617,
2334 619, 631, 641, 643, 647, 653, 659, 661,
2335 673, 677, 683, 691, 701, 709, 719, 727,
2336 733, 739, 743, 751, 757, 761, 769, 773,
2337 787, 797, 809, 811, 821, 823, 827, 829,
2338 839, 853, 857, 859, 863, 877, 881, 883,
2339 887, 907, 911, 919, 929, 937, 941, 947,
2340 953, 967, 971, 977, 983, 991, 997, -103
2341};
2342
2343/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002344 * Small divisors test (X must be positive)
2345 *
2346 * Return values:
2347 * 0: no small factor (possible prime, more tests needed)
2348 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002350 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002353{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002354 int ret = 0;
2355 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002357
Paul Bakker5121ce52009-01-03 21:22:43 +00002358 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
2361 for( i = 0; small_prime[i] > 0; i++ )
2362 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002364 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002367
2368 if( r == 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
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002372cleanup:
2373 return( ret );
2374}
2375
2376/*
2377 * Miller-Rabin pseudo-primality test (HAC 4.24)
2378 */
Janos Follathda31fa12018-09-03 14:45:23 +01002379static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002380 int (*f_rng)(void *, unsigned char *, size_t),
2381 void *p_rng )
2382{
Pascal Junodb99183d2015-03-11 16:49:45 +01002383 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002384 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002386
Hanno Becker8ce11a32018-12-19 16:18:52 +00002387 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002388 MPI_VALIDATE_RET( f_rng != NULL );
2389
2390 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2391 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002392 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002393
Paul Bakker5121ce52009-01-03 21:22:43 +00002394 /*
2395 * W = |X| - 1
2396 * R = W >> lsb( W )
2397 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2399 s = mbedtls_mpi_lsb( &W );
2400 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2401 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002403 i = mbedtls_mpi_bitlen( X );
Janos Follathf301d232018-08-14 13:34:01 +01002404
Janos Follathda31fa12018-09-03 14:45:23 +01002405 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002406 {
2407 /*
2408 * pick a random A, 1 < A < |X| - 1
2409 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002410 count = 0;
2411 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002412 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002413
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002414 j = mbedtls_mpi_bitlen( &A );
2415 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002416 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002417 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002418 }
2419
2420 if (count++ > 30) {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002421 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Pascal Junodb99183d2015-03-11 16:49:45 +01002422 }
2423
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002424 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2425 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002426
2427 /*
2428 * A = A^R mod |X|
2429 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002430 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2433 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002434 continue;
2435
2436 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002438 {
2439 /*
2440 * A = A * A mod |X|
2441 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002442 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2443 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002445 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002446 break;
2447
2448 j++;
2449 }
2450
2451 /*
2452 * not prime if A != |X| - 1 or A == 1
2453 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002454 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2455 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002456 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002458 break;
2459 }
2460 }
2461
2462cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002463 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2464 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002465 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002466
2467 return( ret );
2468}
2469
2470/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002471 * Pseudo-primality test: small factors, then Miller-Rabin
2472 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002473int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2474 int (*f_rng)(void *, unsigned char *, size_t),
2475 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002476{
2477 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002479 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002480 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002481
2482 XX.s = 1;
2483 XX.n = X->n;
2484 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2487 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2488 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002491 return( 0 );
2492
2493 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2494 {
2495 if( ret == 1 )
2496 return( 0 );
2497
2498 return( ret );
2499 }
2500
Janos Follathda31fa12018-09-03 14:45:23 +01002501 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002502}
2503
Janos Follatha0b67c22018-09-18 14:48:23 +01002504#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002505/*
2506 * Pseudo-primality test, error probability 2^-80
2507 */
2508int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2509 int (*f_rng)(void *, unsigned char *, size_t),
2510 void *p_rng )
2511{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002512 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002513 MPI_VALIDATE_RET( f_rng != NULL );
2514
Janos Follatha0b67c22018-09-18 14:48:23 +01002515 /*
2516 * In the past our key generation aimed for an error rate of at most
2517 * 2^-80. Since this function is deprecated, aim for the same certainty
2518 * here as well.
2519 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002520 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002521}
Janos Follatha0b67c22018-09-18 14:48:23 +01002522#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002523
2524/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002525 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002526 *
Janos Follathf301d232018-08-14 13:34:01 +01002527 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2528 * be either 1024 bits or 1536 bits long, and flags must contain
2529 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002530 */
Janos Follath7c025a92018-08-14 11:08:41 +01002531int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002532 int (*f_rng)(void *, unsigned char *, size_t),
2533 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002534{
Jethro Beekman66689272018-02-14 19:24:10 -08002535#ifdef MBEDTLS_HAVE_INT64
2536// ceil(2^63.5)
2537#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2538#else
2539// ceil(2^31.5)
2540#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2541#endif
2542 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002543 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002544 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 mbedtls_mpi_uint r;
2546 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002547
Hanno Becker8ce11a32018-12-19 16:18:52 +00002548 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002549 MPI_VALIDATE_RET( f_rng != NULL );
2550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002551 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2552 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002555
2556 n = BITS_TO_LIMBS( nbits );
2557
Janos Follathda31fa12018-09-03 14:45:23 +01002558 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2559 {
2560 /*
2561 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2562 */
2563 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2564 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2565 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2566 }
2567 else
2568 {
2569 /*
2570 * 2^-100 error probability, number of rounds computed based on HAC,
2571 * fact 4.48
2572 */
2573 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2574 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2575 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2576 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2577 }
2578
Jethro Beekman66689272018-02-14 19:24:10 -08002579 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002580 {
Jethro Beekman66689272018-02-14 19:24:10 -08002581 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2582 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2583 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2584
2585 k = n * biL;
2586 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2587 X->p[0] |= 1;
2588
Janos Follath7c025a92018-08-14 11:08:41 +01002589 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002590 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002591 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002594 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002595 }
Jethro Beekman66689272018-02-14 19:24:10 -08002596 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002597 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002598 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002599 * An necessary condition for Y and X = 2Y + 1 to be prime
2600 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2601 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002602 */
Jethro Beekman66689272018-02-14 19:24:10 -08002603
2604 X->p[0] |= 2;
2605
2606 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2607 if( r == 0 )
2608 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2609 else if( r == 1 )
2610 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2611
2612 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2613 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2614 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2615
2616 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002617 {
Jethro Beekman66689272018-02-14 19:24:10 -08002618 /*
2619 * First, check small factors for X and Y
2620 * before doing Miller-Rabin on any of them
2621 */
2622 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2623 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002624 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002625 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002626 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002627 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002628 goto cleanup;
2629
2630 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2631 goto cleanup;
2632
2633 /*
2634 * Next candidates. We want to preserve Y = (X-1) / 2 and
2635 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2636 * so up Y by 6 and X by 12.
2637 */
2638 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2639 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002640 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002641 }
2642 }
2643
2644cleanup:
2645
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002646 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002647
2648 return( ret );
2649}
2650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002651#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002653#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002654
Paul Bakker23986e52011-04-24 08:57:21 +00002655#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002656
2657static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2658{
2659 { 693, 609, 21 },
2660 { 1764, 868, 28 },
2661 { 768454923, 542167814, 1 }
2662};
2663
Paul Bakker5121ce52009-01-03 21:22:43 +00002664/*
2665 * Checkup routine
2666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002667int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002668{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002669 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002670 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002672 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2673 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002674
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002675 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002676 "EFE021C2645FD1DC586E69184AF4A31E" \
2677 "D5F53E93B5F123FA41680867BA110131" \
2678 "944FE7952E2517337780CB0DB80E61AA" \
2679 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2680
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002681 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002682 "B2E7EFD37075B9F03FF989C7C5051C20" \
2683 "34D2A323810251127E7BF8625A4F49A5" \
2684 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2685 "5B5C25763222FEFCCFC38B832366C29E" ) );
2686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002688 "0066A198186C18C10B2F5ED9B522752A" \
2689 "9830B69916E535C8F047518A889A43A5" \
2690 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002692 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002695 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2696 "9E857EA95A03512E2BAE7391688D264A" \
2697 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2698 "8001B72E848A38CAE1C65F78E56ABDEF" \
2699 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2700 "ECF677152EF804370C1A305CAF3B5BF1" \
2701 "30879B56C61DE584A0F53A2447A51E" ) );
2702
2703 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002704 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002705
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002706 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002707 {
2708 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002709 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002710
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002711 ret = 1;
2712 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002713 }
2714
2715 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002716 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002718 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002720 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002721 "256567336059E52CAE22925474705F39A94" ) );
2722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002723 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002724 "6613F26162223DF488E9CD48CC132C7A" \
2725 "0AC93C701B001B092E4E5B9F73BCD27B" \
2726 "9EE50D0657C77F374E903CDFA4C642" ) );
2727
2728 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002729 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002731 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2732 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002733 {
2734 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002735 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002736
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002737 ret = 1;
2738 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002739 }
2740
2741 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002742 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002743
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002745
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002746 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002747 "36E139AEA55215609D2816998ED020BB" \
2748 "BD96C37890F65171D948E9BC7CBAA4D9" \
2749 "325D24D6A3C12710F10A09FA08AB87" ) );
2750
2751 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002753
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002755 {
2756 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002757 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002758
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002759 ret = 1;
2760 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002761 }
2762
2763 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002764 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002765
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002766 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002769 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2770 "C3DBA76456363A10869622EAC2DD84EC" \
2771 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2772
2773 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002775
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002776 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002777 {
2778 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002779 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002780
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002781 ret = 1;
2782 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002783 }
2784
2785 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002786 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002787
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002788 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002790
Paul Bakker66d5d072014-06-17 16:39:18 +02002791 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002792 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002793 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2794 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002795
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002796 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002797
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002798 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002799 {
2800 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002801 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002802
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002803 ret = 1;
2804 goto cleanup;
2805 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002806 }
2807
2808 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002809 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002810
Paul Bakker5121ce52009-01-03 21:22:43 +00002811cleanup:
2812
2813 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002814 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002815
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002816 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2817 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002818
2819 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002820 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002821
2822 return( ret );
2823}
2824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002827#endif /* MBEDTLS_BIGNUM_C */