blob: 6713bcbf6f20fe9ca7e024b0c86022e62489d04b [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
Simon Butcher15b15d12015-11-26 19:35:03 +000021
Paul Bakker5121ce52009-01-03 21:22:43 +000022/*
Simon Butcher15b15d12015-11-26 19:35:03 +000023 * The following sources were referenced in the design of this Multi-precision
24 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000025 *
Simon Butcher15b15d12015-11-26 19:35:03 +000026 * [1] Handbook of Applied Cryptography - 1997
27 * Menezes, van Oorschot and Vanstone
28 *
29 * [2] Multi-Precision Math
30 * Tom St Denis
31 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
32 *
33 * [3] GNU Multi-Precision Arithmetic Library
34 * https://gmplib.org/manual/index.html
35 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000036 */
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020040#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/bignum.h"
47#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050048#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000049
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <string.h>
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020054#else
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdio.h>
56#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020060#endif
61
Hanno Becker73d7d792018-12-11 10:35:51 +000062#define MPI_VALIDATE_RET( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
64#define MPI_VALIDATE( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE( cond )
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000068#define biL (ciL << 3) /* bits in limb */
69#define biH (ciL << 2) /* half limb size */
70
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010071#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72
Paul Bakker5121ce52009-01-03 21:22:43 +000073/*
74 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020075 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000076 */
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020077#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
78#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000079
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050080/* Implementation that should never be optimized out by the compiler */
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050081static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
82{
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083 mbedtls_platform_zeroize( v, ciL * n );
84}
85
Paul Bakker5121ce52009-01-03 21:22:43 +000086/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000087 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000088 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089void mbedtls_mpi_init( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
Hanno Becker73d7d792018-12-11 10:35:51 +000091 MPI_VALIDATE( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 X->s = 1;
94 X->n = 0;
95 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000096}
97
98/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000099 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_mpi_free( mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
Paul Bakker6c591fa2011-05-05 11:49:20 +0000103 if( X == NULL )
104 return;
Paul Bakker5121ce52009-01-03 21:22:43 +0000105
Paul Bakker6c591fa2011-05-05 11:49:20 +0000106 if( X->p != NULL )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 {
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200108 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker6c591fa2011-05-05 11:49:20 +0000112 X->s = 1;
113 X->n = 0;
114 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000115}
116
117/*
118 * Enlarge to the specified number of limbs
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 mbedtls_mpi_uint *p;
Hanno Becker73d7d792018-12-11 10:35:51 +0000123 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200126 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakkerf9688572011-05-05 10:00:45 +0000127
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 if( X->n < nblimbs )
129 {
Simon Butcher29176892016-05-20 00:19:09 +0100130 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200131 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 if( X->p != NULL )
134 {
135 memcpy( p, X->p, X->n * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200136 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_free( X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 }
139
140 X->n = nblimbs;
141 X->p = p;
142 }
143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100148 * Resize down as much as possible,
149 * while keeping at least the specified number of limbs
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100154 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000155 MPI_VALIDATE_RET( X != NULL );
156
157 if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
158 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100159
160 /* Actually resize up in this case */
161 if( X->n <= nblimbs )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( mbedtls_mpi_grow( X, nblimbs ) );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100163
164 for( i = X->n - 1; i > 0; i-- )
165 if( X->p[i] != 0 )
166 break;
167 i++;
168
169 if( i < nblimbs )
170 i = nblimbs;
171
Simon Butcher29176892016-05-20 00:19:09 +0100172 if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200173 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100174
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 if( X->p != NULL )
176 {
177 memcpy( p, X->p, i * ciL );
Alexey Skalozube17a8da2016-01-13 17:19:33 +0200178 mbedtls_mpi_zeroize( X->p, X->n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_free( X->p );
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100180 }
181
182 X->n = i;
183 X->p = p;
184
185 return( 0 );
186}
187
188/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 * Copy the contents of Y into X
190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100193 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000195 MPI_VALIDATE_RET( X != NULL );
196 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000197
198 if( X == Y )
199 return( 0 );
200
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200201 if( Y->p == NULL )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_mpi_free( X );
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200204 return( 0 );
205 }
206
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 for( i = Y->n - 1; i > 0; i-- )
208 if( Y->p[i] != 0 )
209 break;
210 i++;
211
212 X->s = Y->s;
213
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100214 if( X->n < i )
215 {
216 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
217 }
218 else
219 {
220 memset( X->p + i, 0, ( X->n - i ) * ciL );
221 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000222
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 memcpy( X->p, Y->p, i * ciL );
224
225cleanup:
226
227 return( ret );
228}
229
230/*
231 * Swap the contents of X and Y
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000236 MPI_VALIDATE( X != NULL );
237 MPI_VALIDATE( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memcpy( &T, X, sizeof( mbedtls_mpi ) );
240 memcpy( X, Y, sizeof( mbedtls_mpi ) );
241 memcpy( Y, &T, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242}
243
244/*
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100245 * Conditionally assign X = Y, without leaking information
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100246 * about whether the assignment was made or not.
247 * (Leaking information about the respective sizes of X and Y is ok however.)
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100250{
251 int ret = 0;
252 size_t i;
Hanno Becker73d7d792018-12-11 10:35:51 +0000253 MPI_VALIDATE_RET( X != NULL );
254 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100255
Pascal Junodb99183d2015-03-11 16:49:45 +0100256 /* make sure assign is 0 or 1 in a time-constant manner */
257 assign = (assign | (unsigned char)-assign) >> 7;
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100260
Paul Bakker66d5d072014-06-17 16:39:18 +0200261 X->s = X->s * ( 1 - assign ) + Y->s * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100262
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100263 for( i = 0; i < Y->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200264 X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100265
Manuel Pégourié-Gonnard96c7a922013-11-25 18:28:53 +0100266 for( ; i < X->n; i++ )
Paul Bakker66d5d072014-06-17 16:39:18 +0200267 X->p[i] *= ( 1 - assign );
Manuel Pégourié-Gonnard71c2c212013-11-21 16:56:39 +0100268
269cleanup:
270 return( ret );
271}
272
273/*
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100274 * Conditionally swap X and Y, without leaking information
275 * about whether the swap was made or not.
276 * Here it is not ok to simply swap the pointers, which whould lead to
277 * different memory access patterns when X and Y are used afterwards.
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100280{
281 int ret, s;
282 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_mpi_uint tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +0000284 MPI_VALIDATE_RET( X != NULL );
285 MPI_VALIDATE_RET( Y != NULL );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100286
287 if( X == Y )
288 return( 0 );
289
Pascal Junodb99183d2015-03-11 16:49:45 +0100290 /* make sure swap is 0 or 1 in a time-constant manner */
291 swap = (swap | (unsigned char)-swap) >> 7;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
294 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100295
296 s = X->s;
Paul Bakker66d5d072014-06-17 16:39:18 +0200297 X->s = X->s * ( 1 - swap ) + Y->s * swap;
298 Y->s = Y->s * ( 1 - swap ) + s * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100299
300
301 for( i = 0; i < X->n; i++ )
302 {
303 tmp = X->p[i];
Paul Bakker66d5d072014-06-17 16:39:18 +0200304 X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
305 Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
Manuel Pégourié-Gonnarda60fe892013-12-04 21:41:50 +0100306 }
307
308cleanup:
309 return( ret );
310}
311
312/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000313 * Set value from integer
314 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
317 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +0000318 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 memset( X->p, 0, X->n * ciL );
322
323 X->p[0] = ( z < 0 ) ? -z : z;
324 X->s = ( z < 0 ) ? -1 : 1;
325
326cleanup:
327
328 return( ret );
329}
330
331/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000332 * Get a specific bit
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000335{
Hanno Becker73d7d792018-12-11 10:35:51 +0000336 MPI_VALIDATE_RET( X != NULL );
337
Paul Bakker2f5947e2011-05-18 15:47:11 +0000338 if( X->n * biL <= pos )
339 return( 0 );
340
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200341 return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000342}
343
Gilles Peskine11cdb052018-11-20 16:47:47 +0100344/* Get a specific byte, without range checks. */
345#define GET_BYTE( X, i ) \
346 ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
347
Paul Bakker2f5947e2011-05-18 15:47:11 +0000348/*
349 * Set a bit to a specific value of 0 or 1
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
Paul Bakker2f5947e2011-05-18 15:47:11 +0000352{
353 int ret = 0;
354 size_t off = pos / biL;
355 size_t idx = pos % biL;
Hanno Becker73d7d792018-12-11 10:35:51 +0000356 MPI_VALIDATE_RET( X != NULL );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000357
358 if( val != 0 && val != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker9af723c2014-05-01 13:03:14 +0200360
Paul Bakker2f5947e2011-05-18 15:47:11 +0000361 if( X->n * biL <= pos )
362 {
363 if( val == 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200364 return( 0 );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
Paul Bakker2f5947e2011-05-18 15:47:11 +0000367 }
368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
370 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000371
372cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Paul Bakker2f5947e2011-05-18 15:47:11 +0000374 return( ret );
375}
376
377/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200378 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000381{
Paul Bakker23986e52011-04-24 08:57:21 +0000382 size_t i, j, count = 0;
Hanno Beckerf25ee7f2018-12-19 16:51:02 +0000383 MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000384
385 for( i = 0; i < X->n; i++ )
Paul Bakkerf9688572011-05-05 10:00:45 +0000386 for( j = 0; j < biL; j++, count++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
388 return( count );
389
390 return( 0 );
391}
392
393/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000394 * Count leading zero bits in a given integer
395 */
396static size_t mbedtls_clz( const mbedtls_mpi_uint x )
397{
398 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100399 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000400
401 for( j = 0; j < biL; j++ )
402 {
403 if( x & mask ) break;
404
405 mask >>= 1;
406 }
407
408 return j;
409}
410
411/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200412 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000413 */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200414size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000415{
Paul Bakker23986e52011-04-24 08:57:21 +0000416 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200418 if( X->n == 0 )
419 return( 0 );
420
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 for( i = X->n - 1; i > 0; i-- )
422 if( X->p[i] != 0 )
423 break;
424
Simon Butcher15b15d12015-11-26 19:35:03 +0000425 j = biL - mbedtls_clz( X->p[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Paul Bakker23986e52011-04-24 08:57:21 +0000427 return( ( i * biL ) + j );
Paul Bakker5121ce52009-01-03 21:22:43 +0000428}
429
430/*
431 * Return the total size in bytes
432 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433size_t mbedtls_mpi_size( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200435 return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436}
437
438/*
439 * Convert an ASCII character to digit value
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
Paul Bakker5121ce52009-01-03 21:22:43 +0000442{
443 *d = 255;
444
445 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
446 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
447 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( *d >= (mbedtls_mpi_uint) radix )
450 return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
452 return( 0 );
453}
454
455/*
456 * Import from an ASCII string
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000459{
Paul Bakker23986e52011-04-24 08:57:21 +0000460 int ret;
461 size_t i, j, slen, n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_uint d;
463 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000464 MPI_VALIDATE_RET( X != NULL );
465 MPI_VALIDATE_RET( s != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000468 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000471
Paul Bakkerff60ee62010-03-16 21:09:09 +0000472 slen = strlen( s );
473
Paul Bakker5121ce52009-01-03 21:22:43 +0000474 if( radix == 16 )
475 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100476 if( slen > MPI_SIZE_T_MAX >> 2 )
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +0200477 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478
Paul Bakkerff60ee62010-03-16 21:09:09 +0000479 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
482 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Paul Bakker23986e52011-04-24 08:57:21 +0000484 for( i = slen, j = 0; i > 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 {
Paul Bakker23986e52011-04-24 08:57:21 +0000486 if( i == 1 && s[i - 1] == '-' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000487 {
488 X->s = -1;
489 break;
490 }
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
Paul Bakker66d5d072014-06-17 16:39:18 +0200493 X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 }
495 }
496 else
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Paul Bakkerff60ee62010-03-16 21:09:09 +0000500 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000501 {
502 if( i == 0 && s[i] == '-' )
503 {
504 X->s = -1;
505 continue;
506 }
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
509 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000510
511 if( X->s == 1 )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000514 }
515 else
516 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000518 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000519 }
520 }
521
522cleanup:
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000525
526 return( ret );
527}
528
529/*
Ron Eldora16fa292018-11-20 14:07:01 +0200530 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000531 */
Ron Eldora16fa292018-11-20 14:07:01 +0200532static int mpi_write_hlp( mbedtls_mpi *X, int radix,
533 char **p, const size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000534{
535 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200537 size_t length = 0;
538 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Ron Eldora16fa292018-11-20 14:07:01 +0200540 do
541 {
542 if( length >= buflen )
543 {
544 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
545 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000546
Ron Eldora16fa292018-11-20 14:07:01 +0200547 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
548 MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
549 /*
550 * Write the residue in the current position, as an ASCII character.
551 */
552 if( r < 0xA )
553 *(--p_end) = (char)( '0' + r );
554 else
555 *(--p_end) = (char)( 'A' + ( r - 0xA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
Ron Eldora16fa292018-11-20 14:07:01 +0200557 length++;
558 } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000559
Ron Eldora16fa292018-11-20 14:07:01 +0200560 memmove( *p, p_end, length );
561 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563cleanup:
564
565 return( ret );
566}
567
568/*
569 * Export into an ASCII string
570 */
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100571int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
572 char *buf, size_t buflen, size_t *olen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573{
Paul Bakker23986e52011-04-24 08:57:21 +0000574 int ret = 0;
575 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000576 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_mpi T;
Hanno Becker73d7d792018-12-11 10:35:51 +0000578 MPI_VALIDATE_RET( X != NULL );
579 MPI_VALIDATE_RET( olen != NULL );
580 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000581
582 if( radix < 2 || radix > 16 )
Hanno Becker54c91dd2018-12-12 13:37:06 +0000583 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000585 n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
586 if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
587 * `n`. If radix > 4, this might be a strict
588 * overapproximation of the number of
589 * radix-adic digits needed to present `n`. */
590 if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
591 * present `n`. */
592
Janos Follath870ed002019-03-06 13:43:02 +0000593 n += 1; /* Terminating null byte */
Hanno Beckerc1fa6cd2019-02-04 09:45:07 +0000594 n += 1; /* Compensate for the divisions above, which round down `n`
595 * in case it's not even. */
596 n += 1; /* Potential '-'-sign. */
597 n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
598 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100600 if( buflen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000601 {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100602 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000604 }
605
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100606 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000608
609 if( X->s == -1 )
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000610 {
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 *p++ = '-';
Hanno Beckeraf97cae2019-02-01 16:41:30 +0000612 buflen--;
613 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000614
615 if( radix == 16 )
616 {
Paul Bakker23986e52011-04-24 08:57:21 +0000617 int c;
618 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000619
Paul Bakker23986e52011-04-24 08:57:21 +0000620 for( i = X->n, k = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 {
Paul Bakker23986e52011-04-24 08:57:21 +0000622 for( j = ciL; j > 0; j-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 {
Paul Bakker23986e52011-04-24 08:57:21 +0000624 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000625
Paul Bakker6c343d72014-07-10 14:36:19 +0200626 if( c == 0 && k == 0 && ( i + j ) != 2 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000627 continue;
628
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000629 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000630 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000631 k = 1;
632 }
633 }
634 }
635 else
636 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000638
639 if( T.s == -1 )
640 T.s = 1;
641
Ron Eldora16fa292018-11-20 14:07:01 +0200642 MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 }
644
645 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100646 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
648cleanup:
649
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
652 return( ret );
653}
654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000656/*
657 * Read X from an opened file
658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
Paul Bakker5121ce52009-01-03 21:22:43 +0000660{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000662 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000664 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000665 * Buffer should have space for (short) label and decimal formatted MPI,
666 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Paul Bakker5121ce52009-01-03 21:22:43 +0000669
Hanno Becker73d7d792018-12-11 10:35:51 +0000670 MPI_VALIDATE_RET( X != NULL );
671 MPI_VALIDATE_RET( fin != NULL );
672
673 if( radix < 2 || radix > 16 )
674 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
675
Paul Bakker5121ce52009-01-03 21:22:43 +0000676 memset( s, 0, sizeof( s ) );
677 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
680 slen = strlen( s );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000681 if( slen == sizeof( s ) - 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakkercb37aa52011-11-30 16:00:20 +0000683
Hanno Beckerb2034b72017-04-26 11:46:46 +0100684 if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
685 if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687 p = s + slen;
Hanno Beckerb2034b72017-04-26 11:46:46 +0100688 while( p-- > s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000689 if( mpi_get_digit( &d, radix, *p ) != 0 )
690 break;
691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000693}
694
695/*
696 * Write X into an opened file (or stdout if fout == NULL)
697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000699{
Paul Bakker23986e52011-04-24 08:57:21 +0000700 int ret;
701 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000702 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000703 * Buffer should have space for (short) label and decimal formatted MPI,
704 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000705 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
Hanno Becker73d7d792018-12-11 10:35:51 +0000707 MPI_VALIDATE_RET( X != NULL );
708
709 if( radix < 2 || radix > 16 )
710 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100712 memset( s, 0, sizeof( s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100714 MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716 if( p == NULL ) p = "";
717
718 plen = strlen( p );
719 slen = strlen( s );
720 s[slen++] = '\r';
721 s[slen++] = '\n';
722
723 if( fout != NULL )
724 {
725 if( fwrite( p, 1, plen, fout ) != plen ||
726 fwrite( s, 1, slen, fout ) != slen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000728 }
729 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_printf( "%s%s", p, s );
Paul Bakker5121ce52009-01-03 21:22:43 +0000731
732cleanup:
733
734 return( ret );
735}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
Hanno Beckerda1655a2017-10-18 14:21:44 +0100738
739/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
740 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000741
742static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
743{
744 uint8_t i;
Hanno Becker92c98932019-05-01 17:09:11 +0100745 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000746 mbedtls_mpi_uint tmp = 0;
Hanno Becker92c98932019-05-01 17:09:11 +0100747
748 for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
749 {
750 tmp <<= CHAR_BIT;
751 tmp |= (mbedtls_mpi_uint) *x_ptr;
752 }
753
Hanno Beckerf8720072018-11-08 11:53:49 +0000754 return( tmp );
755}
756
757static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
758{
759#if defined(__BYTE_ORDER__)
760
761/* Nothing to do on bigendian systems. */
762#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
763 return( x );
764#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
765
766#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
767
768/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000769#if defined(__GNUC__) && defined(__GNUC_PREREQ)
770#if __GNUC_PREREQ(4,3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000771#define have_bswap
772#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000773#endif
774
775#if defined(__clang__) && defined(__has_builtin)
776#if __has_builtin(__builtin_bswap32) && \
777 __has_builtin(__builtin_bswap64)
778#define have_bswap
779#endif
780#endif
781
Hanno Beckerf8720072018-11-08 11:53:49 +0000782#if defined(have_bswap)
783 /* The compiler is hopefully able to statically evaluate this! */
784 switch( sizeof(mbedtls_mpi_uint) )
785 {
786 case 4:
787 return( __builtin_bswap32(x) );
788 case 8:
789 return( __builtin_bswap64(x) );
790 }
791#endif
792#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
793#endif /* __BYTE_ORDER__ */
794
795 /* Fall back to C-based reordering if we don't know the byte order
796 * or we couldn't use a compiler-specific builtin. */
797 return( mpi_uint_bigendian_to_host_c( x ) );
798}
799
Hanno Becker2be8a552018-10-25 12:40:09 +0100800static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
Hanno Beckerda1655a2017-10-18 14:21:44 +0100801{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100802 mbedtls_mpi_uint *cur_limb_left;
803 mbedtls_mpi_uint *cur_limb_right;
Hanno Becker2be8a552018-10-25 12:40:09 +0100804 if( limbs == 0 )
805 return;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100806
807 /*
808 * Traverse limbs and
809 * - adapt byte-order in each limb
810 * - swap the limbs themselves.
811 * For that, simultaneously traverse the limbs from left to right
812 * and from right to left, as long as the left index is not bigger
813 * than the right index (it's not a problem if limbs is odd and the
814 * indices coincide in the last iteration).
815 */
Hanno Beckerda1655a2017-10-18 14:21:44 +0100816 for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
817 cur_limb_left <= cur_limb_right;
818 cur_limb_left++, cur_limb_right-- )
819 {
Hanno Beckerf8720072018-11-08 11:53:49 +0000820 mbedtls_mpi_uint tmp;
821 /* Note that if cur_limb_left == cur_limb_right,
822 * this code effectively swaps the bytes only once. */
823 tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
824 *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
825 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100826 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100827}
828
Paul Bakker5121ce52009-01-03 21:22:43 +0000829/*
830 * Import X from unsigned binary data, big endian
831 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000833{
Paul Bakker23986e52011-04-24 08:57:21 +0000834 int ret;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100835 size_t const limbs = CHARS_TO_LIMBS( buflen );
836 size_t const overhead = ( limbs * ciL ) - buflen;
837 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000838
Hanno Becker8ce11a32018-12-19 16:18:52 +0000839 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +0000840 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
841
Hanno Becker073c1992017-10-17 15:17:27 +0100842 /* Ensure that target MPI has exactly the necessary number of limbs */
843 if( X->n != limbs )
844 {
845 mbedtls_mpi_free( X );
846 mbedtls_mpi_init( X );
847 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
848 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000850
Hanno Becker0e810b92019-01-03 17:13:11 +0000851 /* Avoid calling `memcpy` with NULL source argument,
852 * even if buflen is 0. */
853 if( buf != NULL )
854 {
855 Xp = (unsigned char*) X->p;
856 memcpy( Xp + overhead, buf, buflen );
Hanno Beckerda1655a2017-10-18 14:21:44 +0100857
Hanno Becker0e810b92019-01-03 17:13:11 +0000858 mpi_bigendian_to_host( X->p, limbs );
859 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000860
861cleanup:
862
863 return( ret );
864}
865
866/*
867 * Export X into unsigned binary data, big endian
868 */
Gilles Peskine11cdb052018-11-20 16:47:47 +0100869int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
870 unsigned char *buf, size_t buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000871{
Hanno Becker73d7d792018-12-11 10:35:51 +0000872 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100873 size_t bytes_to_copy;
874 unsigned char *p;
875 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000876
Hanno Becker73d7d792018-12-11 10:35:51 +0000877 MPI_VALIDATE_RET( X != NULL );
878 MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
879
880 stored_bytes = X->n * ciL;
881
Gilles Peskine11cdb052018-11-20 16:47:47 +0100882 if( stored_bytes < buflen )
883 {
884 /* There is enough space in the output buffer. Write initial
885 * null bytes and record the position at which to start
886 * writing the significant bytes. In this case, the execution
887 * trace of this function does not depend on the value of the
888 * number. */
889 bytes_to_copy = stored_bytes;
890 p = buf + buflen - stored_bytes;
891 memset( buf, 0, buflen - stored_bytes );
892 }
893 else
894 {
895 /* The output buffer is smaller than the allocated size of X.
896 * However X may fit if its leading bytes are zero. */
897 bytes_to_copy = buflen;
898 p = buf;
899 for( i = bytes_to_copy; i < stored_bytes; i++ )
900 {
901 if( GET_BYTE( X, i ) != 0 )
902 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
903 }
904 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000905
Gilles Peskine11cdb052018-11-20 16:47:47 +0100906 for( i = 0; i < bytes_to_copy; i++ )
907 p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
Paul Bakker5121ce52009-01-03 21:22:43 +0000908
909 return( 0 );
910}
911
912/*
913 * Left-shift: X <<= count
914 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000916{
Paul Bakker23986e52011-04-24 08:57:21 +0000917 int ret;
918 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000920 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000921
922 v0 = count / (biL );
923 t1 = count & (biL - 1);
924
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200925 i = mbedtls_mpi_bitlen( X ) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
Paul Bakkerf9688572011-05-05 10:00:45 +0000927 if( X->n * biL < i )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000929
930 ret = 0;
931
932 /*
933 * shift by count / limb_size
934 */
935 if( v0 > 0 )
936 {
Paul Bakker23986e52011-04-24 08:57:21 +0000937 for( i = X->n; i > v0; i-- )
938 X->p[i - 1] = X->p[i - v0 - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +0000939
Paul Bakker23986e52011-04-24 08:57:21 +0000940 for( ; i > 0; i-- )
941 X->p[i - 1] = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000942 }
943
944 /*
945 * shift by count % limb_size
946 */
947 if( t1 > 0 )
948 {
949 for( i = v0; i < X->n; i++ )
950 {
951 r1 = X->p[i] >> (biL - t1);
952 X->p[i] <<= t1;
953 X->p[i] |= r0;
954 r0 = r1;
955 }
956 }
957
958cleanup:
959
960 return( ret );
961}
962
963/*
964 * Right-shift: X >>= count
965 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
Paul Bakker5121ce52009-01-03 21:22:43 +0000967{
Paul Bakker23986e52011-04-24 08:57:21 +0000968 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 mbedtls_mpi_uint r0 = 0, r1;
Hanno Becker73d7d792018-12-11 10:35:51 +0000970 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000971
972 v0 = count / biL;
973 v1 = count & (biL - 1);
974
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100975 if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200976 return mbedtls_mpi_lset( X, 0 );
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +0100977
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 /*
979 * shift by count / limb_size
980 */
981 if( v0 > 0 )
982 {
983 for( i = 0; i < X->n - v0; i++ )
984 X->p[i] = X->p[i + v0];
985
986 for( ; i < X->n; i++ )
987 X->p[i] = 0;
988 }
989
990 /*
991 * shift by count % limb_size
992 */
993 if( v1 > 0 )
994 {
Paul Bakker23986e52011-04-24 08:57:21 +0000995 for( i = X->n; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +0000996 {
Paul Bakker23986e52011-04-24 08:57:21 +0000997 r1 = X->p[i - 1] << (biL - v1);
998 X->p[i - 1] >>= v1;
999 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001000 r0 = r1;
1001 }
1002 }
1003
1004 return( 0 );
1005}
1006
1007/*
1008 * Compare unsigned values
1009 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001011{
Paul Bakker23986e52011-04-24 08:57:21 +00001012 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001013 MPI_VALIDATE_RET( X != NULL );
1014 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001015
Paul Bakker23986e52011-04-24 08:57:21 +00001016 for( i = X->n; i > 0; i-- )
1017 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 break;
1019
Paul Bakker23986e52011-04-24 08:57:21 +00001020 for( j = Y->n; j > 0; j-- )
1021 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001022 break;
1023
Paul Bakker23986e52011-04-24 08:57:21 +00001024 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001025 return( 0 );
1026
1027 if( i > j ) return( 1 );
1028 if( j > i ) return( -1 );
1029
Paul Bakker23986e52011-04-24 08:57:21 +00001030 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001031 {
Paul Bakker23986e52011-04-24 08:57:21 +00001032 if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
1033 if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001034 }
1035
1036 return( 0 );
1037}
1038
1039/*
1040 * Compare signed values
1041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +00001043{
Paul Bakker23986e52011-04-24 08:57:21 +00001044 size_t i, j;
Hanno Becker73d7d792018-12-11 10:35:51 +00001045 MPI_VALIDATE_RET( X != NULL );
1046 MPI_VALIDATE_RET( Y != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001047
Paul Bakker23986e52011-04-24 08:57:21 +00001048 for( i = X->n; i > 0; i-- )
1049 if( X->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001050 break;
1051
Paul Bakker23986e52011-04-24 08:57:21 +00001052 for( j = Y->n; j > 0; j-- )
1053 if( Y->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001054 break;
1055
Paul Bakker23986e52011-04-24 08:57:21 +00001056 if( i == 0 && j == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 return( 0 );
1058
1059 if( i > j ) return( X->s );
Paul Bakker0c8f73b2012-03-22 14:08:57 +00001060 if( j > i ) return( -Y->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001061
1062 if( X->s > 0 && Y->s < 0 ) return( 1 );
1063 if( Y->s > 0 && X->s < 0 ) return( -1 );
1064
Paul Bakker23986e52011-04-24 08:57:21 +00001065 for( ; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001066 {
Paul Bakker23986e52011-04-24 08:57:21 +00001067 if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
1068 if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
Paul Bakker5121ce52009-01-03 21:22:43 +00001069 }
1070
1071 return( 0 );
1072}
1073
Janos Follath45ec9902019-10-14 09:09:32 +01001074/** Decide if an integer is less than the other, without branches.
1075 *
1076 * \param x First integer.
1077 * \param y Second integer.
1078 *
1079 * \return 1 if \p x is less than \p y, 0 otherwise
1080 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001081static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
1082 const mbedtls_mpi_uint y )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001083{
1084 mbedtls_mpi_uint ret;
1085 mbedtls_mpi_uint cond;
1086
1087 /*
1088 * Check if the most significant bits (MSB) of the operands are different.
1089 */
1090 cond = ( x ^ y );
1091 /*
1092 * If the MSB are the same then the difference x-y will be negative (and
1093 * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
1094 */
1095 ret = ( x - y ) & ~cond;
1096 /*
1097 * If the MSB are different, then the operand with the MSB of 1 is the
1098 * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
1099 * the MSB of y is 0.)
1100 */
1101 ret |= y & cond;
1102
1103
Janos Follath7a34bcf2019-10-14 08:59:14 +01001104 ret = ret >> ( biL - 1 );
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001105
Janos Follath359a01e2019-10-29 15:08:46 +00001106 return (unsigned) ret;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001107}
1108
1109/*
1110 * Compare signed values in constant time
1111 */
Janos Follath867a3ab2019-10-11 14:21:53 +01001112int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
1113 unsigned *ret )
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001114{
1115 size_t i;
Janos Follathbd87a592019-10-28 12:23:18 +00001116 /* The value of any of these variables is either 0 or 1 at all times. */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001117 unsigned cond, done, X_is_negative, Y_is_negative;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001118
1119 MPI_VALIDATE_RET( X != NULL );
1120 MPI_VALIDATE_RET( Y != NULL );
1121 MPI_VALIDATE_RET( ret != NULL );
1122
1123 if( X->n != Y->n )
1124 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1125
1126 /*
Janos Follath58525182019-10-28 12:12:15 +00001127 * Set sign_N to 1 if N >= 0, 0 if N < 0.
1128 * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001129 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001130 X_is_negative = ( X->s & 2 ) >> 1;
1131 Y_is_negative = ( Y->s & 2 ) >> 1;
Janos Follath867a3ab2019-10-11 14:21:53 +01001132
1133 /*
1134 * If the signs are different, then the positive operand is the bigger.
Janos Follath1f21c1d2019-10-28 12:31:34 +00001135 * That is if X is negative (X_is_negative == 1), then X < Y is true and it
1136 * is false if X is positive (X_is_negative == 0).
Janos Follath867a3ab2019-10-11 14:21:53 +01001137 */
Janos Follath1f21c1d2019-10-28 12:31:34 +00001138 cond = ( X_is_negative ^ Y_is_negative );
1139 *ret = cond & X_is_negative;
Janos Follath867a3ab2019-10-11 14:21:53 +01001140
1141 /*
Janos Follathbd87a592019-10-28 12:23:18 +00001142 * This is a constant-time function. We might have the result, but we still
Janos Follath867a3ab2019-10-11 14:21:53 +01001143 * need to go through the loop. Record if we have the result already.
1144 */
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001145 done = cond;
1146
1147 for( i = X->n; i > 0; i-- )
1148 {
1149 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001150 * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
1151 * X and Y are negative.
Janos Follath867a3ab2019-10-11 14:21:53 +01001152 *
1153 * Again even if we can make a decision, we just mark the result and
1154 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001155 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001156 cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
1157 *ret |= cond & ( 1 - done ) & X_is_negative;
Janos Follathfbe4c942019-10-28 12:37:21 +00001158 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001159
1160 /*
Janos Follathe25f1ee2019-11-05 12:24:52 +00001161 * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
1162 * X and Y are positive.
Janos Follath867a3ab2019-10-11 14:21:53 +01001163 *
1164 * Again even if we can make a decision, we just mark the result and
1165 * the fact that we are done and continue looping.
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001166 */
Janos Follathe25f1ee2019-11-05 12:24:52 +00001167 cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
1168 *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
Janos Follathfbe4c942019-10-28 12:37:21 +00001169 done |= cond;
Janos Follathb9f6f9b2019-09-05 14:47:19 +01001170 }
1171
1172 return( 0 );
1173}
1174
Paul Bakker5121ce52009-01-03 21:22:43 +00001175/*
1176 * Compare signed values
1177 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001178int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
Paul Bakker5121ce52009-01-03 21:22:43 +00001179{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001180 mbedtls_mpi Y;
1181 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001182 MPI_VALIDATE_RET( X != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001183
1184 *p = ( z < 0 ) ? -z : z;
1185 Y.s = ( z < 0 ) ? -1 : 1;
1186 Y.n = 1;
1187 Y.p = p;
1188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001189 return( mbedtls_mpi_cmp_mpi( X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001190}
1191
1192/*
1193 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1194 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001196{
Paul Bakker23986e52011-04-24 08:57:21 +00001197 int ret;
1198 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001199 mbedtls_mpi_uint *o, *p, c, tmp;
Hanno Becker73d7d792018-12-11 10:35:51 +00001200 MPI_VALIDATE_RET( X != NULL );
1201 MPI_VALIDATE_RET( A != NULL );
1202 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001203
1204 if( X == B )
1205 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001207 }
1208
1209 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker9af723c2014-05-01 13:03:14 +02001211
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001212 /*
1213 * X should always be positive as a result of unsigned additions.
1214 */
1215 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001216
Paul Bakker23986e52011-04-24 08:57:21 +00001217 for( j = B->n; j > 0; j-- )
1218 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001219 break;
1220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001222
1223 o = B->p; p = X->p; c = 0;
1224
Janos Follath6c922682015-10-30 17:43:11 +01001225 /*
1226 * tmp is used because it might happen that p == o
1227 */
Paul Bakker23986e52011-04-24 08:57:21 +00001228 for( i = 0; i < j; i++, o++, p++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00001229 {
Janos Follath6c922682015-10-30 17:43:11 +01001230 tmp= *o;
Paul Bakker5121ce52009-01-03 21:22:43 +00001231 *p += c; c = ( *p < c );
Janos Follath6c922682015-10-30 17:43:11 +01001232 *p += tmp; c += ( *p < tmp );
Paul Bakker5121ce52009-01-03 21:22:43 +00001233 }
1234
1235 while( c != 0 )
1236 {
1237 if( i >= X->n )
1238 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001240 p = X->p + i;
1241 }
1242
Paul Bakker2d319fd2012-09-16 21:34:26 +00001243 *p += c; c = ( *p < c ); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001244 }
1245
1246cleanup:
1247
1248 return( ret );
1249}
1250
1251/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252 * Helper for mbedtls_mpi subtraction
Paul Bakker5121ce52009-01-03 21:22:43 +00001253 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
Paul Bakker5121ce52009-01-03 21:22:43 +00001255{
Paul Bakker23986e52011-04-24 08:57:21 +00001256 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 mbedtls_mpi_uint c, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001258
1259 for( i = c = 0; i < n; i++, s++, d++ )
1260 {
1261 z = ( *d < c ); *d -= c;
1262 c = ( *d < *s ) + z; *d -= *s;
1263 }
1264
1265 while( c != 0 )
1266 {
1267 z = ( *d < c ); *d -= c;
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001268 c = z; d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001269 }
1270}
1271
1272/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001273 * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
Paul Bakker5121ce52009-01-03 21:22:43 +00001274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001276{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277 mbedtls_mpi TB;
Paul Bakker23986e52011-04-24 08:57:21 +00001278 int ret;
1279 size_t n;
Hanno Becker73d7d792018-12-11 10:35:51 +00001280 MPI_VALIDATE_RET( X != NULL );
1281 MPI_VALIDATE_RET( A != NULL );
1282 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1285 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001287 mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001288
1289 if( X == B )
1290 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001292 B = &TB;
1293 }
1294
1295 if( X != A )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001296 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001297
Paul Bakker1ef7a532009-06-20 10:50:55 +00001298 /*
Paul Bakker60b1d102013-10-29 10:02:51 +01001299 * X should always be positive as a result of unsigned subtractions.
Paul Bakker1ef7a532009-06-20 10:50:55 +00001300 */
1301 X->s = 1;
1302
Paul Bakker5121ce52009-01-03 21:22:43 +00001303 ret = 0;
1304
Paul Bakker23986e52011-04-24 08:57:21 +00001305 for( n = B->n; n > 0; n-- )
1306 if( B->p[n - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001307 break;
1308
Paul Bakker23986e52011-04-24 08:57:21 +00001309 mpi_sub_hlp( n, B->p, X->p );
Paul Bakker5121ce52009-01-03 21:22:43 +00001310
1311cleanup:
1312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001314
1315 return( ret );
1316}
1317
1318/*
1319 * Signed addition: X = A + B
1320 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001322{
Hanno Becker73d7d792018-12-11 10:35:51 +00001323 int ret, s;
1324 MPI_VALIDATE_RET( X != NULL );
1325 MPI_VALIDATE_RET( A != NULL );
1326 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001327
Hanno Becker73d7d792018-12-11 10:35:51 +00001328 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001329 if( A->s * B->s < 0 )
1330 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001332 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001333 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001334 X->s = s;
1335 }
1336 else
1337 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001339 X->s = -s;
1340 }
1341 }
1342 else
1343 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001345 X->s = s;
1346 }
1347
1348cleanup:
1349
1350 return( ret );
1351}
1352
1353/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001354 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001357{
Hanno Becker73d7d792018-12-11 10:35:51 +00001358 int ret, s;
1359 MPI_VALIDATE_RET( X != NULL );
1360 MPI_VALIDATE_RET( A != NULL );
1361 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001362
Hanno Becker73d7d792018-12-11 10:35:51 +00001363 s = A->s;
Paul Bakker5121ce52009-01-03 21:22:43 +00001364 if( A->s * B->s > 0 )
1365 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001367 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001369 X->s = s;
1370 }
1371 else
1372 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001373 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001374 X->s = -s;
1375 }
1376 }
1377 else
1378 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001380 X->s = s;
1381 }
1382
1383cleanup:
1384
1385 return( ret );
1386}
1387
1388/*
1389 * Signed addition: X = A + b
1390 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001392{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 mbedtls_mpi _B;
1394 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001395 MPI_VALIDATE_RET( X != NULL );
1396 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001397
1398 p[0] = ( b < 0 ) ? -b : b;
1399 _B.s = ( b < 0 ) ? -1 : 1;
1400 _B.n = 1;
1401 _B.p = p;
1402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 return( mbedtls_mpi_add_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001404}
1405
1406/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001407 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001408 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001410{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001411 mbedtls_mpi _B;
1412 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001413 MPI_VALIDATE_RET( X != NULL );
1414 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001415
1416 p[0] = ( b < 0 ) ? -b : b;
1417 _B.s = ( b < 0 ) ? -1 : 1;
1418 _B.n = 1;
1419 _B.p = p;
1420
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001421 return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001422}
1423
1424/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001425 * Helper for mbedtls_mpi multiplication
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001426 */
1427static
1428#if defined(__APPLE__) && defined(__arm__)
1429/*
1430 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1431 * appears to need this to prevent bad ARM code generation at -O3.
1432 */
1433__attribute__ ((noinline))
1434#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435void 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 +00001436{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437 mbedtls_mpi_uint c = 0, t = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001438
1439#if defined(MULADDC_HUIT)
1440 for( ; i >= 8; i -= 8 )
1441 {
1442 MULADDC_INIT
1443 MULADDC_HUIT
1444 MULADDC_STOP
1445 }
1446
1447 for( ; i > 0; i-- )
1448 {
1449 MULADDC_INIT
1450 MULADDC_CORE
1451 MULADDC_STOP
1452 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001453#else /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001454 for( ; i >= 16; i -= 16 )
1455 {
1456 MULADDC_INIT
1457 MULADDC_CORE MULADDC_CORE
1458 MULADDC_CORE MULADDC_CORE
1459 MULADDC_CORE MULADDC_CORE
1460 MULADDC_CORE MULADDC_CORE
1461
1462 MULADDC_CORE MULADDC_CORE
1463 MULADDC_CORE MULADDC_CORE
1464 MULADDC_CORE MULADDC_CORE
1465 MULADDC_CORE MULADDC_CORE
1466 MULADDC_STOP
1467 }
1468
1469 for( ; i >= 8; i -= 8 )
1470 {
1471 MULADDC_INIT
1472 MULADDC_CORE MULADDC_CORE
1473 MULADDC_CORE MULADDC_CORE
1474
1475 MULADDC_CORE MULADDC_CORE
1476 MULADDC_CORE MULADDC_CORE
1477 MULADDC_STOP
1478 }
1479
1480 for( ; i > 0; i-- )
1481 {
1482 MULADDC_INIT
1483 MULADDC_CORE
1484 MULADDC_STOP
1485 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001486#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001487
1488 t++;
1489
1490 do {
1491 *d += c; c = ( *d < c ); d++;
1492 }
1493 while( c != 0 );
1494}
1495
1496/*
1497 * Baseline multiplication: X = A * B (HAC 14.12)
1498 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001500{
Paul Bakker23986e52011-04-24 08:57:21 +00001501 int ret;
1502 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 mbedtls_mpi TA, TB;
Hanno Becker73d7d792018-12-11 10:35:51 +00001504 MPI_VALIDATE_RET( X != NULL );
1505 MPI_VALIDATE_RET( A != NULL );
1506 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001508 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00001509
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510 if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1511 if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
Paul Bakker5121ce52009-01-03 21:22:43 +00001512
Paul Bakker23986e52011-04-24 08:57:21 +00001513 for( i = A->n; i > 0; i-- )
1514 if( A->p[i - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001515 break;
1516
Paul Bakker23986e52011-04-24 08:57:21 +00001517 for( j = B->n; j > 0; j-- )
1518 if( B->p[j - 1] != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001519 break;
1520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001521 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1522 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001523
Alexey Skalozub8e75e682016-01-13 21:59:27 +02001524 for( ; j > 0; j-- )
1525 mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
Paul Bakker5121ce52009-01-03 21:22:43 +00001526
1527 X->s = A->s * B->s;
1528
1529cleanup:
1530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001531 mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001532
1533 return( ret );
1534}
1535
1536/*
1537 * Baseline multiplication: X = A * b
1538 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001540{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001541 mbedtls_mpi _B;
1542 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001543 MPI_VALIDATE_RET( X != NULL );
1544 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001545
1546 _B.s = 1;
1547 _B.n = 1;
1548 _B.p = p;
1549 p[0] = b;
1550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001551 return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001552}
1553
1554/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001555 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1556 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001557 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001558static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1559 mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
Simon Butcher15b15d12015-11-26 19:35:03 +00001560{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001561#if defined(MBEDTLS_HAVE_UDBL)
1562 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001563#else
Simon Butcher9803d072016-01-03 00:24:34 +00001564 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1565 const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001566 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1567 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001568 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001569#endif
1570
Simon Butcher15b15d12015-11-26 19:35:03 +00001571 /*
1572 * Check for overflow
1573 */
Simon Butcherf5ba0452015-12-27 23:01:55 +00001574 if( 0 == d || u1 >= d )
Simon Butcher15b15d12015-11-26 19:35:03 +00001575 {
Simon Butcherf5ba0452015-12-27 23:01:55 +00001576 if (r != NULL) *r = ~0;
Simon Butcher15b15d12015-11-26 19:35:03 +00001577
Simon Butcherf5ba0452015-12-27 23:01:55 +00001578 return ( ~0 );
Simon Butcher15b15d12015-11-26 19:35:03 +00001579 }
1580
1581#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001582 dividend = (mbedtls_t_udbl) u1 << biL;
1583 dividend |= (mbedtls_t_udbl) u0;
1584 quotient = dividend / d;
1585 if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1586 quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1587
1588 if( r != NULL )
Simon Butcher9803d072016-01-03 00:24:34 +00001589 *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001590
1591 return (mbedtls_mpi_uint) quotient;
1592#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001593
1594 /*
1595 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1596 * Vol. 2 - Seminumerical Algorithms, Knuth
1597 */
1598
1599 /*
1600 * Normalize the divisor, d, and dividend, u0, u1
1601 */
1602 s = mbedtls_clz( d );
1603 d = d << s;
1604
1605 u1 = u1 << s;
Simon Butcher9803d072016-01-03 00:24:34 +00001606 u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
Simon Butcher15b15d12015-11-26 19:35:03 +00001607 u0 = u0 << s;
1608
1609 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001610 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001611
1612 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001613 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001614
1615 /*
1616 * Find the first quotient and remainder
1617 */
1618 q1 = u1 / d1;
1619 r0 = u1 - d1 * q1;
1620
1621 while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1622 {
1623 q1 -= 1;
1624 r0 += d1;
1625
1626 if ( r0 >= radix ) break;
1627 }
1628
Simon Butcherf5ba0452015-12-27 23:01:55 +00001629 rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
Simon Butcher15b15d12015-11-26 19:35:03 +00001630 q0 = rAX / d1;
1631 r0 = rAX - q0 * d1;
1632
1633 while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1634 {
1635 q0 -= 1;
1636 r0 += d1;
1637
1638 if ( r0 >= radix ) break;
1639 }
1640
1641 if (r != NULL)
Simon Butcherf5ba0452015-12-27 23:01:55 +00001642 *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
Simon Butcher15b15d12015-11-26 19:35:03 +00001643
1644 quotient = q1 * radix + q0;
1645
1646 return quotient;
1647#endif
1648}
1649
1650/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001652 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001653int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1654 const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001655{
Paul Bakker23986e52011-04-24 08:57:21 +00001656 int ret;
1657 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 mbedtls_mpi X, Y, Z, T1, T2;
Hanno Becker73d7d792018-12-11 10:35:51 +00001659 MPI_VALIDATE_RET( A != NULL );
1660 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662 if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1663 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1666 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001669 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001670 if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1671 if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001672 return( 0 );
1673 }
1674
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001675 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1676 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001677 X.s = Y.s = 1;
1678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1680 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
1681 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1682 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001683
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001684 k = mbedtls_mpi_bitlen( &Y ) % biL;
Paul Bakkerf9688572011-05-05 10:00:45 +00001685 if( k < biL - 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001686 {
1687 k = biL - 1 - k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001690 }
1691 else k = 0;
1692
1693 n = X.n - 1;
1694 t = Y.n - 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001695 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001698 {
1699 Z.p[n - t]++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001701 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001702 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
1704 for( i = n; i > t ; i-- )
1705 {
1706 if( X.p[i] >= Y.p[t] )
1707 Z.p[i - t - 1] = ~0;
1708 else
1709 {
Simon Butcher15b15d12015-11-26 19:35:03 +00001710 Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1711 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001712 }
1713
1714 Z.p[i - t - 1]++;
1715 do
1716 {
1717 Z.p[i - t - 1]--;
1718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001720 T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001721 T1.p[1] = Y.p[t];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
Paul Bakker66d5d072014-06-17 16:39:18 +02001725 T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1726 T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001727 T2.p[2] = X.p[i];
1728 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001729 while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001731 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1732 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1733 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001735 if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001736 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001737 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1738 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1739 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001740 Z.p[i - t - 1]--;
1741 }
1742 }
1743
1744 if( Q != NULL )
1745 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001746 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001747 Q->s = A->s * B->s;
1748 }
1749
1750 if( R != NULL )
1751 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001752 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
Paul Bakkerf02c5642012-11-13 10:25:21 +00001753 X.s = A->s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001754 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001756 if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001757 R->s = 1;
1758 }
1759
1760cleanup:
1761
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1763 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001764
1765 return( ret );
1766}
1767
1768/*
1769 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001770 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001771int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
1772 const mbedtls_mpi *A,
1773 mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001774{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001775 mbedtls_mpi _B;
1776 mbedtls_mpi_uint p[1];
Hanno Becker73d7d792018-12-11 10:35:51 +00001777 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001778
1779 p[0] = ( b < 0 ) ? -b : b;
1780 _B.s = ( b < 0 ) ? -1 : 1;
1781 _B.n = 1;
1782 _B.p = p;
1783
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001784 return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001785}
1786
1787/*
1788 * Modulo: R = A mod B
1789 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001791{
1792 int ret;
Hanno Becker73d7d792018-12-11 10:35:51 +00001793 MPI_VALIDATE_RET( R != NULL );
1794 MPI_VALIDATE_RET( A != NULL );
1795 MPI_VALIDATE_RET( B != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1798 return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1803 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1806 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001807
1808cleanup:
1809
1810 return( ret );
1811}
1812
1813/*
1814 * Modulo: r = A mod b
1815 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001817{
Paul Bakker23986e52011-04-24 08:57:21 +00001818 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 mbedtls_mpi_uint x, y, z;
Hanno Becker73d7d792018-12-11 10:35:51 +00001820 MPI_VALIDATE_RET( r != NULL );
1821 MPI_VALIDATE_RET( A != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001822
1823 if( b == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
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_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001828
1829 /*
1830 * handle trivial cases
1831 */
1832 if( b == 1 )
1833 {
1834 *r = 0;
1835 return( 0 );
1836 }
1837
1838 if( b == 2 )
1839 {
1840 *r = A->p[0] & 1;
1841 return( 0 );
1842 }
1843
1844 /*
1845 * general case
1846 */
Paul Bakker23986e52011-04-24 08:57:21 +00001847 for( i = A->n, y = 0; i > 0; i-- )
Paul Bakker5121ce52009-01-03 21:22:43 +00001848 {
Paul Bakker23986e52011-04-24 08:57:21 +00001849 x = A->p[i - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001850 y = ( y << biH ) | ( x >> biH );
1851 z = y / b;
1852 y -= z * b;
1853
1854 x <<= biH;
1855 y = ( y << biH ) | ( x >> biH );
1856 z = y / b;
1857 y -= z * b;
1858 }
1859
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001860 /*
1861 * If A is negative, then the current y represents a negative value.
1862 * Flipping it to the positive side.
1863 */
1864 if( A->s < 0 && y != 0 )
1865 y = b - y;
1866
Paul Bakker5121ce52009-01-03 21:22:43 +00001867 *r = y;
1868
1869 return( 0 );
1870}
1871
1872/*
1873 * Fast Montgomery initialization (thanks to Tom St Denis)
1874 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001876{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001878 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001879
1880 x = m0;
1881 x += ( ( m0 + 2 ) & 4 ) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001882
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001883 for( i = biL; i >= 8; i /= 2 )
1884 x *= ( 2 - ( m0 * x ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001885
1886 *mm = ~x + 1;
1887}
1888
1889/*
1890 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1891 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001892static 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 +02001893 const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001894{
Paul Bakker23986e52011-04-24 08:57:21 +00001895 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001897
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001898 if( T->n < N->n + 1 || T->p == NULL )
1899 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1900
Paul Bakker5121ce52009-01-03 21:22:43 +00001901 memset( T->p, 0, T->n * ciL );
1902
1903 d = T->p;
1904 n = N->n;
1905 m = ( B->n < n ) ? B->n : n;
1906
1907 for( i = 0; i < n; i++ )
1908 {
1909 /*
1910 * T = (T + u0*B + u1*N) / 2^biL
1911 */
1912 u0 = A->p[i];
1913 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1914
1915 mpi_mul_hlp( m, B->p, d, u0 );
1916 mpi_mul_hlp( n, N->p, d, u1 );
1917
1918 *d++ = u0; d[n + 1] = 0;
1919 }
1920
Paul Bakker66d5d072014-06-17 16:39:18 +02001921 memcpy( A->p, d, ( n + 1 ) * ciL );
Paul Bakker5121ce52009-01-03 21:22:43 +00001922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001924 mpi_sub_hlp( n, N->p, A->p );
1925 else
1926 /* prevent timing attacks */
1927 mpi_sub_hlp( n, A->p, T->p );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001928
1929 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001930}
1931
1932/*
1933 * Montgomery reduction: A = A * R^-1 mod N
1934 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001935static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
1936 mbedtls_mpi_uint mm, const mbedtls_mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001937{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 mbedtls_mpi_uint z = 1;
1939 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001940
Paul Bakker8ddb6452013-02-27 14:56:33 +01001941 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001942 U.p = &z;
1943
Nicholas Wilson91c68a52016-04-13 11:44:29 +01001944 return( mpi_montmul( A, &U, N, mm, T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001945}
1946
1947/*
1948 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1949 */
Hanno Becker73d7d792018-12-11 10:35:51 +00001950int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
1951 const mbedtls_mpi *E, const mbedtls_mpi *N,
1952 mbedtls_mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001953{
Paul Bakker23986e52011-04-24 08:57:21 +00001954 int ret;
1955 size_t wbits, wsize, one = 1;
1956 size_t i, j, nblimbs;
1957 size_t bufsize, nbits;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001958 mbedtls_mpi_uint ei, mm, state;
1959 mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001960 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001961
Hanno Becker73d7d792018-12-11 10:35:51 +00001962 MPI_VALIDATE_RET( X != NULL );
1963 MPI_VALIDATE_RET( A != NULL );
1964 MPI_VALIDATE_RET( E != NULL );
1965 MPI_VALIDATE_RET( N != NULL );
1966
Hanno Becker8d1dd1b2017-09-28 11:02:24 +01001967 if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001970 if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1971 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakkerf6198c12012-05-16 08:02:29 +00001972
1973 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001974 * Init temps and window size
1975 */
1976 mpi_montg_init( &mm, N );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1978 mbedtls_mpi_init( &Apos );
Paul Bakker5121ce52009-01-03 21:22:43 +00001979 memset( W, 0, sizeof( W ) );
1980
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001981 i = mbedtls_mpi_bitlen( E );
Paul Bakker5121ce52009-01-03 21:22:43 +00001982
1983 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1984 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1985
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001986#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001987 if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1988 wsize = MBEDTLS_MPI_WINDOW_SIZE;
Peter Kolbusb83d41d2018-12-11 14:01:44 -06001989#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001990
Paul Bakker5121ce52009-01-03 21:22:43 +00001991 j = N->n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1993 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
1994 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001995
1996 /*
Paul Bakker50546922012-05-19 08:40:49 +00001997 * Compensate for negative A (and correct at the end)
1998 */
1999 neg = ( A->s == -1 );
Paul Bakker50546922012-05-19 08:40:49 +00002000 if( neg )
2001 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002002 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
Paul Bakker50546922012-05-19 08:40:49 +00002003 Apos.s = 1;
2004 A = &Apos;
2005 }
2006
2007 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002008 * If 1st call, pre-compute R^2 mod N
2009 */
2010 if( _RR == NULL || _RR->p == NULL )
2011 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002012 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2013 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2014 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002015
2016 if( _RR != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017 memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002018 }
2019 else
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 /*
2023 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2024 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2026 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
Paul Bakkerc2024f42014-01-23 20:38:35 +01002027 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002028 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002029
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002030 MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002031
2032 /*
2033 * X = R^2 * R^-1 mod N = R mod N
2034 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002036 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002037
2038 if( wsize > 1 )
2039 {
2040 /*
2041 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2042 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002043 j = one << ( wsize - 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2046 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002047
2048 for( i = 0; i < wsize - 1; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002049 MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
Paul Bakker0d7702c2013-10-29 16:18:35 +01002050
Paul Bakker5121ce52009-01-03 21:22:43 +00002051 /*
2052 * W[i] = W[i - 1] * W[1]
2053 */
Paul Bakker66d5d072014-06-17 16:39:18 +02002054 for( i = j + 1; i < ( one << wsize ); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002055 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002056 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2057 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002058
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002059 MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002060 }
2061 }
2062
2063 nblimbs = E->n;
2064 bufsize = 0;
2065 nbits = 0;
2066 wbits = 0;
2067 state = 0;
2068
2069 while( 1 )
2070 {
2071 if( bufsize == 0 )
2072 {
Paul Bakker0d7702c2013-10-29 16:18:35 +01002073 if( nblimbs == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002074 break;
2075
Paul Bakker0d7702c2013-10-29 16:18:35 +01002076 nblimbs--;
2077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 bufsize = sizeof( mbedtls_mpi_uint ) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002079 }
2080
2081 bufsize--;
2082
2083 ei = (E->p[nblimbs] >> bufsize) & 1;
2084
2085 /*
2086 * skip leading 0s
2087 */
2088 if( ei == 0 && state == 0 )
2089 continue;
2090
2091 if( ei == 0 && state == 1 )
2092 {
2093 /*
2094 * out of window, square X
2095 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002096 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002097 continue;
2098 }
2099
2100 /*
2101 * add ei to current window
2102 */
2103 state = 2;
2104
2105 nbits++;
Paul Bakker66d5d072014-06-17 16:39:18 +02002106 wbits |= ( ei << ( wsize - nbits ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
2108 if( nbits == wsize )
2109 {
2110 /*
2111 * X = X^wsize R^-1 mod N
2112 */
2113 for( i = 0; i < wsize; i++ )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002114 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002115
2116 /*
2117 * X = X * W[wbits] R^-1 mod N
2118 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002119 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002120
2121 state--;
2122 nbits = 0;
2123 wbits = 0;
2124 }
2125 }
2126
2127 /*
2128 * process the remaining bits
2129 */
2130 for( i = 0; i < nbits; i++ )
2131 {
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002132 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002133
2134 wbits <<= 1;
2135
Paul Bakker66d5d072014-06-17 16:39:18 +02002136 if( ( wbits & ( one << wsize ) ) != 0 )
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002137 MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002138 }
2139
2140 /*
2141 * X = A^E * R * R^-1 mod N = A^E mod N
2142 */
Nicholas Wilson91c68a52016-04-13 11:44:29 +01002143 MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002144
Hanno Beckera4af1c42017-04-18 09:07:45 +01002145 if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
Paul Bakkerf6198c12012-05-16 08:02:29 +00002146 {
2147 X->s = -1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002148 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
Paul Bakkerf6198c12012-05-16 08:02:29 +00002149 }
2150
Paul Bakker5121ce52009-01-03 21:22:43 +00002151cleanup:
2152
Paul Bakker66d5d072014-06-17 16:39:18 +02002153 for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 mbedtls_mpi_free( &W[i] );
Paul Bakker5121ce52009-01-03 21:22:43 +00002155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002156 mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
Paul Bakker6c591fa2011-05-05 11:49:20 +00002157
Paul Bakker75a28602014-03-31 12:08:17 +02002158 if( _RR == NULL || _RR->p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002160
2161 return( ret );
2162}
2163
Paul Bakker5121ce52009-01-03 21:22:43 +00002164/*
2165 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2166 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002167int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00002168{
Paul Bakker23986e52011-04-24 08:57:21 +00002169 int ret;
2170 size_t lz, lzt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 mbedtls_mpi TG, TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002172
Hanno Becker73d7d792018-12-11 10:35:51 +00002173 MPI_VALIDATE_RET( G != NULL );
2174 MPI_VALIDATE_RET( A != NULL );
2175 MPI_VALIDATE_RET( B != NULL );
2176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002179 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2180 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 lz = mbedtls_mpi_lsb( &TA );
2183 lzt = mbedtls_mpi_lsb( &TB );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002184
Paul Bakker66d5d072014-06-17 16:39:18 +02002185 if( lzt < lz )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002186 lz = lzt;
2187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
2189 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002190
Paul Bakker5121ce52009-01-03 21:22:43 +00002191 TA.s = TB.s = 1;
2192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002193 while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002194 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2196 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002199 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2201 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002202 }
2203 else
2204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002205 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2206 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002207 }
2208 }
2209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002210 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2211 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002212
2213cleanup:
2214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
Paul Bakker5121ce52009-01-03 21:22:43 +00002216
2217 return( ret );
2218}
2219
Paul Bakker33dc46b2014-04-30 16:11:39 +02002220/*
2221 * Fill X with size bytes of random.
2222 *
2223 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002224 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002225 * deterministic, eg for tests).
2226 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002228 int (*f_rng)(void *, unsigned char *, size_t),
2229 void *p_rng )
Paul Bakker287781a2011-03-26 13:18:49 +00002230{
Paul Bakker23986e52011-04-24 08:57:21 +00002231 int ret;
Hanno Becker6dab6202019-01-02 16:42:29 +00002232 size_t const limbs = CHARS_TO_LIMBS( size );
Hanno Beckerda1655a2017-10-18 14:21:44 +01002233 size_t const overhead = ( limbs * ciL ) - size;
2234 unsigned char *Xp;
2235
Hanno Becker8ce11a32018-12-19 16:18:52 +00002236 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002237 MPI_VALIDATE_RET( f_rng != NULL );
Paul Bakker33dc46b2014-04-30 16:11:39 +02002238
Hanno Beckerda1655a2017-10-18 14:21:44 +01002239 /* Ensure that target MPI has exactly the necessary number of limbs */
2240 if( X->n != limbs )
2241 {
2242 mbedtls_mpi_free( X );
2243 mbedtls_mpi_init( X );
2244 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2245 }
2246 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Paul Bakker287781a2011-03-26 13:18:49 +00002247
Hanno Beckerda1655a2017-10-18 14:21:44 +01002248 Xp = (unsigned char*) X->p;
2249 f_rng( p_rng, Xp + overhead, size );
2250
Hanno Becker2be8a552018-10-25 12:40:09 +01002251 mpi_bigendian_to_host( X->p, limbs );
Paul Bakker287781a2011-03-26 13:18:49 +00002252
2253cleanup:
2254 return( ret );
2255}
2256
Paul Bakker5121ce52009-01-03 21:22:43 +00002257/*
2258 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2259 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00002261{
2262 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002263 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Hanno Becker73d7d792018-12-11 10:35:51 +00002264 MPI_VALIDATE_RET( X != NULL );
2265 MPI_VALIDATE_RET( A != NULL );
2266 MPI_VALIDATE_RET( N != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +00002267
Hanno Becker4bcb4912017-04-18 15:49:39 +01002268 if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
2272 mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
2273 mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002277 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002278 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002279 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002280 goto cleanup;
2281 }
2282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2284 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2285 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2286 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2289 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2290 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2291 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002292
2293 do
2294 {
2295 while( ( TU.p[0] & 1 ) == 0 )
2296 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002297 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002298
2299 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2300 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2302 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002303 }
2304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002305 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2306 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002307 }
2308
2309 while( ( TV.p[0] & 1 ) == 0 )
2310 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002312
2313 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2314 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002315 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2316 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002317 }
2318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002319 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2320 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002321 }
2322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002323 if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002324 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2326 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2327 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002328 }
2329 else
2330 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002331 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2332 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2333 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002334 }
2335 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336 while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2339 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2342 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002345
2346cleanup:
2347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348 mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2349 mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2350 mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002351
2352 return( ret );
2353}
2354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002356
Paul Bakker5121ce52009-01-03 21:22:43 +00002357static const int small_prime[] =
2358{
2359 3, 5, 7, 11, 13, 17, 19, 23,
2360 29, 31, 37, 41, 43, 47, 53, 59,
2361 61, 67, 71, 73, 79, 83, 89, 97,
2362 101, 103, 107, 109, 113, 127, 131, 137,
2363 139, 149, 151, 157, 163, 167, 173, 179,
2364 181, 191, 193, 197, 199, 211, 223, 227,
2365 229, 233, 239, 241, 251, 257, 263, 269,
2366 271, 277, 281, 283, 293, 307, 311, 313,
2367 317, 331, 337, 347, 349, 353, 359, 367,
2368 373, 379, 383, 389, 397, 401, 409, 419,
2369 421, 431, 433, 439, 443, 449, 457, 461,
2370 463, 467, 479, 487, 491, 499, 503, 509,
2371 521, 523, 541, 547, 557, 563, 569, 571,
2372 577, 587, 593, 599, 601, 607, 613, 617,
2373 619, 631, 641, 643, 647, 653, 659, 661,
2374 673, 677, 683, 691, 701, 709, 719, 727,
2375 733, 739, 743, 751, 757, 761, 769, 773,
2376 787, 797, 809, 811, 821, 823, 827, 829,
2377 839, 853, 857, 859, 863, 877, 881, 883,
2378 887, 907, 911, 919, 929, 937, 941, 947,
2379 953, 967, 971, 977, 983, 991, 997, -103
2380};
2381
2382/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002383 * Small divisors test (X must be positive)
2384 *
2385 * Return values:
2386 * 0: no small factor (possible prime, more tests needed)
2387 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002389 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002390 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391static int mpi_check_small_factors( const mbedtls_mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +00002392{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002393 int ret = 0;
2394 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002396
Paul Bakker5121ce52009-01-03 21:22:43 +00002397 if( ( X->p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002398 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002399
2400 for( i = 0; small_prime[i] > 0; i++ )
2401 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002403 return( 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002406
2407 if( r == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00002409 }
2410
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002411cleanup:
2412 return( ret );
2413}
2414
2415/*
2416 * Miller-Rabin pseudo-primality test (HAC 4.24)
2417 */
Janos Follathda31fa12018-09-03 14:45:23 +01002418static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002419 int (*f_rng)(void *, unsigned char *, size_t),
2420 void *p_rng )
2421{
Pascal Junodb99183d2015-03-11 16:49:45 +01002422 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002423 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002425
Hanno Becker8ce11a32018-12-19 16:18:52 +00002426 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002427 MPI_VALIDATE_RET( f_rng != NULL );
2428
2429 mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R );
2430 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002431 mbedtls_mpi_init( &RR );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002432
Paul Bakker5121ce52009-01-03 21:22:43 +00002433 /*
2434 * W = |X| - 1
2435 * R = W >> lsb( W )
2436 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002437 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2438 s = mbedtls_mpi_lsb( &W );
2439 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2440 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002441
Janos Follathda31fa12018-09-03 14:45:23 +01002442 for( i = 0; i < rounds; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +00002443 {
2444 /*
2445 * pick a random A, 1 < A < |X| - 1
2446 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002447 count = 0;
2448 do {
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002449 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
Pascal Junodb99183d2015-03-11 16:49:45 +01002450
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002451 j = mbedtls_mpi_bitlen( &A );
2452 k = mbedtls_mpi_bitlen( &W );
Pascal Junodb99183d2015-03-11 16:49:45 +01002453 if (j > k) {
Darryl Greene3f95ed2018-10-02 13:21:35 +01002454 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002455 }
2456
2457 if (count++ > 30) {
Jens Wiklanderdfd447e2019-01-17 13:30:57 +01002458 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2459 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002460 }
2461
Manuel Pégourié-Gonnard53c76c02015-04-17 20:15:36 +02002462 } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2463 mbedtls_mpi_cmp_int( &A, 1 ) <= 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00002464
2465 /*
2466 * A = A^R mod |X|
2467 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002468 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002469
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002470 if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2471 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002472 continue;
2473
2474 j = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002476 {
2477 /*
2478 * A = A * A mod |X|
2479 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002480 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2481 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002484 break;
2485
2486 j++;
2487 }
2488
2489 /*
2490 * not prime if A != |X| - 1 or A == 1
2491 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2493 mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002494 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002496 break;
2497 }
2498 }
2499
2500cleanup:
Hanno Becker73d7d792018-12-11 10:35:51 +00002501 mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
2502 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 mbedtls_mpi_free( &RR );
Paul Bakker5121ce52009-01-03 21:22:43 +00002504
2505 return( ret );
2506}
2507
2508/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002509 * Pseudo-primality test: small factors, then Miller-Rabin
2510 */
Janos Follatha0b67c22018-09-18 14:48:23 +01002511int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2512 int (*f_rng)(void *, unsigned char *, size_t),
2513 void *p_rng )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002514{
2515 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002516 mbedtls_mpi XX;
Hanno Becker8ce11a32018-12-19 16:18:52 +00002517 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002518 MPI_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002519
2520 XX.s = 1;
2521 XX.n = X->n;
2522 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2525 mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2526 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002528 if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002529 return( 0 );
2530
2531 if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2532 {
2533 if( ret == 1 )
2534 return( 0 );
2535
2536 return( ret );
2537 }
2538
Janos Follathda31fa12018-09-03 14:45:23 +01002539 return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
Janos Follathf301d232018-08-14 13:34:01 +01002540}
2541
Janos Follatha0b67c22018-09-18 14:48:23 +01002542#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002543/*
2544 * Pseudo-primality test, error probability 2^-80
2545 */
2546int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2547 int (*f_rng)(void *, unsigned char *, size_t),
2548 void *p_rng )
2549{
Hanno Becker8ce11a32018-12-19 16:18:52 +00002550 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002551 MPI_VALIDATE_RET( f_rng != NULL );
2552
Janos Follatha0b67c22018-09-18 14:48:23 +01002553 /*
2554 * In the past our key generation aimed for an error rate of at most
2555 * 2^-80. Since this function is deprecated, aim for the same certainty
2556 * here as well.
2557 */
Hanno Becker73d7d792018-12-11 10:35:51 +00002558 return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002559}
Janos Follatha0b67c22018-09-18 14:48:23 +01002560#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002561
2562/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002563 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002564 *
Janos Follathf301d232018-08-14 13:34:01 +01002565 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2566 * be either 1024 bits or 1536 bits long, and flags must contain
2567 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002568 */
Janos Follath7c025a92018-08-14 11:08:41 +01002569int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
Paul Bakkera3d195c2011-11-27 21:07:34 +00002570 int (*f_rng)(void *, unsigned char *, size_t),
2571 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +00002572{
Jethro Beekman66689272018-02-14 19:24:10 -08002573#ifdef MBEDTLS_HAVE_INT64
2574// ceil(2^63.5)
2575#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2576#else
2577// ceil(2^31.5)
2578#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2579#endif
2580 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002581 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002582 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002583 mbedtls_mpi_uint r;
2584 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002585
Hanno Becker8ce11a32018-12-19 16:18:52 +00002586 MPI_VALIDATE_RET( X != NULL );
Hanno Becker73d7d792018-12-11 10:35:51 +00002587 MPI_VALIDATE_RET( f_rng != NULL );
2588
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589 if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2590 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00002591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 mbedtls_mpi_init( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002593
2594 n = BITS_TO_LIMBS( nbits );
2595
Janos Follathda31fa12018-09-03 14:45:23 +01002596 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
2597 {
2598 /*
2599 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2600 */
2601 rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
2602 ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
2603 ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
2604 }
2605 else
2606 {
2607 /*
2608 * 2^-100 error probability, number of rounds computed based on HAC,
2609 * fact 4.48
2610 */
2611 rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
2612 ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
2613 ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
2614 ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
2615 }
2616
Jethro Beekman66689272018-02-14 19:24:10 -08002617 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002618 {
Jethro Beekman66689272018-02-14 19:24:10 -08002619 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2620 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
2621 if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2622
2623 k = n * biL;
2624 if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2625 X->p[0] |= 1;
2626
Janos Follath7c025a92018-08-14 11:08:41 +01002627 if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002628 {
Janos Follatha0b67c22018-09-18 14:48:23 +01002629 ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
Jethro Beekman66689272018-02-14 19:24:10 -08002630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002631 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00002632 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002633 }
Jethro Beekman66689272018-02-14 19:24:10 -08002634 else
Paul Bakker5121ce52009-01-03 21:22:43 +00002635 {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002636 /*
Jethro Beekman66689272018-02-14 19:24:10 -08002637 * An necessary condition for Y and X = 2Y + 1 to be prime
2638 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2639 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002640 */
Jethro Beekman66689272018-02-14 19:24:10 -08002641
2642 X->p[0] |= 2;
2643
2644 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2645 if( r == 0 )
2646 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2647 else if( r == 1 )
2648 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2649
2650 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2651 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2652 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2653
2654 while( 1 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002655 {
Jethro Beekman66689272018-02-14 19:24:10 -08002656 /*
2657 * First, check small factors for X and Y
2658 * before doing Miller-Rabin on any of them
2659 */
2660 if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
2661 ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002662 ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002663 == 0 &&
Janos Follathda31fa12018-09-03 14:45:23 +01002664 ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
Janos Follathf301d232018-08-14 13:34:01 +01002665 == 0 )
Jethro Beekman66689272018-02-14 19:24:10 -08002666 goto cleanup;
2667
2668 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2669 goto cleanup;
2670
2671 /*
2672 * Next candidates. We want to preserve Y = (X-1) / 2 and
2673 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2674 * so up Y by 6 and X by 12.
2675 */
2676 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) );
2677 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002678 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002679 }
2680 }
2681
2682cleanup:
2683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 mbedtls_mpi_free( &Y );
Paul Bakker5121ce52009-01-03 21:22:43 +00002685
2686 return( ret );
2687}
2688
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002689#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002692
Paul Bakker23986e52011-04-24 08:57:21 +00002693#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002694
2695static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2696{
2697 { 693, 609, 21 },
2698 { 1764, 868, 28 },
2699 { 768454923, 542167814, 1 }
2700};
2701
Paul Bakker5121ce52009-01-03 21:22:43 +00002702/*
2703 * Checkup routine
2704 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002705int mbedtls_mpi_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00002706{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002707 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002708 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002709
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002710 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2711 mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002712
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002713 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002714 "EFE021C2645FD1DC586E69184AF4A31E" \
2715 "D5F53E93B5F123FA41680867BA110131" \
2716 "944FE7952E2517337780CB0DB80E61AA" \
2717 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002719 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002720 "B2E7EFD37075B9F03FF989C7C5051C20" \
2721 "34D2A323810251127E7BF8625A4F49A5" \
2722 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2723 "5B5C25763222FEFCCFC38B832366C29E" ) );
2724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002725 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002726 "0066A198186C18C10B2F5ED9B522752A" \
2727 "9830B69916E535C8F047518A889A43A5" \
2728 "94B6BED27A168D31D4A52F88925AA8F5" ) );
2729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002730 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002732 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002733 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2734 "9E857EA95A03512E2BAE7391688D264A" \
2735 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2736 "8001B72E848A38CAE1C65F78E56ABDEF" \
2737 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2738 "ECF677152EF804370C1A305CAF3B5BF1" \
2739 "30879B56C61DE584A0F53A2447A51E" ) );
2740
2741 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002742 mbedtls_printf( " MPI test #1 (mul_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002743
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002744 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002745 {
2746 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002748
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002749 ret = 1;
2750 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002751 }
2752
2753 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002757
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002758 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002759 "256567336059E52CAE22925474705F39A94" ) );
2760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002761 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002762 "6613F26162223DF488E9CD48CC132C7A" \
2763 "0AC93C701B001B092E4E5B9F73BCD27B" \
2764 "9EE50D0657C77F374E903CDFA4C642" ) );
2765
2766 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002767 mbedtls_printf( " MPI test #2 (div_mpi): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002769 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2770 mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002771 {
2772 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002773 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002774
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002775 ret = 1;
2776 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002777 }
2778
2779 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002781
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002782 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002783
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002784 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002785 "36E139AEA55215609D2816998ED020BB" \
2786 "BD96C37890F65171D948E9BC7CBAA4D9" \
2787 "325D24D6A3C12710F10A09FA08AB87" ) );
2788
2789 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002790 mbedtls_printf( " MPI test #3 (exp_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002792 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002793 {
2794 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002796
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002797 ret = 1;
2798 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002799 }
2800
2801 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002802 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002804 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00002805
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002806 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
Paul Bakker5121ce52009-01-03 21:22:43 +00002807 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2808 "C3DBA76456363A10869622EAC2DD84EC" \
2809 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2810
2811 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002812 mbedtls_printf( " MPI test #4 (inv_mod): " );
Paul Bakker5121ce52009-01-03 21:22:43 +00002813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002814 if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00002815 {
2816 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002818
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002819 ret = 1;
2820 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002821 }
2822
2823 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002824 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002825
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002826 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002827 mbedtls_printf( " MPI test #5 (simple gcd): " );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002828
Paul Bakker66d5d072014-06-17 16:39:18 +02002829 for( i = 0; i < GCD_PAIR_COUNT; i++ )
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002830 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002831 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2832 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002834 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002836 if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002837 {
2838 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002839 mbedtls_printf( "failed at %d\n", i );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002840
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002841 ret = 1;
2842 goto cleanup;
2843 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002844 }
2845
2846 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002847 mbedtls_printf( "passed\n" );
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002848
Paul Bakker5121ce52009-01-03 21:22:43 +00002849cleanup:
2850
2851 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002852 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00002853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002854 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2855 mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
Paul Bakker5121ce52009-01-03 21:22:43 +00002856
2857 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002858 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00002859
2860 return( ret );
2861}
2862
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002863#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002864
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002865#endif /* MBEDTLS_BIGNUM_C */