blob: 8d2ad95849a43213899a6107628a461bfff47fa3 [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
Gilles Peskine27c15c72020-01-20 21:17:43 +0100160 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Gilles Peskine56427c22020-01-21 13:59:51 +0100163 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164
165 for( i = X->n - 1; i > 0; i-- )
166 if( X->p[i] != 0 )
167 break;
168 i++;
169
170 if( i < nblimbs )
171 i = nblimbs;
172
Simon Butcher29176892016-05-20 00:19:09 +0100173 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200174 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100176 if( X->p != NULL )
177 {
178 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200179 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100181 }
182
183 X->n = i;
184 X->p = p;
185
186 return( 0 );
187}
188
189/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000190 * Copy the contents of Y into X
191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000193{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100194 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000195 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000196 MPI_VALIDATE_RET( X != NULL );
197 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
199 if( X == Y )
200 return( 0 );
201
Gilles Peskine3e9f5222020-01-20 21:12:50 +0100202 if( Y->n == 0 )
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200205 return( 0 );
206 }
207
Paul Bakker5121ce52009-01-03 21:22:43 +0000208 for( i = Y->n - 1; i > 0; i-- )
209 if( Y->p[i] != 0 )
210 break;
211 i++;
212
213 X->s = Y->s;
214
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100215 if( X->n < i )
216 {
217 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
218 }
219 else
220 {
221 memset( X->p + i, 0, ( X->n - i ) * ciL );
222 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 memcpy( X->p, Y->p, i * ciL );
225
226cleanup:
227
228 return( ret );
229}
230
231/*
232 * Swap the contents of X and Y
233 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000235{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000237 MPI_VALIDATE( X != NULL );
238 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 memcpy( &T, X, sizeof( mbedtls_mpi ) );
241 memcpy( X, Y, sizeof( mbedtls_mpi ) );
242 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000243}
244
245/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100246 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100247 * about whether the assignment was made or not.
248 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100251{
252 int ret = 0;
253 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000254 MPI_VALIDATE_RET( X != NULL );
255 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100256
Pascal Junodb99183d2015-03-11 16:49:45 +0100257 /* make sure assign is 0 or 1 in a time-constant manner */
258 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100261
Paul Bakker66d5d072014-06-17 16:39:18 +0200262 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100263
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100264 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200265 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100266
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100267 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200268 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100269
270cleanup:
271 return( ret );
272}
273
274/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100275 * Conditionally swap X and Y, without leaking information
276 * about whether the swap was made or not.
277 * Here it is not ok to simply swap the pointers, which whould lead to
278 * different memory access patterns when X and Y are used afterwards.
279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100281{
282 int ret, s;
283 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000285 MPI_VALIDATE_RET( X != NULL );
286 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100287
288 if( X == Y )
289 return( 0 );
290
Pascal Junodb99183d2015-03-11 16:49:45 +0100291 /* make sure swap is 0 or 1 in a time-constant manner */
292 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
295 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100296
297 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200298 X->s = X->s * ( 1 - swap ) + Y->s * swap;
299 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100300
301
302 for( i = 0; i < X->n; i++ )
303 {
304 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200305 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
306 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100307 }
308
309cleanup:
310 return( ret );
311}
312
313/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000314 * Set value from integer
315 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000317{
318 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000319 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000322 memset( X->p, 0, X->n * ciL );
323
324 X->p[0] = ( z < 0 ) ? -z : z;
325 X->s = ( z < 0 ) ? -1 : 1;
326
327cleanup:
328
329 return( ret );
330}
331
332/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000333 * Get a specific bit
334 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000336{
Hanno Becker73d7d792018-12-11 10:35:51 +0000337 MPI_VALIDATE_RET( X != NULL );
338
Paul Bakker2f5947e2011-05-18 15:47:11 +0000339 if( X->n * biL <= pos )
340 return( 0 );
341
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200342 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000343}
344
Gilles Peskine11cdb052018-11-20 16:47:47 +0100345/* Get a specific byte, without range checks. */
346#define GET_BYTE( X, i ) \
347 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
348
Paul Bakker2f5947e2011-05-18 15:47:11 +0000349/*
350 * Set a bit to a specific value of 0 or 1
351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000353{
354 int ret = 0;
355 size_t off = pos / biL;
356 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000357 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000358
359 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200361
Paul Bakker2f5947e2011-05-18 15:47:11 +0000362 if( X->n * biL <= pos )
363 {
364 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200365 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000368 }
369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
371 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000372
373cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200374
Paul Bakker2f5947e2011-05-18 15:47:11 +0000375 return( ret );
376}
377
378/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200379 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000380 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000382{
Paul Bakker23986e52011-04-24 08:57:21 +0000383 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000384 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000385
386 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000387 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000388 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
389 return( count );
390
391 return( 0 );
392}
393
394/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000395 * Count leading zero bits in a given integer
396 */
397static size_t mbedtls_clz( const mbedtls_mpi_uint x )
398{
399 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100400 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000401
402 for( j = 0; j < biL; j++ )
403 {
404 if( x & mask ) break;
405
406 mask >>= 1;
407 }
408
409 return j;
410}
411
412/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200413 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000414 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200415size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000416{
Paul Bakker23986e52011-04-24 08:57:21 +0000417 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000418
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200419 if( X->n == 0 )
420 return( 0 );
421
Paul Bakker5121ce52009-01-03 21:22:43 +0000422 for( i = X->n - 1; i > 0; i-- )
423 if( X->p[i] != 0 )
424 break;
425
Simon Butcher15b15d12015-11-26 19:35:03 +0000426 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
Paul Bakker23986e52011-04-24 08:57:21 +0000428 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000429}
430
431/*
432 * Return the total size in bytes
433 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000435{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200436 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000437}
438
439/*
440 * Convert an ASCII character to digit value
441 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000443{
444 *d = 255;
445
446 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
447 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
448 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 if( *d >= (mbedtls_mpi_uint) radix )
451 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452
453 return( 0 );
454}
455
456/*
457 * Import from an ASCII string
458 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000460{
Paul Bakker23986e52011-04-24 08:57:21 +0000461 int ret;
462 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 mbedtls_mpi_uint d;
464 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000465 MPI_VALIDATE_RET( X != NULL );
466 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467
468 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000469 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
Paul Bakkerff60ee62010-03-16 21:09:09 +0000473 slen = strlen( s );
474
Paul Bakker5121ce52009-01-03 21:22:43 +0000475 if( radix == 16 )
476 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100477 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200478 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
479
Paul Bakkerff60ee62010-03-16 21:09:09 +0000480 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
483 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
Paul Bakker23986e52011-04-24 08:57:21 +0000485 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000486 {
Paul Bakker23986e52011-04-24 08:57:21 +0000487 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000488 {
489 X->s = -1;
490 break;
491 }
492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200494 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000495 }
496 }
497 else
498 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
Paul Bakkerff60ee62010-03-16 21:09:09 +0000501 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 {
503 if( i == 0 && s[i] == '-' )
504 {
505 X->s = -1;
506 continue;
507 }
508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
510 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000511
512 if( X->s == 1 )
513 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000515 }
516 else
517 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000519 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000520 }
521 }
522
523cleanup:
524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000526
527 return( ret );
528}
529
530/*
Ron Eldora16fa292018-11-20 14:07:01 +0200531 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 */
Ron Eldora16fa292018-11-20 14:07:01 +0200533static int mpi_write_hlp( mbedtls_mpi *X, int radix,
534 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000535{
536 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200538 size_t length = 0;
539 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000540
Ron Eldora16fa292018-11-20 14:07:01 +0200541 do
542 {
543 if( length >= buflen )
544 {
545 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
546 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
Ron Eldora16fa292018-11-20 14:07:01 +0200548 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
549 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
550 /*
551 * Write the residue in the current position, as an ASCII character.
552 */
553 if( r < 0xA )
554 *(--p_end) = (char)( '0' + r );
555 else
556 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000557
Ron Eldora16fa292018-11-20 14:07:01 +0200558 length++;
559 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000560
Ron Eldora16fa292018-11-20 14:07:01 +0200561 memmove( *p, p_end, length );
562 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
564cleanup:
565
566 return( ret );
567}
568
569/*
570 * Export into an ASCII string
571 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100572int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
573 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000574{
Paul Bakker23986e52011-04-24 08:57:21 +0000575 int ret = 0;
576 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000577 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000579 MPI_VALIDATE_RET( X != NULL );
580 MPI_VALIDATE_RET( olen != NULL );
581 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
583 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000584 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000585
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000586 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
587 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
588 * `n`. If radix > 4, this might be a strict
589 * overapproximation of the number of
590 * radix-adic digits needed to present `n`. */
591 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
592 * present `n`. */
593
Janos Follath870ed002019-03-06 13:43:02 +0000594 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000595 n += 1; /* Compensate for the divisions above, which round down `n`
596 * in case it's not even. */
597 n += 1; /* Potential '-'-sign. */
598 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
599 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000600
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100601 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000602 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100603 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000605 }
606
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100607 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000609
610 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000611 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000612 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000613 buflen--;
614 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000615
616 if( radix == 16 )
617 {
Paul Bakker23986e52011-04-24 08:57:21 +0000618 int c;
619 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000620
Paul Bakker23986e52011-04-24 08:57:21 +0000621 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000622 {
Paul Bakker23986e52011-04-24 08:57:21 +0000623 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000624 {
Paul Bakker23986e52011-04-24 08:57:21 +0000625 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000626
Paul Bakker6c343d72014-07-10 14:36:19 +0200627 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000628 continue;
629
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000630 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000631 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000632 k = 1;
633 }
634 }
635 }
636 else
637 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000639
640 if( T.s == -1 )
641 T.s = 1;
642
Ron Eldora16fa292018-11-20 14:07:01 +0200643 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000644 }
645
646 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100647 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000648
649cleanup:
650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
653 return( ret );
654}
655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000657/*
658 * Read X from an opened file
659 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000661{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000663 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000664 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000665 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000666 * Buffer should have space for (short) label and decimal formatted MPI,
667 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000668 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
Hanno Becker73d7d792018-12-11 10:35:51 +0000671 MPI_VALIDATE_RET( X != NULL );
672 MPI_VALIDATE_RET( fin != NULL );
673
674 if( radix < 2 || radix > 16 )
675 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
676
Paul Bakker5121ce52009-01-03 21:22:43 +0000677 memset( s, 0, sizeof( s ) );
678 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
681 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000682 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000684
Hanno Beckerb2034b72017-04-26 11:46:46 +0100685 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
686 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
688 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100689 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000690 if( mpi_get_digit( &d, radix, *p ) != 0 )
691 break;
692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000694}
695
696/*
697 * Write X into an opened file (or stdout if fout == NULL)
698 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000700{
Paul Bakker23986e52011-04-24 08:57:21 +0000701 int ret;
702 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000703 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000704 * Buffer should have space for (short) label and decimal formatted MPI,
705 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000706 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000708 MPI_VALIDATE_RET( X != NULL );
709
710 if( radix < 2 || radix > 16 )
711 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000712
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100713 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000714
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100715 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
717 if( p == NULL ) p = "";
718
719 plen = strlen( p );
720 slen = strlen( s );
721 s[slen++] = '\r';
722 s[slen++] = '\n';
723
724 if( fout != NULL )
725 {
726 if( fwrite( p, 1, plen, fout ) != plen ||
727 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000729 }
730 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
733cleanup:
734
735 return( ret );
736}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
Hanno Beckerda1655a2017-10-18 14:21:44 +0100739
740/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
741 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000742
743static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
744{
745 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100746 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000747 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100748
749 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
750 {
751 tmp <<= CHAR_BIT;
752 tmp |= (mbedtls_mpi_uint) *x_ptr;
753 }
754
Hanno Beckerf8720072018-11-08 11:53:49 +0000755 return( tmp );
756}
757
758static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
759{
760#if defined(__BYTE_ORDER__)
761
762/* Nothing to do on bigendian systems. */
763#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
764 return( x );
765#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
766
767#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
768
769/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000770#if defined(__GNUC__) && defined(__GNUC_PREREQ)
771#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000772#define have_bswap
773#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000774#endif
775
776#if defined(__clang__) && defined(__has_builtin)
777#if __has_builtin(__builtin_bswap32) && \
778 __has_builtin(__builtin_bswap64)
779#define have_bswap
780#endif
781#endif
782
Hanno Beckerf8720072018-11-08 11:53:49 +0000783#if defined(have_bswap)
784 /* The compiler is hopefully able to statically evaluate this! */
785 switch( sizeof(mbedtls_mpi_uint) )
786 {
787 case 4:
788 return( __builtin_bswap32(x) );
789 case 8:
790 return( __builtin_bswap64(x) );
791 }
792#endif
793#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
794#endif /* __BYTE_ORDER__ */
795
796 /* Fall back to C-based reordering if we don't know the byte order
797 * or we couldn't use a compiler-specific builtin. */
798 return( mpi_uint_bigendian_to_host_c( x ) );
799}
800
Hanno Becker2be8a552018-10-25 12:40:09 +0100801static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100802{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100803 mbedtls_mpi_uint *cur_limb_left;
804 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100805 if( limbs == 0 )
806 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100807
808 /*
809 * Traverse limbs and
810 * - adapt byte-order in each limb
811 * - swap the limbs themselves.
812 * For that, simultaneously traverse the limbs from left to right
813 * and from right to left, as long as the left index is not bigger
814 * than the right index (it's not a problem if limbs is odd and the
815 * indices coincide in the last iteration).
816 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100817 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
818 cur_limb_left <= cur_limb_right;
819 cur_limb_left++, cur_limb_right-- )
820 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000821 mbedtls_mpi_uint tmp;
822 /* Note that if cur_limb_left == cur_limb_right,
823 * this code effectively swaps the bytes only once. */
824 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
825 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
826 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100827 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100828}
829
Paul Bakker5121ce52009-01-03 21:22:43 +0000830/*
831 * Import X from unsigned binary data, big endian
832 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000834{
Paul Bakker23986e52011-04-24 08:57:21 +0000835 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100836 size_t const limbs = CHARS_TO_LIMBS( buflen );
837 size_t const overhead = ( limbs * ciL ) - buflen;
838 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000839
Hanno Becker8ce11a32018-12-19 16:18:52 +0000840 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000841 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
842
Hanno Becker073c1992017-10-17 15:17:27 +0100843 /* Ensure that target MPI has exactly the necessary number of limbs */
844 if( X->n != limbs )
845 {
846 mbedtls_mpi_free( X );
847 mbedtls_mpi_init( X );
848 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
849 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000851
Hanno Becker0e810b92019-01-03 17:13:11 +0000852 /* Avoid calling `memcpy` with NULL source argument,
853 * even if buflen is 0. */
854 if( buf != NULL )
855 {
856 Xp = (unsigned char*) X->p;
857 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100858
Hanno Becker0e810b92019-01-03 17:13:11 +0000859 mpi_bigendian_to_host( X->p, limbs );
860 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000861
862cleanup:
863
864 return( ret );
865}
866
867/*
868 * Export X into unsigned binary data, big endian
869 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100870int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
871 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000872{
Hanno Becker73d7d792018-12-11 10:35:51 +0000873 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100874 size_t bytes_to_copy;
875 unsigned char *p;
876 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000877
Hanno Becker73d7d792018-12-11 10:35:51 +0000878 MPI_VALIDATE_RET( X != NULL );
879 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
880
881 stored_bytes = X->n * ciL;
882
Gilles Peskine11cdb052018-11-20 16:47:47 +0100883 if( stored_bytes < buflen )
884 {
885 /* There is enough space in the output buffer. Write initial
886 * null bytes and record the position at which to start
887 * writing the significant bytes. In this case, the execution
888 * trace of this function does not depend on the value of the
889 * number. */
890 bytes_to_copy = stored_bytes;
891 p = buf + buflen - stored_bytes;
892 memset( buf, 0, buflen - stored_bytes );
893 }
894 else
895 {
896 /* The output buffer is smaller than the allocated size of X.
897 * However X may fit if its leading bytes are zero. */
898 bytes_to_copy = buflen;
899 p = buf;
900 for( i = bytes_to_copy; i < stored_bytes; i++ )
901 {
902 if( GET_BYTE( X, i ) != 0 )
903 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
904 }
905 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
Gilles Peskine11cdb052018-11-20 16:47:47 +0100907 for( i = 0; i < bytes_to_copy; i++ )
908 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000909
910 return( 0 );
911}
912
913/*
914 * Left-shift: X <<= count
915 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000917{
Paul Bakker23986e52011-04-24 08:57:21 +0000918 int ret;
919 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000921 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000922
923 v0 = count / (biL );
924 t1 = count & (biL - 1);
925
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200926 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000927
Paul Bakkerf9688572011-05-05 10:00:45 +0000928 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000930
931 ret = 0;
932
933 /*
934 * shift by count / limb_size
935 */
936 if( v0 > 0 )
937 {
Paul Bakker23986e52011-04-24 08:57:21 +0000938 for( i = X->n; i > v0; i-- )
939 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000940
Paul Bakker23986e52011-04-24 08:57:21 +0000941 for( ; i > 0; i-- )
942 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000943 }
944
945 /*
946 * shift by count % limb_size
947 */
948 if( t1 > 0 )
949 {
950 for( i = v0; i < X->n; i++ )
951 {
952 r1 = X->p[i] >> (biL - t1);
953 X->p[i] <<= t1;
954 X->p[i] |= r0;
955 r0 = r1;
956 }
957 }
958
959cleanup:
960
961 return( ret );
962}
963
964/*
965 * Right-shift: X >>= count
966 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200967int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000968{
Paul Bakker23986e52011-04-24 08:57:21 +0000969 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000971 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000972
973 v0 = count / biL;
974 v1 = count & (biL - 1);
975
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100976 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100978
Paul Bakker5121ce52009-01-03 21:22:43 +0000979 /*
980 * shift by count / limb_size
981 */
982 if( v0 > 0 )
983 {
984 for( i = 0; i < X->n - v0; i++ )
985 X->p[i] = X->p[i + v0];
986
987 for( ; i < X->n; i++ )
988 X->p[i] = 0;
989 }
990
991 /*
992 * shift by count % limb_size
993 */
994 if( v1 > 0 )
995 {
Paul Bakker23986e52011-04-24 08:57:21 +0000996 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000997 {
Paul Bakker23986e52011-04-24 08:57:21 +0000998 r1 = X->p[i - 1] << (biL - v1);
999 X->p[i - 1] >>= v1;
1000 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001001 r0 = r1;
1002 }
1003 }
1004
1005 return( 0 );
1006}
1007
1008/*
1009 * Compare unsigned values
1010 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001012{
Paul Bakker23986e52011-04-24 08:57:21 +00001013 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001014 MPI_VALIDATE_RET( X != NULL );
1015 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001016
Paul Bakker23986e52011-04-24 08:57:21 +00001017 for( i = X->n; i > 0; i-- )
1018 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001019 break;
1020
Paul Bakker23986e52011-04-24 08:57:21 +00001021 for( j = Y->n; j > 0; j-- )
1022 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 break;
1024
Paul Bakker23986e52011-04-24 08:57:21 +00001025 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001026 return( 0 );
1027
1028 if( i > j ) return( 1 );
1029 if( j > i ) return( -1 );
1030
Paul Bakker23986e52011-04-24 08:57:21 +00001031 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001032 {
Paul Bakker23986e52011-04-24 08:57:21 +00001033 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1034 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001035 }
1036
1037 return( 0 );
1038}
1039
1040/*
1041 * Compare signed values
1042 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001043int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001044{
Paul Bakker23986e52011-04-24 08:57:21 +00001045 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001046 MPI_VALIDATE_RET( X != NULL );
1047 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001048
Paul Bakker23986e52011-04-24 08:57:21 +00001049 for( i = X->n; i > 0; i-- )
1050 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 break;
1052
Paul Bakker23986e52011-04-24 08:57:21 +00001053 for( j = Y->n; j > 0; j-- )
1054 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001055 break;
1056
Paul Bakker23986e52011-04-24 08:57:21 +00001057 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001058 return( 0 );
1059
1060 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001061 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001062
1063 if( X->s > 0 && Y->s < 0 ) return( 1 );
1064 if( Y->s > 0 && X->s < 0 ) return( -1 );
1065
Paul Bakker23986e52011-04-24 08:57:21 +00001066 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001067 {
Paul Bakker23986e52011-04-24 08:57:21 +00001068 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1069 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001070 }
1071
1072 return( 0 );
1073}
1074
Janos Follath45ec9902019-10-14 09:09:32 +01001075/** Decide if an integer is less than the other, without branches.
1076 *
1077 * \param x First integer.
1078 * \param y Second integer.
1079 *
1080 * \return 1 if \p x is less than \p y, 0 otherwise
1081 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001082static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1083 const mbedtls_mpi_uint y )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001084{
1085 mbedtls_mpi_uint ret;
1086 mbedtls_mpi_uint cond;
1087
1088 /*
1089 * Check if the most significant bits (MSB) of the operands are different.
1090 */
1091 cond = ( x ^ y );
1092 /*
1093 * If the MSB are the same then the difference x-y will be negative (and
1094 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1095 */
1096 ret = ( x - y ) & ~cond;
1097 /*
1098 * If the MSB are different, then the operand with the MSB of 1 is the
1099 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1100 * the MSB of y is 0.)
1101 */
1102 ret |= y & cond;
1103
1104
Janos Follath7a34bcf2019-10-14 08:59:14 +01001105 ret = ret >> ( biL - 1 );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001106
Janos Follath359a01e2019-10-29 15:08:46 +00001107 return (unsigned) ret;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001108}
1109
1110/*
1111 * Compare signed values in constant time
1112 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001113int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1114 unsigned *ret )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001115{
1116 size_t i;
Janos Follathbd87a592019-10-28 12:23:18 +00001117 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001118 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001119
1120 MPI_VALIDATE_RET( X != NULL );
1121 MPI_VALIDATE_RET( Y != NULL );
1122 MPI_VALIDATE_RET( ret != NULL );
1123
1124 if( X->n != Y->n )
1125 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1126
1127 /*
Janos Follath58525182019-10-28 12:12:15 +00001128 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1129 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001130 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001131 X_is_negative = ( X->s & 2 ) >> 1;
1132 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath867a3ab2019-10-11 14:21:53 +01001133
1134 /*
1135 * If the signs are different, then the positive operand is the bigger.
Janos Follath1f21c1d2019-10-28 12:31:34 +00001136 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1137 * is false if X is positive (X_is_negative == 0).
Janos Follath867a3ab2019-10-11 14:21:53 +01001138 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001139 cond = ( X_is_negative ^ Y_is_negative );
1140 *ret = cond & X_is_negative;
Janos Follath867a3ab2019-10-11 14:21:53 +01001141
1142 /*
Janos Follathbd87a592019-10-28 12:23:18 +00001143 * This is a constant-time function. We might have the result, but we still
Janos Follath867a3ab2019-10-11 14:21:53 +01001144 * need to go through the loop. Record if we have the result already.
1145 */
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001146 done = cond;
1147
1148 for( i = X->n; i > 0; i-- )
1149 {
1150 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001151 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1152 * X and Y are negative.
Janos Follath867a3ab2019-10-11 14:21:53 +01001153 *
1154 * Again even if we can make a decision, we just mark the result and
1155 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001156 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001157 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1158 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathfbe4c942019-10-28 12:37:21 +00001159 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001160
1161 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001162 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1163 * X and Y are positive.
Janos Follath867a3ab2019-10-11 14:21:53 +01001164 *
1165 * Again even if we can make a decision, we just mark the result and
1166 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001167 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001168 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1169 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathfbe4c942019-10-28 12:37:21 +00001170 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001171 }
1172
1173 return( 0 );
1174}
1175
Paul Bakker5121ce52009-01-03 21:22:43 +00001176/*
1177 * Compare signed values
1178 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001180{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001181 mbedtls_mpi Y;
1182 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001183 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001184
1185 *p = ( z < 0 ) ? -z : z;
1186 Y.s = ( z < 0 ) ? -1 : 1;
1187 Y.n = 1;
1188 Y.p = p;
1189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001191}
1192
1193/*
1194 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001197{
Paul Bakker23986e52011-04-24 08:57:21 +00001198 int ret;
1199 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001200 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001201 MPI_VALIDATE_RET( X != NULL );
1202 MPI_VALIDATE_RET( A != NULL );
1203 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001204
1205 if( X == B )
1206 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001208 }
1209
1210 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001212
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001213 /*
1214 * X should always be positive as a result of unsigned additions.
1215 */
1216 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001217
Paul Bakker23986e52011-04-24 08:57:21 +00001218 for( j = B->n; j > 0; j-- )
1219 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001220 break;
1221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001223
1224 o = B->p; p = X->p; c = 0;
1225
Janos Follath6c922682015-10-30 17:43:11 +01001226 /*
1227 * tmp is used because it might happen that p == o
1228 */
Paul Bakker23986e52011-04-24 08:57:21 +00001229 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001230 {
Janos Follath6c922682015-10-30 17:43:11 +01001231 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001232 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001233 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001234 }
1235
1236 while( c != 0 )
1237 {
1238 if( i >= X->n )
1239 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001241 p = X->p + i;
1242 }
1243
Paul Bakker2d319fd2012-09-16 21:34:26 +00001244 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001245 }
1246
1247cleanup:
1248
1249 return( ret );
1250}
1251
1252/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001254 */
Gilles Peskinee9073a62020-06-04 15:01:32 +02001255static void mpi_sub_hlp( size_t n,
1256 const mbedtls_mpi_uint *s,
1257 mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001258{
Paul Bakker23986e52011-04-24 08:57:21 +00001259 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001261
1262 for( i = c = 0; i < n; i++, s++, d++ )
1263 {
1264 z = ( *d < c ); *d -= c;
1265 c = ( *d < *s ) + z; *d -= *s;
1266 }
1267
1268 while( c != 0 )
1269 {
1270 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001271 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001272 }
1273}
1274
1275/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001276 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001279{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001281 int ret;
1282 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001283 MPI_VALIDATE_RET( X != NULL );
1284 MPI_VALIDATE_RET( A != NULL );
1285 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001287 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1288 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001291
1292 if( X == B )
1293 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001295 B = &TB;
1296 }
1297
1298 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001300
Paul Bakker1ef7a532009-06-20 10:50:55 +00001301 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001302 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001303 */
1304 X->s = 1;
1305
Paul Bakker5121ce52009-01-03 21:22:43 +00001306 ret = 0;
1307
Paul Bakker23986e52011-04-24 08:57:21 +00001308 for( n = B->n; n > 0; n-- )
1309 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001310 break;
1311
Paul Bakker23986e52011-04-24 08:57:21 +00001312 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001313
1314cleanup:
1315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001316 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001317
1318 return( ret );
1319}
1320
1321/*
1322 * Signed addition: X = A + B
1323 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001325{
Hanno Becker73d7d792018-12-11 10:35:51 +00001326 int ret, s;
1327 MPI_VALIDATE_RET( X != NULL );
1328 MPI_VALIDATE_RET( A != NULL );
1329 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001330
Hanno Becker73d7d792018-12-11 10:35:51 +00001331 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 if( A->s * B->s < 0 )
1333 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 X->s = s;
1338 }
1339 else
1340 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001342 X->s = -s;
1343 }
1344 }
1345 else
1346 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001348 X->s = s;
1349 }
1350
1351cleanup:
1352
1353 return( ret );
1354}
1355
1356/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001357 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001360{
Hanno Becker73d7d792018-12-11 10:35:51 +00001361 int ret, s;
1362 MPI_VALIDATE_RET( X != NULL );
1363 MPI_VALIDATE_RET( A != NULL );
1364 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001365
Hanno Becker73d7d792018-12-11 10:35:51 +00001366 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 if( A->s * B->s > 0 )
1368 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001370 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001372 X->s = s;
1373 }
1374 else
1375 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001377 X->s = -s;
1378 }
1379 }
1380 else
1381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001383 X->s = s;
1384 }
1385
1386cleanup:
1387
1388 return( ret );
1389}
1390
1391/*
1392 * Signed addition: X = A + b
1393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001395{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 mbedtls_mpi _B;
1397 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001398 MPI_VALIDATE_RET( X != NULL );
1399 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001400
1401 p[0] = ( b < 0 ) ? -b : b;
1402 _B.s = ( b < 0 ) ? -1 : 1;
1403 _B.n = 1;
1404 _B.p = p;
1405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001407}
1408
1409/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001410 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001411 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001413{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 mbedtls_mpi _B;
1415 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001416 MPI_VALIDATE_RET( X != NULL );
1417 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001418
1419 p[0] = ( b < 0 ) ? -b : b;
1420 _B.s = ( b < 0 ) ? -1 : 1;
1421 _B.n = 1;
1422 _B.p = p;
1423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001425}
1426
1427/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001429 */
1430static
1431#if defined(__APPLE__) && defined(__arm__)
1432/*
1433 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1434 * appears to need this to prevent bad ARM code generation at -O3.
1435 */
1436__attribute__ ((noinline))
1437#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438void 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 +00001439{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001441
1442#if defined(MULADDC_HUIT)
1443 for( ; i >= 8; i -= 8 )
1444 {
1445 MULADDC_INIT
1446 MULADDC_HUIT
1447 MULADDC_STOP
1448 }
1449
1450 for( ; i > 0; i-- )
1451 {
1452 MULADDC_INIT
1453 MULADDC_CORE
1454 MULADDC_STOP
1455 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001456#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001457 for( ; i >= 16; i -= 16 )
1458 {
1459 MULADDC_INIT
1460 MULADDC_CORE MULADDC_CORE
1461 MULADDC_CORE MULADDC_CORE
1462 MULADDC_CORE MULADDC_CORE
1463 MULADDC_CORE MULADDC_CORE
1464
1465 MULADDC_CORE MULADDC_CORE
1466 MULADDC_CORE MULADDC_CORE
1467 MULADDC_CORE MULADDC_CORE
1468 MULADDC_CORE MULADDC_CORE
1469 MULADDC_STOP
1470 }
1471
1472 for( ; i >= 8; i -= 8 )
1473 {
1474 MULADDC_INIT
1475 MULADDC_CORE MULADDC_CORE
1476 MULADDC_CORE MULADDC_CORE
1477
1478 MULADDC_CORE MULADDC_CORE
1479 MULADDC_CORE MULADDC_CORE
1480 MULADDC_STOP
1481 }
1482
1483 for( ; i > 0; i-- )
1484 {
1485 MULADDC_INIT
1486 MULADDC_CORE
1487 MULADDC_STOP
1488 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001489#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001490
1491 t++;
1492
1493 do {
1494 *d += c; c = ( *d < c ); d++;
1495 }
1496 while( c != 0 );
1497}
1498
1499/*
1500 * Baseline multiplication: X = A * B (HAC 14.12)
1501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001503{
Paul Bakker23986e52011-04-24 08:57:21 +00001504 int ret;
1505 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001507 MPI_VALIDATE_RET( X != NULL );
1508 MPI_VALIDATE_RET( A != NULL );
1509 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1514 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001515
Paul Bakker23986e52011-04-24 08:57:21 +00001516 for( i = A->n; i > 0; i-- )
1517 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 break;
1519
Paul Bakker23986e52011-04-24 08:57:21 +00001520 for( j = B->n; j > 0; j-- )
1521 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001522 break;
1523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1525 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001527 for( ; j > 0; j-- )
1528 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001529
1530 X->s = A->s * B->s;
1531
1532cleanup:
1533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001535
1536 return( ret );
1537}
1538
1539/*
1540 * Baseline multiplication: X = A * b
1541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001543{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 mbedtls_mpi _B;
1545 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001546 MPI_VALIDATE_RET( X != NULL );
1547 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001548
1549 _B.s = 1;
1550 _B.n = 1;
1551 _B.p = p;
1552 p[0] = b;
1553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001555}
1556
1557/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001558 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1559 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001560 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001561static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1562 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001563{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001564#if defined(MBEDTLS_HAVE_UDBL)
1565 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001566#else
Simon Butcher9803d072016-01-03 00:24:34 +00001567 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1568 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001569 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1570 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001571 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001572#endif
1573
Simon Butcher15b15d12015-11-26 19:35:03 +00001574 /*
1575 * Check for overflow
1576 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001577 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001578 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001579 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001580
Simon Butcherf5ba0452015-12-27 23:01:55 +00001581 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001582 }
1583
1584#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001585 dividend = (mbedtls_t_udbl) u1 << biL;
1586 dividend |= (mbedtls_t_udbl) u0;
1587 quotient = dividend / d;
1588 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1589 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1590
1591 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001592 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001593
1594 return (mbedtls_mpi_uint) quotient;
1595#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001596
1597 /*
1598 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1599 * Vol. 2 - Seminumerical Algorithms, Knuth
1600 */
1601
1602 /*
1603 * Normalize the divisor, d, and dividend, u0, u1
1604 */
1605 s = mbedtls_clz( d );
1606 d = d << s;
1607
1608 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001609 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001610 u0 = u0 << s;
1611
1612 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001613 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001614
1615 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001616 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001617
1618 /*
1619 * Find the first quotient and remainder
1620 */
1621 q1 = u1 / d1;
1622 r0 = u1 - d1 * q1;
1623
1624 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1625 {
1626 q1 -= 1;
1627 r0 += d1;
1628
1629 if ( r0 >= radix ) break;
1630 }
1631
Simon Butcherf5ba0452015-12-27 23:01:55 +00001632 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001633 q0 = rAX / d1;
1634 r0 = rAX - q0 * d1;
1635
1636 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1637 {
1638 q0 -= 1;
1639 r0 += d1;
1640
1641 if ( r0 >= radix ) break;
1642 }
1643
1644 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001645 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001646
1647 quotient = q1 * radix + q0;
1648
1649 return quotient;
1650#endif
1651}
1652
1653/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001655 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001656int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1657 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001658{
Paul Bakker23986e52011-04-24 08:57:21 +00001659 int ret;
1660 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001662 MPI_VALIDATE_RET( A != NULL );
1663 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1666 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1669 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001670
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001672 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001673 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1674 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001675 return( 0 );
1676 }
1677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1679 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001680 X.s = Y.s = 1;
1681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1683 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1684 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1685 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001687 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001688 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 {
1690 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1692 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001693 }
1694 else k = 0;
1695
1696 n = X.n - 1;
1697 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001698 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001701 {
1702 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001703 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001706
1707 for( i = n; i > t ; i-- )
1708 {
1709 if( X.p[i] >= Y.p[t] )
1710 Z.p[i - t - 1] = ~0;
1711 else
1712 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001713 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1714 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001715 }
1716
1717 Z.p[i - t - 1]++;
1718 do
1719 {
1720 Z.p[i - t - 1]--;
1721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001723 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001724 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001728 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1729 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001730 T2.p[2] = X.p[i];
1731 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001732 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1735 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1736 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001739 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001740 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1741 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1742 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001743 Z.p[i - t - 1]--;
1744 }
1745 }
1746
1747 if( Q != NULL )
1748 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001750 Q->s = A->s * B->s;
1751 }
1752
1753 if( R != NULL )
1754 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001756 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 R->s = 1;
1761 }
1762
1763cleanup:
1764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1766 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001767
1768 return( ret );
1769}
1770
1771/*
1772 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001773 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001774int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1775 const mbedtls_mpi *A,
1776 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001777{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778 mbedtls_mpi _B;
1779 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001780 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001781
1782 p[0] = ( b < 0 ) ? -b : b;
1783 _B.s = ( b < 0 ) ? -1 : 1;
1784 _B.n = 1;
1785 _B.p = p;
1786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001788}
1789
1790/*
1791 * Modulo: R = A mod B
1792 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001794{
1795 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001796 MPI_VALIDATE_RET( R != NULL );
1797 MPI_VALIDATE_RET( A != NULL );
1798 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1801 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1806 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1809 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001810
1811cleanup:
1812
1813 return( ret );
1814}
1815
1816/*
1817 * Modulo: r = A mod b
1818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001820{
Paul Bakker23986e52011-04-24 08:57:21 +00001821 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001823 MPI_VALIDATE_RET( r != NULL );
1824 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001825
1826 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
1829 if( b < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001831
1832 /*
1833 * handle trivial cases
1834 */
1835 if( b == 1 )
1836 {
1837 *r = 0;
1838 return( 0 );
1839 }
1840
1841 if( b == 2 )
1842 {
1843 *r = A->p[0] & 1;
1844 return( 0 );
1845 }
1846
1847 /*
1848 * general case
1849 */
Paul Bakker23986e52011-04-24 08:57:21 +00001850 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 {
Paul Bakker23986e52011-04-24 08:57:21 +00001852 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001853 y = ( y << biH ) | ( x >> biH );
1854 z = y / b;
1855 y -= z * b;
1856
1857 x <<= biH;
1858 y = ( y << biH ) | ( x >> biH );
1859 z = y / b;
1860 y -= z * b;
1861 }
1862
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001863 /*
1864 * If A is negative, then the current y represents a negative value.
1865 * Flipping it to the positive side.
1866 */
1867 if( A->s < 0 && y != 0 )
1868 y = b - y;
1869
Paul Bakker5121ce52009-01-03 21:22:43 +00001870 *r = y;
1871
1872 return( 0 );
1873}
1874
1875/*
1876 * Fast Montgomery initialization (thanks to Tom St Denis)
1877 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001879{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001881 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
1883 x = m0;
1884 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001886 for( i = biL; i >= 8; i /= 2 )
1887 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001888
1889 *mm = ~x + 1;
1890}
1891
1892/*
1893 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1894 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001895static 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 +02001896 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001897{
Paul Bakker23986e52011-04-24 08:57:21 +00001898 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001899 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001900
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001901 if( T->n < N->n + 1 || T->p == NULL )
1902 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1903
Paul Bakker5121ce52009-01-03 21:22:43 +00001904 memset( T->p, 0, T->n * ciL );
1905
1906 d = T->p;
1907 n = N->n;
1908 m = ( B->n < n ) ? B->n : n;
1909
1910 for( i = 0; i < n; i++ )
1911 {
1912 /*
1913 * T = (T + u0*B + u1*N) / 2^biL
1914 */
1915 u0 = A->p[i];
1916 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1917
1918 mpi_mul_hlp( m, B->p, d, u0 );
1919 mpi_mul_hlp( n, N->p, d, u1 );
1920
1921 *d++ = u0; d[n + 1] = 0;
1922 }
1923
Paul Bakker66d5d072014-06-17 16:39:18 +02001924 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001925
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001926 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001927 mpi_sub_hlp( n, N->p, A->p );
1928 else
1929 /* prevent timing attacks */
1930 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001931
1932 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001933}
1934
1935/*
1936 * Montgomery reduction: A = A * R^-1 mod N
1937 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001938static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1939 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001940{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 mbedtls_mpi_uint z = 1;
1942 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001943
Paul Bakker8ddb6452013-02-27 14:56:33 +01001944 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001945 U.p = &z;
1946
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001947 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001948}
1949
1950/*
1951 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1952 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001953int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1954 const mbedtls_mpi *E, const mbedtls_mpi *N,
1955 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001956{
Paul Bakker23986e52011-04-24 08:57:21 +00001957 int ret;
1958 size_t wbits, wsize, one = 1;
1959 size_t i, j, nblimbs;
1960 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961 mbedtls_mpi_uint ei, mm, state;
1962 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001963 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001964
Hanno Becker73d7d792018-12-11 10:35:51 +00001965 MPI_VALIDATE_RET( X != NULL );
1966 MPI_VALIDATE_RET( A != NULL );
1967 MPI_VALIDATE_RET( E != NULL );
1968 MPI_VALIDATE_RET( N != NULL );
1969
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001970 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001973 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1974 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001975
1976 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001977 * Init temps and window size
1978 */
1979 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1981 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982 memset( W, 0, sizeof( W ) );
1983
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001984 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001985
1986 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1987 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1988
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001989#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1991 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001992#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001993
Paul Bakker5121ce52009-01-03 21:22:43 +00001994 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1996 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1997 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001998
1999 /*
Paul Bakker50546922012-05-19 08:40:49 +00002000 * Compensate for negative A (and correct at the end)
2001 */
2002 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002003 if( neg )
2004 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002006 Apos.s = 1;
2007 A = &Apos;
2008 }
2009
2010 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002011 * If 1st call, pre-compute R^2 mod N
2012 */
2013 if( _RR == NULL || _RR->p == NULL )
2014 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2016 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2017 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
2019 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002021 }
2022 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002024
2025 /*
2026 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2027 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2029 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002030 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002032
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002033 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002034
2035 /*
2036 * X = R^2 * R^-1 mod N = R mod N
2037 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002038 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002039 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002040
2041 if( wsize > 1 )
2042 {
2043 /*
2044 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2045 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002046 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2049 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002050
2051 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002052 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002053
Paul Bakker5121ce52009-01-03 21:22:43 +00002054 /*
2055 * W[i] = W[i - 1] * W[1]
2056 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002057 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002058 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2060 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002061
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002062 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002063 }
2064 }
2065
2066 nblimbs = E->n;
2067 bufsize = 0;
2068 nbits = 0;
2069 wbits = 0;
2070 state = 0;
2071
2072 while( 1 )
2073 {
2074 if( bufsize == 0 )
2075 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002076 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002077 break;
2078
Paul Bakker0d7702c2013-10-29 16:18:35 +01002079 nblimbs--;
2080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002082 }
2083
2084 bufsize--;
2085
2086 ei = (E->p[nblimbs] >> bufsize) & 1;
2087
2088 /*
2089 * skip leading 0s
2090 */
2091 if( ei == 0 && state == 0 )
2092 continue;
2093
2094 if( ei == 0 && state == 1 )
2095 {
2096 /*
2097 * out of window, square X
2098 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002099 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002100 continue;
2101 }
2102
2103 /*
2104 * add ei to current window
2105 */
2106 state = 2;
2107
2108 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002109 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002110
2111 if( nbits == wsize )
2112 {
2113 /*
2114 * X = X^wsize R^-1 mod N
2115 */
2116 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002117 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002118
2119 /*
2120 * X = X * W[wbits] R^-1 mod N
2121 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002122 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002123
2124 state--;
2125 nbits = 0;
2126 wbits = 0;
2127 }
2128 }
2129
2130 /*
2131 * process the remaining bits
2132 */
2133 for( i = 0; i < nbits; i++ )
2134 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002135 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002136
2137 wbits <<= 1;
2138
Paul Bakker66d5d072014-06-17 16:39:18 +02002139 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002140 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002141 }
2142
2143 /*
2144 * X = A^E * R * R^-1 mod N = A^E mod N
2145 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002146 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002147
Hanno Beckera4af1c42017-04-18 09:07:45 +01002148 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002149 {
2150 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002152 }
2153
Paul Bakker5121ce52009-01-03 21:22:43 +00002154cleanup:
2155
Paul Bakker66d5d072014-06-17 16:39:18 +02002156 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002160
Paul Bakker75a28602014-03-31 12:08:17 +02002161 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002163
2164 return( ret );
2165}
2166
Paul Bakker5121ce52009-01-03 21:22:43 +00002167/*
2168 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2169 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002171{
Paul Bakker23986e52011-04-24 08:57:21 +00002172 int ret;
2173 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002174 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002175
Hanno Becker73d7d792018-12-11 10:35:51 +00002176 MPI_VALIDATE_RET( G != NULL );
2177 MPI_VALIDATE_RET( A != NULL );
2178 MPI_VALIDATE_RET( B != NULL );
2179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002180 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2183 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002185 lz = mbedtls_mpi_lsb( &TA );
2186 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002187
Paul Bakker66d5d072014-06-17 16:39:18 +02002188 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002189 lz = lzt;
2190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002191 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2192 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002193
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 TA.s = TB.s = 1;
2195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2199 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2204 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002205 }
2206 else
2207 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002208 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2209 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002210 }
2211 }
2212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2214 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002215
2216cleanup:
2217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002218 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002219
2220 return( ret );
2221}
2222
Paul Bakker33dc46b2014-04-30 16:11:39 +02002223/*
2224 * Fill X with size bytes of random.
2225 *
2226 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002227 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002228 * deterministic, eg for tests).
2229 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002231 int (*f_rng)(void *, unsigned char *, size_t),
2232 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002233{
Paul Bakker23986e52011-04-24 08:57:21 +00002234 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002235 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002236 size_t const overhead = ( limbs * ciL ) - size;
2237 unsigned char *Xp;
2238
Hanno Becker8ce11a32018-12-19 16:18:52 +00002239 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002240 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002241
Hanno Beckerda1655a2017-10-18 14:21:44 +01002242 /* Ensure that target MPI has exactly the necessary number of limbs */
2243 if( X->n != limbs )
2244 {
2245 mbedtls_mpi_free( X );
2246 mbedtls_mpi_init( X );
2247 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2248 }
2249 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002250
Hanno Beckerda1655a2017-10-18 14:21:44 +01002251 Xp = (unsigned char*) X->p;
2252 f_rng( p_rng, Xp + overhead, size );
2253
Hanno Becker2be8a552018-10-25 12:40:09 +01002254 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002255
2256cleanup:
2257 return( ret );
2258}
2259
Paul Bakker5121ce52009-01-03 21:22:43 +00002260/*
2261 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2262 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002264{
2265 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002266 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002267 MPI_VALIDATE_RET( X != NULL );
2268 MPI_VALIDATE_RET( A != NULL );
2269 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002270
Hanno Becker4bcb4912017-04-18 15:49:39 +01002271 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2275 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2276 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002280 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002283 goto cleanup;
2284 }
2285
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2287 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2288 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2289 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002291 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2292 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2293 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2294 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002295
2296 do
2297 {
2298 while( ( TU.p[0] & 1 ) == 0 )
2299 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002301
2302 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2303 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2305 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002306 }
2307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002308 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2309 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002310 }
2311
2312 while( ( TV.p[0] & 1 ) == 0 )
2313 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002314 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002315
2316 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2317 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002318 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2319 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002320 }
2321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2323 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 }
2325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002326 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002327 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2329 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002331 }
2332 else
2333 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2335 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2336 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337 }
2338 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2342 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2345 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002348
2349cleanup:
2350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2352 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2353 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002354
2355 return( ret );
2356}
2357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002359
Paul Bakker5121ce52009-01-03 21:22:43 +00002360static const int small_prime[] =
2361{
2362 3, 5, 7, 11, 13, 17, 19, 23,
2363 29, 31, 37, 41, 43, 47, 53, 59,
2364 61, 67, 71, 73, 79, 83, 89, 97,
2365 101, 103, 107, 109, 113, 127, 131, 137,
2366 139, 149, 151, 157, 163, 167, 173, 179,
2367 181, 191, 193, 197, 199, 211, 223, 227,
2368 229, 233, 239, 241, 251, 257, 263, 269,
2369 271, 277, 281, 283, 293, 307, 311, 313,
2370 317, 331, 337, 347, 349, 353, 359, 367,
2371 373, 379, 383, 389, 397, 401, 409, 419,
2372 421, 431, 433, 439, 443, 449, 457, 461,
2373 463, 467, 479, 487, 491, 499, 503, 509,
2374 521, 523, 541, 547, 557, 563, 569, 571,
2375 577, 587, 593, 599, 601, 607, 613, 617,
2376 619, 631, 641, 643, 647, 653, 659, 661,
2377 673, 677, 683, 691, 701, 709, 719, 727,
2378 733, 739, 743, 751, 757, 761, 769, 773,
2379 787, 797, 809, 811, 821, 823, 827, 829,
2380 839, 853, 857, 859, 863, 877, 881, 883,
2381 887, 907, 911, 919, 929, 937, 941, 947,
2382 953, 967, 971, 977, 983, 991, 997, -103
2383};
2384
2385/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002386 * Small divisors test (X must be positive)
2387 *
2388 * Return values:
2389 * 0: no small factor (possible prime, more tests needed)
2390 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002392 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002394static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002395{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002396 int ret = 0;
2397 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
Paul Bakker5121ce52009-01-03 21:22:43 +00002400 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002402
2403 for( i = 0; small_prime[i] > 0; i++ )
2404 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002406 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002409
2410 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002411 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002412 }
2413
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002414cleanup:
2415 return( ret );
2416}
2417
2418/*
2419 * Miller-Rabin pseudo-primality test (HAC 4.24)
2420 */
Janos Follathda31fa12018-09-03 14:45:23 +01002421static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002422 int (*f_rng)(void *, unsigned char *, size_t),
2423 void *p_rng )
2424{
Pascal Junodb99183d2015-03-11 16:49:45 +01002425 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002426 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002428
Hanno Becker8ce11a32018-12-19 16:18:52 +00002429 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002430 MPI_VALIDATE_RET( f_rng != NULL );
2431
2432 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2433 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002434 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002435
Paul Bakker5121ce52009-01-03 21:22:43 +00002436 /*
2437 * W = |X| - 1
2438 * R = W >> lsb( W )
2439 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2441 s = mbedtls_mpi_lsb( &W );
2442 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2443 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002444
Janos Follathda31fa12018-09-03 14:45:23 +01002445 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002446 {
2447 /*
2448 * pick a random A, 1 < A < |X| - 1
2449 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002450 count = 0;
2451 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002452 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002453
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002454 j = mbedtls_mpi_bitlen( &A );
2455 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002456 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002457 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002458 }
2459
2460 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002461 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2462 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002463 }
2464
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002465 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2466 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002467
2468 /*
2469 * A = A^R mod |X|
2470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2474 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002475 continue;
2476
2477 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002478 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002479 {
2480 /*
2481 * A = A * A mod |X|
2482 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2484 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002487 break;
2488
2489 j++;
2490 }
2491
2492 /*
2493 * not prime if A != |X| - 1 or A == 1
2494 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2496 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002498 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002499 break;
2500 }
2501 }
2502
2503cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002504 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2505 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002507
2508 return( ret );
2509}
2510
2511/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002512 * Pseudo-primality test: small factors, then Miller-Rabin
2513 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002514int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2515 int (*f_rng)(void *, unsigned char *, size_t),
2516 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002517{
2518 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002519 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002520 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002521 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002522
2523 XX.s = 1;
2524 XX.n = X->n;
2525 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2528 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2529 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002531 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002532 return( 0 );
2533
2534 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2535 {
2536 if( ret == 1 )
2537 return( 0 );
2538
2539 return( ret );
2540 }
2541
Janos Follathda31fa12018-09-03 14:45:23 +01002542 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002543}
2544
Janos Follatha0b67c22018-09-18 14:48:23 +01002545#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002546/*
2547 * Pseudo-primality test, error probability 2^-80
2548 */
2549int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2550 int (*f_rng)(void *, unsigned char *, size_t),
2551 void *p_rng )
2552{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002553 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002554 MPI_VALIDATE_RET( f_rng != NULL );
2555
Janos Follatha0b67c22018-09-18 14:48:23 +01002556 /*
2557 * In the past our key generation aimed for an error rate of at most
2558 * 2^-80. Since this function is deprecated, aim for the same certainty
2559 * here as well.
2560 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002561 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002562}
Janos Follatha0b67c22018-09-18 14:48:23 +01002563#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002564
2565/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002566 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002567 *
Janos Follathf301d232018-08-14 13:34:01 +01002568 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2569 * be either 1024 bits or 1536 bits long, and flags must contain
2570 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002571 */
Janos Follath7c025a92018-08-14 11:08:41 +01002572int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002573 int (*f_rng)(void *, unsigned char *, size_t),
2574 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002575{
Jethro Beekman66689272018-02-14 19:24:10 -08002576#ifdef MBEDTLS_HAVE_INT64
2577// ceil(2^63.5)
2578#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2579#else
2580// ceil(2^31.5)
2581#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2582#endif
2583 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002584 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002585 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002586 mbedtls_mpi_uint r;
2587 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002588
Hanno Becker8ce11a32018-12-19 16:18:52 +00002589 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002590 MPI_VALIDATE_RET( f_rng != NULL );
2591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2593 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002596
2597 n = BITS_TO_LIMBS( nbits );
2598
Janos Follathda31fa12018-09-03 14:45:23 +01002599 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2600 {
2601 /*
2602 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2603 */
2604 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2605 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2606 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2607 }
2608 else
2609 {
2610 /*
2611 * 2^-100 error probability, number of rounds computed based on HAC,
2612 * fact 4.48
2613 */
2614 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2615 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2616 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2617 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2618 }
2619
Jethro Beekman66689272018-02-14 19:24:10 -08002620 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002621 {
Jethro Beekman66689272018-02-14 19:24:10 -08002622 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2623 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2624 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2625
2626 k = n * biL;
2627 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2628 X->p[0] |= 1;
2629
Janos Follath7c025a92018-08-14 11:08:41 +01002630 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002631 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002632 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002635 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002636 }
Jethro Beekman66689272018-02-14 19:24:10 -08002637 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002638 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002639 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002640 * An necessary condition for Y and X = 2Y + 1 to be prime
2641 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2642 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002643 */
Jethro Beekman66689272018-02-14 19:24:10 -08002644
2645 X->p[0] |= 2;
2646
2647 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2648 if( r == 0 )
2649 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2650 else if( r == 1 )
2651 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2652
2653 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2654 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2655 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2656
2657 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002658 {
Jethro Beekman66689272018-02-14 19:24:10 -08002659 /*
2660 * First, check small factors for X and Y
2661 * before doing Miller-Rabin on any of them
2662 */
2663 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2664 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002665 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002666 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002667 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002668 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002669 goto cleanup;
2670
2671 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2672 goto cleanup;
2673
2674 /*
2675 * Next candidates. We want to preserve Y = (X-1) / 2 and
2676 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2677 * so up Y by 6 and X by 12.
2678 */
2679 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2680 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002681 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002682 }
2683 }
2684
2685cleanup:
2686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002688
2689 return( ret );
2690}
2691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002692#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002694#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002695
Paul Bakker23986e52011-04-24 08:57:21 +00002696#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002697
2698static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2699{
2700 { 693, 609, 21 },
2701 { 1764, 868, 28 },
2702 { 768454923, 542167814, 1 }
2703};
2704
Paul Bakker5121ce52009-01-03 21:22:43 +00002705/*
2706 * Checkup routine
2707 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002709{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002710 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002711 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002712
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002713 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2714 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002715
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002716 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002717 "EFE021C2645FD1DC586E69184AF4A31E" \
2718 "D5F53E93B5F123FA41680867BA110131" \
2719 "944FE7952E2517337780CB0DB80E61AA" \
2720 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002722 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002723 "B2E7EFD37075B9F03FF989C7C5051C20" \
2724 "34D2A323810251127E7BF8625A4F49A5" \
2725 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2726 "5B5C25763222FEFCCFC38B832366C29E" ) );
2727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002728 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002729 "0066A198186C18C10B2F5ED9B522752A" \
2730 "9830B69916E535C8F047518A889A43A5" \
2731 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002733 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002735 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002736 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2737 "9E857EA95A03512E2BAE7391688D264A" \
2738 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2739 "8001B72E848A38CAE1C65F78E56ABDEF" \
2740 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2741 "ECF677152EF804370C1A305CAF3B5BF1" \
2742 "30879B56C61DE584A0F53A2447A51E" ) );
2743
2744 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002745 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002748 {
2749 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002750 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002751
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002752 ret = 1;
2753 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002754 }
2755
2756 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002757 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002761 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002762 "256567336059E52CAE22925474705F39A94" ) );
2763
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002764 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002765 "6613F26162223DF488E9CD48CC132C7A" \
2766 "0AC93C701B001B092E4E5B9F73BCD27B" \
2767 "9EE50D0657C77F374E903CDFA4C642" ) );
2768
2769 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002770 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002771
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002772 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2773 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002774 {
2775 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002776 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002777
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002778 ret = 1;
2779 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002780 }
2781
2782 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002787 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002788 "36E139AEA55215609D2816998ED020BB" \
2789 "BD96C37890F65171D948E9BC7CBAA4D9" \
2790 "325D24D6A3C12710F10A09FA08AB87" ) );
2791
2792 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002793 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002796 {
2797 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002798 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002799
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002800 ret = 1;
2801 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002802 }
2803
2804 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002805 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002808
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002809 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002810 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2811 "C3DBA76456363A10869622EAC2DD84EC" \
2812 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2813
2814 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002815 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002816
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002818 {
2819 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002820 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002821
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002822 ret = 1;
2823 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002824 }
2825
2826 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002827 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002828
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002829 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002830 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002831
Paul Bakker66d5d072014-06-17 16:39:18 +02002832 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002833 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002834 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2835 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002837 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002838
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002839 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002840 {
2841 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002842 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002843
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002844 ret = 1;
2845 goto cleanup;
2846 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002847 }
2848
2849 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002850 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002851
Paul Bakker5121ce52009-01-03 21:22:43 +00002852cleanup:
2853
2854 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002855 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002857 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2858 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002859
2860 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002861 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002862
2863 return( ret );
2864}
2865
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002866#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002867
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002868#endif /* MBEDTLS_BIGNUM_C */